☰

πŸ› οΈ PopControl

Popmundo scriptlerini tek panelden yânetmenizi sağlayan merkezi modül

이 슀크립트λ₯Ό μ„€μΉ˜ν•˜λ €λ©΄ Tampermonkey, Greasemonkey λ˜λŠ” Violentmonkey와 같은 ν™•μž₯ ν”„λ‘œκ·Έλž¨μ΄ ν•„μš”ν•©λ‹ˆλ‹€.

이 슀크립트λ₯Ό μ„€μΉ˜ν•˜λ €λ©΄ Tampermonkey와 같은 ν™•μž₯ ν”„λ‘œκ·Έλž¨μ„ μ„€μΉ˜ν•΄μ•Ό ν•©λ‹ˆλ‹€.

이 슀크립트λ₯Ό μ„€μΉ˜ν•˜λ €λ©΄ Tampermonkey λ˜λŠ” Violentmonkey와 같은 ν™•μž₯ ν”„λ‘œκ·Έλž¨μ΄ ν•„μš”ν•©λ‹ˆλ‹€.

이 슀크립트λ₯Ό μ„€μΉ˜ν•˜λ €λ©΄ Tampermonkey λ˜λŠ” Userscripts와 같은 ν™•μž₯ ν”„λ‘œκ·Έλž¨μ΄ ν•„μš”ν•©λ‹ˆλ‹€.

이 슀크립트λ₯Ό μ„€μΉ˜ν•˜λ €λ©΄ Tampermonkey와 같은 ν™•μž₯ ν”„λ‘œκ·Έλž¨μ΄ ν•„μš”ν•©λ‹ˆλ‹€.

이 슀크립트λ₯Ό μ„€μΉ˜ν•˜λ €λ©΄ μœ μ € 슀크립트 κ΄€λ¦¬μž ν™•μž₯ ν”„λ‘œκ·Έλž¨μ΄ ν•„μš”ν•©λ‹ˆλ‹€.

(이미 μœ μ € 슀크립트 κ΄€λ¦¬μžκ°€ μ„€μΉ˜λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. μ„€μΉ˜λ₯Ό μ§„ν–‰ν•©λ‹ˆλ‹€!)

이 μŠ€νƒ€μΌμ„ μ„€μΉ˜ν•˜λ €λ©΄ Stylus와 같은 ν™•μž₯ ν”„λ‘œκ·Έλž¨μ΄ ν•„μš”ν•©λ‹ˆλ‹€.

이 μŠ€νƒ€μΌμ„ μ„€μΉ˜ν•˜λ €λ©΄ Stylus와 같은 ν™•μž₯ ν”„λ‘œκ·Έλž¨μ΄ ν•„μš”ν•©λ‹ˆλ‹€.

이 μŠ€νƒ€μΌμ„ μ„€μΉ˜ν•˜λ €λ©΄ Stylus와 같은 ν™•μž₯ ν”„λ‘œκ·Έλž¨μ΄ ν•„μš”ν•©λ‹ˆλ‹€.

이 μŠ€νƒ€μΌμ„ μ„€μΉ˜ν•˜λ €λ©΄ μœ μ € μŠ€νƒ€μΌ κ΄€λ¦¬μž ν™•μž₯ ν”„λ‘œκ·Έλž¨μ΄ ν•„μš”ν•©λ‹ˆλ‹€.

이 μŠ€νƒ€μΌμ„ μ„€μΉ˜ν•˜λ €λ©΄ μœ μ € μŠ€νƒ€μΌ κ΄€λ¦¬μž ν™•μž₯ ν”„λ‘œκ·Έλž¨μ΄ ν•„μš”ν•©λ‹ˆλ‹€.

이 μŠ€νƒ€μΌμ„ μ„€μΉ˜ν•˜λ €λ©΄ μœ μ € μŠ€νƒ€μΌ κ΄€λ¦¬μž ν™•μž₯ ν”„λ‘œκ·Έλž¨μ΄ ν•„μš”ν•©λ‹ˆλ‹€.

(이미 μœ μ € μŠ€νƒ€μΌ κ΄€λ¦¬μžκ°€ μ„€μΉ˜λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. μ„€μΉ˜λ₯Ό μ§„ν–‰ν•©λ‹ˆλ‹€!)

// ==UserScript==
// @name        πŸ› οΈ PopControl
// @name:tr     πŸ› οΈ PopControl
// @name:en     πŸ› οΈ PopControl
// @name:pt-BR  πŸ› οΈ PopControl
// @namespace   popmundo.popcontrol
// @version     2.3
// @description Popmundo scriptlerini tek panelden yânetmenizi sağlayan merkezi modül
// @description:tr Popmundo scriptlerini tek panelden yânetmenizi sağlayan merkezi modül
// @description:tr Popmundo scriptlerini tek panelden yânetmenizi sağlayan merkezi modül
// @description:en Central hub to manage all Popmundo scripts from one panel
// @description:pt-BR MΓ³dulo central para gerenciar todos os scripts do Popmundo
// @author      luke-james-gibson
// @license     MIT
// @match       https://*.popmundo.com/*
// @run-at      document-end
// @grant       unsafeWindow
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_deleteValue
// ==/UserScript==

(function () {
'use strict';

// ─── CORE UTILS ────────────────────────────────────────────────────────────────
const DEBUG = localStorage.getItem('ppc_debug') === 'true';
const log = (...args) => DEBUG && console.log('[PopControl]', ...args);

const CK = {
    get: k => { const m = document.cookie.match(new RegExp('(?:^|; )' + k + '=([^;]*)')); return m ? decodeURIComponent(m[1]) : null; },
    set: (k, v) => { document.cookie = `${k}=${encodeURIComponent(v)};domain=.popmundo.com;path=/;max-age=31536000`; }
};

const LS = {
    get: (k, d) => { try { const v = localStorage.getItem(k); return v !== null ? JSON.parse(v) : d; } catch { return d; } },
    set: (k, v) => { try { localStorage.setItem(k, JSON.stringify(v)); } catch {} },
};

const mk = (tag, cls, txt) => { 
    const e = document.createElement(tag); 
    if (cls) e.className = cls; 
    if (txt != null) e.textContent = txt; 
    return e; 
};

const mkB = (txt, cls, fn) => Object.assign(mk('button', cls, txt), { onclick: fn, type: 'button' });

// ─── LANGUAGE & STRINGS ────────────────────────────────────────────────────────
const LANG = CK.get('ppm_lang') || 'TR';
const _D = (tr, en, pt) => ({ TR: tr, EN: en, PT: pt }[LANG] || tr);
const STR = {
    posLabel:    _D('Konum',            'Position',          'PosiΓ§Γ£o'),
    posBottom:   _D('⬇ Alt',           '⬇ Bottom',         '⬇ Baixo'),
    posTop:      _D('⬆ Üst',           '⬆ Top',            '⬆ Cima'),
    posLeft:     _D('β—€ Sol',           'β—€ Left',           'β—€ Esquerda'),
    posRight:    _D('β–Ά Sağ',           'β–Ά Right',          'β–Ά Direita'),
    langLabel:   _D('Dil',              'Language',          'Idioma'),
    scripts:     _D('Scriptler',        'Scripts',           'Scripts'),
    order:       _D('SΔ±ra',             'Order',             'Ordem'),
    orderHint:   _D('Barda butonlarΔ± sΓΌrΓΌkleyip bΔ±rakarak sΔ±ralayabilirsiniz.',
                    'Drag & drop buttons on the bar to reorder.',
                    'Arraste os botΓ΅es na barra para reordenar.'),
    colorBar:    _D('Bar Rengi',        'Bar Color',         'Cor da Barra'),
    colorText:   _D('YazΔ± Rengi',       'Text Color',        'Cor do Texto'),
    shortcut:    _D('Paneli AΓ§/Kapat - Alt + P', 'Toggle Panel - Alt + P', 'Alternar Painel - Alt + P'),
    close:       _D('Kapat',            'Close',             'Fechar'),
};

// ─── STORAGE & STATE ───────────────────────────────────────────────────────────
const _getEnabledObj = () => { try { return JSON.parse(GM_getValue('ppc_enabled', '{}')); } catch { return {}; } };
const _saveEnabledObj = o => GM_setValue('ppc_enabled', JSON.stringify(o));
const _isEnabled = id => _getEnabledObj()[id] !== false;
const _setEnabled = (id, v) => { const e = _getEnabledObj(); e[id] = v; _saveEnabledObj(e); };

const _getPos = () => GM_getValue('ppc_pos', 'bottom');
const _setPos = p => GM_setValue('ppc_pos', p);

const _getOrder = () => { try { return JSON.parse(GM_getValue('ppc_order', '[]')); } catch { return []; } };
const _setOrder = o => GM_setValue('ppc_order', JSON.stringify(o));

const _getColBg = () => GM_getValue('ppc_bg', '#f5f0ff');
const _getColFg = () => GM_getValue('ppc_fg', '#5a30a0');
const _setColBg = v => GM_setValue('ppc_bg', v);
const _setColFg = v => GM_setValue('ppc_fg', v);

const _registry = [];
const _plugins = [];
let _collapsed = false;
const _setCollapsed = v => { _collapsed = v; GM_setValue('ppc_collapsed', v); };

function _sortedRegistry() {
    const order = _getOrder();
    if (!order.length) return [..._registry];
    const res = [];
    order.forEach(id => { const e = _registry.find(r => r.id === id); if (e) res.push(e); });
    _registry.forEach(e => { if (!res.includes(e)) res.push(e); });
    return res;
}

// ─── COLORS & GEOMETRY ─────────────────────────────────────────────────────────
const PRESET_BG = ['#f5f0ff','#fff','#1a1035','#2c3e50','#0d1117','#fff0f5','#f0fff4','#f0f8ff','#fffde7','#f3e5f5'];
const PRESET_FG = ['#5a30a0','#6f42c1','#fff','#ecf0f1','#ccc','#e83e8c','#28a745','#007bff','#fd7e14','#ffc107'];

function _mainGeom() {
    const m = document.getElementById('ppm-main') || document.getElementById('ppm-footer');
    if (!m) return { left: 0, width: window.innerWidth, right: window.innerWidth };
    const r = m.getBoundingClientRect();
    return { left: Math.round(r.left), width: m.offsetWidth, right: Math.round(r.right) };
}

function _applyPush(size) {
    document.getElementById('ppc-push')?.remove();
    if (!size) return;
    const s = document.createElement('style'); s.id = 'ppc-push';
    s.textContent = `#ppm-main{margin-top:${65 + size}px!important}#character-tools,#header-logo{margin-top:${size}px!important}`;
    document.head.appendChild(s);
}

function _positionFab(fab) {
    const footer = document.getElementById('ppm-footer');
    if (footer && window.innerWidth >= 768) {
        const r = footer.getBoundingClientRect();
        fab.style.bottom = (window.innerHeight - r.bottom + 8) + 'px';
        fab.style.right = (window.innerWidth - r.right + 8) + 'px';
    }
}

function _shadeHex(hex, amt) {
    try {
        let h = hex.replace('#','');
        if (h.length === 3) h = h[0]+h[0]+h[1]+h[1]+h[2]+h[2];
        const r = Math.max(0,Math.min(255,parseInt(h.slice(0,2),16)+amt));
        const g = Math.max(0,Math.min(255,parseInt(h.slice(2,4),16)+amt));
        const b = Math.max(0,Math.min(255,parseInt(h.slice(4,6),16)+amt));
        return '#'+[r,g,b].map(x=>x.toString(16).padStart(2,'0')).join('');
    } catch { return hex; }
}
            // ─── UI BUILDING ───────────────────────────────────────────────────────────────
let _dragId = null;
let _rebuildTimer = null;

const _queueRebuild = () => { 
    clearTimeout(_rebuildTimer); 
    _rebuildTimer = setTimeout(() => {
        log('Rebuilding UI...');
        _rebuild();
    }, 50); 
};

function _rebuild() {
    document.getElementById('ppc-bar')?.remove();
    document.getElementById('ppc-fab')?.remove();
    document.getElementById('ppc-push')?.remove();

    const pos = _getPos();
    const g = _mainGeom();
    const mob = window.innerWidth < 768;
    const vert = pos === 'left' || pos === 'right';
    const BG = _getColBg();
    const BDR = '1px solid ' + _shadeHex(BG, -25);
    const FG = _getColFg();
    const SZ = 46;
    const sortedReg = _sortedRegistry();

    // FAB (collapsed)
    const fab = mk('button'); fab.id = 'ppc-fab'; fab.type = 'button';
    fab.textContent = 'βš™οΈ';
    fab.style.cssText = [
        'position:fixed;bottom:16px;right:16px;z-index:9996',
        `background:${BG};border:${BDR};border-radius:50%`,
        `width:${SZ}px;height:${SZ}px;font-size:20px;cursor:pointer`,
        'box-shadow:0 2px 10px rgba(0,0,0,.25);display:none;align-items:center;justify-content:center',
        'font-family:inherit'
    ].join(';');
    fab.onclick = () => { _setCollapsed(false); _rebuild(); };
    document.body.appendChild(fab);

    // Main bar
    const bar = mk('div'); bar.id = 'ppc-bar';

    if (vert) {
        const side = pos === 'left' ? `left:${mob ? 0 : Math.max(0, g.left - SZ)}px` : `right:${mob ? 0 : Math.max(0, window.innerWidth - g.right - SZ)}px`;
        const shadow = pos === 'left' ? '2px 0 8px rgba(0,0,0,.12)' : '-2px 0 8px rgba(0,0,0,.12)';
        bar.style.cssText = [
            `position:fixed;${side};top:65px;bottom:0;z-index:9990`,
            `background:${BG};border:${BDR};box-shadow:${shadow}`,
            `border-radius:${pos==='left'?'0 8px 8px 0':'8px 0 0 8px'}`,
            `width:${SZ}px;overflow-y:auto;overflow-x:hidden;scrollbar-width:none`,
            `display:flex;flex-direction:column;align-items:center;padding:4px 0;gap:0`,
        ].join(';');
    } else {
        const side = pos === 'bottom' ? 'bottom:0' : 'top:0';
        const xPos = mob ? 'left:0;right:0' : `left:${g.left}px;width:${g.width}px`;
        const zIdx = pos === 'top' ? 99990 : 9990;
        const shadow = pos === 'bottom' ? '0 -2px 8px rgba(0,0,0,.12)' : '0 2px 8px rgba(0,0,0,.12)';
        bar.style.cssText = [
            `position:fixed;${xPos};${side};z-index:${zIdx}`,
            `background:${BG};border:${BDR};box-shadow:${shadow}`,
            `border-radius:${pos==='bottom'?'8px 8px 0 0':'0 0 8px 8px'}`,
            `display:flex;flex-direction:row;flex-wrap:nowrap;align-items:stretch`,
        ].join(';');
    }

    // Button factory
    const BTN_W = vert ? SZ : 52;
    const mkBtn = (icon, label, onClick, draggable) => {
        const b = mk('button'); b.type = 'button';
        if (draggable) b.draggable = true;
        b.style.cssText = [
            `display:flex;flex-direction:column;align-items:center;justify-content:center`,
            vert ? `width:${BTN_W}px;min-height:${SZ}px;padding:4px 2px;gap:2px;flex-shrink:0` : `min-width:48px;flex:1;min-height:${SZ}px;padding:4px 6px;gap:2px`,
            `background:transparent;border:none;border-radius:4px;cursor:pointer;font-family:inherit;transition:all 0.2s ease`
        ].join(';');
        
        b.addEventListener('mouseenter', () => {
            b.style.transform = 'scale(1.05)';
            b.style.background = 'rgba(0,0,0,.07)';
        });
        
        b.addEventListener('mouseleave', () => {
            b.style.transform = 'scale(1)';
            b.style.background = 'none';
        });
        
        const ico = mk('span'); ico.textContent = icon;
        ico.style.cssText = 'font-size:18px;line-height:1;pointer-events:none;flex-shrink:0';
        const lbl = mk('span'); lbl.textContent = label;
        lbl.dataset.ppcLbl = '1';
        lbl.style.cssText = `font-size:9px;color:${FG};font-weight:700;white-space:nowrap;text-align:center;line-height:1.15;pointer-events:none;`;
        b.append(ico, lbl);
        b.onclick = onClick;
        return b;
    };

    const mkSep = () => {
        const d = mk('div');
        d.style.cssText = vert
            ? `height:1px;background:${_shadeHex(BG,-18)};margin:2px 6px;width:${SZ-12}px;flex-shrink:0`
            : `width:1px;background:${_shadeHex(BG,-18)};margin:5px 0;flex-shrink:0;align-self:stretch`;
        return d;
    };

    // Drag & drop
    function _attachDrag(btn, groupId) {
        btn.addEventListener('dragstart', e => {
            _dragId = groupId;
            e.dataTransfer.effectAllowed = 'move';
            setTimeout(() => btn.style.opacity = '.4', 0);
        });
        btn.addEventListener('dragend', () => { _dragId = null; btn.style.opacity = '1'; });
        btn.addEventListener('dragover', e => { e.preventDefault(); btn.style.outline = '2px dashed ' + FG; });
        btn.addEventListener('dragleave', () => btn.style.outline = '');
        btn.addEventListener('drop', e => {
            e.preventDefault(); btn.style.outline = '';
            if (!_dragId || _dragId === groupId) return;
            const order = sortedReg.map(r => r.id);
            const from = order.indexOf(_dragId), to = order.indexOf(groupId);
            if (from < 0 || to < 0) return;
            order.splice(to, 0, order.splice(from, 1)[0]);
            _setOrder(order); _rebuild();
        });
    }

    // Touch drag for mobile
    function _attachTouchDrag(container) {
        let dragEl = null, ghost = null, lastOver = null;
        let startX = 0, startY = 0, origLeft = 0, origTop = 0;
        let pressTimer = null, isDragging = false;

        container.addEventListener('touchstart', e => {
            const h = e.target.closest('[data-ppc-drag]');
            if (!h) return;
            dragEl = h;
            startX = e.touches[0].clientX;
            startY = e.touches[0].clientY;

            pressTimer = setTimeout(() => {
                isDragging = true;
                const r = dragEl.getBoundingClientRect();
                origLeft = r.left; origTop = r.top;
                ghost = dragEl.cloneNode(true);
                ghost.style.cssText = `position:fixed;left:${origLeft}px;top:${origTop}px;width:${r.width}px;height:${r.height}px;opacity:.8;pointer-events:none;z-index:99999;border:2px dashed ${FG};border-radius:6px;background:${BG};box-shadow:0 10px 20px rgba(0,0,0,0.3);transform:scale(1.05);transition:transform 0.1s;`;
                document.body.appendChild(ghost);
                dragEl.style.opacity = '.3';
            }, 300);
        }, { passive: true });

        container.addEventListener('touchmove', e => {
            if (!dragEl) return;
            if (!isDragging) {
                clearTimeout(pressTimer);
                dragEl = null;
                return;
            }
            e.preventDefault();
            const t = e.touches[0];
            ghost.style.left = (origLeft + t.clientX - startX) + 'px';
            ghost.style.top = (origTop + t.clientY - startY) + 'px';

            const over = document.elementFromPoint(t.clientX, t.clientY)?.closest('[data-ppc-drag]');
            if (lastOver && lastOver !== dragEl) lastOver.style.outline = '';
            if (over && over !== dragEl) { over.style.outline = '2px dashed ' + FG; lastOver = over; }
        }, { passive: false });

        container.addEventListener('touchend', e => {
            clearTimeout(pressTimer);
            if (!isDragging || !dragEl) {
                dragEl = null; isDragging = false;
                return;
            }
            ghost?.remove(); ghost = null;
            dragEl.style.opacity = '1';
            if (lastOver && lastOver !== dragEl) lastOver.style.outline = '';

            const t = e.changedTouches[0];
            const over = document.elementFromPoint(t.clientX, t.clientY)?.closest('[data-ppc-drag]');
            if (over && over !== dragEl) {
                const fromId = dragEl.dataset.ppcDrag, toId = over.dataset.ppcDrag;
                const order = sortedReg.map(r => r.id);
                const fi = order.indexOf(fromId), ti = order.indexOf(toId);
                if (fi >= 0 && ti >= 0) { order.splice(ti, 0, order.splice(fi, 1)[0]); _setOrder(order); _rebuild(); }
            }
            dragEl = null; lastOver = null; isDragging = false;
        }, { passive: true });
    }

    // Collapse button
    const colBtn = mk('button'); colBtn.type = 'button';
    colBtn.textContent = 'β–Ό';
    colBtn.style.cssText = [
        `font-size:9px;color:${FG};background:none;border:none;cursor:pointer`,
        `padding:2px 4px;font-family:inherit;flex-shrink:0`,
        vert ? `width:${SZ}px;text-align:center` : `min-width:20px;align-self:center`
    ].join(';');
    colBtn.title = _D('KΓΌΓ§ΓΌlt', 'Collapse', 'Recolher');
    colBtn.onclick = () => { _setCollapsed(true); _rebuild(); };

    // Render entries
    if (!vert) {
        const scrollWrap = mk('div');
        scrollWrap.style.cssText = 'display:flex;flex:1;min-width:0;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch;align-items:stretch';
        const fixedEnd = mk('div');
        fixedEnd.style.cssText = 'display:flex;flex-shrink:0;align-items:stretch';

        let hasAny = false;
        sortedReg.forEach(entry => {
            if (!_isEnabled(entry.id)) return;
            if (hasAny) scrollWrap.appendChild(mkSep());
            entry.buttons.forEach((btn, i) => {
                const b = mkBtn(btn.icon, btn.label, btn.onClick, i === 0);
                if (i === 0) { b.dataset.ppcDrag = entry.id; _attachDrag(b, entry.id); }
                scrollWrap.appendChild(b);
            });
            hasAny = true;
        });

        if (hasAny) fixedEnd.appendChild(mkSep());
        const sBtn = mkBtn('βš™οΈ', 'PopControl', _openSettings, false);
        fixedEnd.appendChild(sBtn);
        fixedEnd.appendChild(colBtn);

        bar.appendChild(scrollWrap);
        bar.appendChild(fixedEnd);
        _attachTouchDrag(scrollWrap);
    } else {
        let hasAny = false;
        sortedReg.forEach(entry => {
            if (!_isEnabled(entry.id)) return;
            if (hasAny) bar.appendChild(mkSep());
            entry.buttons.forEach((btn, i) => {
                const b = mkBtn(btn.icon, btn.label, btn.onClick, i === 0);
                if (i === 0) { b.dataset.ppcDrag = entry.id; _attachDrag(b, entry.id); }
                bar.appendChild(b);
            });
            hasAny = true;
        });
        if (hasAny) bar.appendChild(mkSep());
        const sBtn = mkBtn('βš™οΈ', 'PopControl', _openSettings, false);
        sBtn.style.marginTop = 'auto';
        bar.appendChild(sBtn); bar.appendChild(mkSep()); bar.appendChild(colBtn);
        _attachTouchDrag(bar);
    }

    document.body.appendChild(bar);

    // Auto-shrink labels
    requestAnimationFrame(() => {
        bar.querySelectorAll('[data-ppc-lbl]').forEach(lbl => {
            const btn = lbl.closest('button');
            if (btn && lbl.scrollWidth > btn.clientWidth + 2) lbl.style.fontSize = '8px';
        });
    });

    // Push layout for top
    if (pos === 'top') _applyPush(bar.offsetHeight || 34);

    // Apply collapsed state
    if (_collapsed) {
        bar.style.display = 'none';
        fab.style.display = 'flex';
        _positionFab(fab);
    }
}

// ─── SETTINGS PANEL ──────────────────────────────────────────────────────────
function _openSettings() {
    document.getElementById('ppc-ov')?.remove();
    const pos = _getPos();

    const ov = mk('div'); ov.id = 'ppc-ov';
    ov.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.55);z-index:99998;display:flex;align-items:flex-end;justify-content:center';

    const box = mk('div');
    box.style.cssText = 'background:#fff;border-radius:16px 16px 0 0;padding:20px;width:100%;max-width:520px;max-height:80vh;overflow-y:auto;box-sizing:border-box';

    const mkH = t => { const d = mk('div'); d.textContent = t; d.style.cssText = 'font-size:10px;font-weight:700;color:#888;text-transform:uppercase;letter-spacing:.5px;margin:14px 0 6px'; return d; };
    const mkHr = () => { const hr = mk('hr'); hr.style.cssText = 'border:none;border-top:1px solid #eee;margin:10px 0'; return hr; };
    const mkPillRow = (items) => {
        const row = mk('div'); row.style.cssText = 'display:flex;gap:6px;flex-wrap:wrap';
        items.forEach(([val, lbl, active, fn]) => {
            const b = mkB(lbl, '', fn);
            b.style.cssText = `flex:1;min-width:70px;padding:7px 4px;border-radius:6px;border:1px solid ${active?'#6f42c1':'#ddd'};background:${active?'#6f42c1':'#f8f9fa'};color:${active?'#fff':'#333'};font-size:11px;cursor:pointer;font-family:inherit`;
            row.appendChild(b);
        });
        return row;
    };

    // Title
    const titleRow = mk('div'); titleRow.style.cssText = 'display:flex;justify-content:space-between;align-items:center;margin-bottom:16px';
    titleRow.appendChild(Object.assign(mk('span'), { textContent: ' PopControl v' + GM_info.script.version, style: { fontWeight: 'bold', fontSize: '16px' } }));
    const closeBtn = mkB('βœ•', '', () => ov.remove()); closeBtn.style.cssText = 'background:none;border:none;font-size:20px;cursor:pointer;color:#aaa;padding:0';
    titleRow.appendChild(closeBtn); box.appendChild(titleRow);

    // Position
    box.appendChild(mkH(STR.posLabel));
    box.appendChild(mkPillRow([
        ['bottom', STR.posBottom, pos==='bottom', () => { _setPos('bottom'); ov.remove(); location.reload(); }],
        ['top',    STR.posTop,    pos==='top',    () => { _setPos('top');    ov.remove(); location.reload(); }],
        ['left',   STR.posLeft,   pos==='left',   () => { _setPos('left');   ov.remove(); location.reload(); }],
        ['right',  STR.posRight,  pos==='right',  () => { _setPos('right');  ov.remove(); location.reload(); }],
    ]));
    box.appendChild(mkHr());

    // Ecosystem links
    const ecosystemRow = mk('div');
    ecosystemRow.style.cssText = 'background:#f0f8ff;border-radius:8px;padding:16px;margin-bottom:12px';
    ecosystemRow.innerHTML = `
        <div style="display:flex;gap:20px;justify-content:center;align-items:center">
            <div style="display:flex;align-items:center;gap:10px">
                <span style="font-size:16px">πŸ‡ΉπŸ‡·</span>
                <a href="https://rentry.org/PopControlEkosistemi" target="_blank" style="color:#1a5276;font-weight:500;text-decoration:none;font-size:13px">Beni Oku</a>
            </div>
            <div style="display:flex;align-items:center;gap:10px">
                <span style="font-size:16px">πŸ‡¬πŸ‡§</span>
                <a href="https://rentry.org/PopControlEcosystem" target="_blank" style="color:#1a5276;font-weight:500;text-decoration:none;font-size:13px">Read Me</a>
            </div>
            <div style="display:flex;align-items:center;gap:10px">
                <span style="font-size:16px">πŸ‡§πŸ‡·</span>
                <a href="https://rentry.org/EcossistemaPopControl" target="_blank" style="color:#1a5276;font-weight:500;text-decoration:none;font-size:13px">Leia-me</a>
            </div>
        </div>
    `;
    box.appendChild(ecosystemRow);

    // Language
    box.appendChild(mkH(STR.langLabel));
        
    const _hasCustom = ['ppc_lc_helper','ppc_lc_social','ppc_lc_social_mobile','ppc_lc_depot','ppc_lc_guide','ppc_lc_route49'].some(k => localStorage.getItem(k));
    box.appendChild(mkPillRow([
        ['TR','πŸ‡ΉπŸ‡· TΓΌrkΓ§e', LANG==='TR', () => { CK.set('ppm_lang','TR'); ov.remove(); location.reload(); }],
        ['EN','πŸ‡¬πŸ‡§ English', LANG==='EN', () => { CK.set('ppm_lang','EN'); ov.remove(); location.reload(); }],
        ['PT','πŸ‡§πŸ‡· PortuguΓͺs', LANG==='PT', () => { CK.set('ppm_lang','PT'); ov.remove(); location.reload(); }],
        ['CU','🌍 Customize', _hasCustom, () => _openCustomize(ov)],
    ]));
    box.appendChild(mkHr());

    // Colors
    box.appendChild(mkH('Renk AyarlarΔ±'));
    const colorRow = mk('div'); colorRow.style.cssText = 'display:flex;gap:12px;align-items:center;margin-bottom:12px';
    
    const bgInput = mk('input'); bgInput.type = 'color'; bgInput.value = _getColBg();
    bgInput.style.cssText = 'width:40px;height:40px;border:1px solid #ddd;border-radius:6px;cursor:pointer;box-shadow:0 2px 4px rgba(0,0,0,0.1)';
    bgInput.oninput = () => { _setColBg(bgInput.value); _queueRebuild(); };
    
    const fgInput = mk('input'); fgInput.type = 'color'; fgInput.value = _getColFg();
    fgInput.style.cssText = 'width:40px;height:40px;border:1px solid #ddd;border-radius:6px;cursor:pointer;box-shadow:0 2px 4px rgba(0,0,0,0.1)';
    fgInput.oninput = () => { _setColFg(fgInput.value); _queueRebuild(); };
    
    const bgLabel = mk('span'); bgLabel.textContent = STR.colorBar; bgLabel.style.cssText = 'font-size:13px;font-weight:500;color:#333';
    const fgLabel = mk('span'); fgLabel.textContent = STR.colorText; fgLabel.style.cssText = 'font-size:13px;font-weight:500;color:#333';
    
    colorRow.appendChild(bgLabel); colorRow.appendChild(bgInput);
    colorRow.appendChild(fgLabel); colorRow.appendChild(fgInput);
    box.appendChild(colorRow);
    
    // Keyboard shortcuts info
    const shortcutsRow = mk('div');
    shortcutsRow.style.cssText = 'background:#f8f9fa;border-radius:8px;padding:16px;margin-bottom:10px';
    shortcutsRow.innerHTML = `
        <div style="display:flex;align-items:center;gap:8px;margin-bottom:8px">
            <span style="font-size:16px">⌨️</span>
            <span style="font-size:13px;font-weight:500;color:#333">${STR.shortcut}</span>
        </div>
        <div style="display:flex;align-items:center;gap:8px">
            <span style="font-size:16px">πŸ“±</span>
            <span style="font-size:13px;font-weight:500;color:#333">${STR.orderHint}</span>
        </div>
    `;
    box.appendChild(shortcutsRow);
    box.appendChild(mkHr());

    // Menu Settings
    if (location.href.includes('/World/Popmundo.aspx/Character')) {
        box.appendChild(mkH(_D('Karakter MenΓΌsΓΌ', 'Character Menu', 'Menu do Personagem')));
        const menuRow = mk('div'); 
        menuRow.style.cssText = 'display:flex;align-items:center;justify-content:space-between;padding:12px;background:#f8f9fa;border-radius:8px;margin-bottom:12px';
        
        const menuInfo = mk('span');
        menuInfo.innerHTML = `<span style="font-size:16px;margin-right:8px">πŸ—‚οΈ</span><span style="font-size:13px;font-weight:500;color:#333">${_D('Gizle, favorilere al, sΔ±rala', 'Hide, favorite & reorder items', 'Ocultar, favoritar e reordenar')}</span>`;
        
        const _hiddenCount = JSON.parse(localStorage.getItem('hidden-native-menu-items') || '[]').length;
        const _badgeTxt = _hiddenCount ? ` <span style="background:#dc3545;color:#fff;border-radius:10px;padding:1px 7px;font-size:11px;font-weight:700;margin-left:4px;">${_hiddenCount}</span>` : '';
        const menuBtn = mk('button');
        menuBtn.type = 'button';
        menuBtn.innerHTML = _D('YΓΆnet', 'Manage', 'Gerenciar') + _badgeTxt;
        menuBtn.style.cssText = 'padding:8px 16px;background:#667eea;color:white;border:none;border-radius:6px;cursor:pointer;font-size:12px;font-weight:600;transition:all 0.2s;display:flex;align-items:center;gap:4px;';
        menuBtn.onclick = () => { API.MenuManager.showMenuSettings(); ov.remove(); };
        menuBtn.onmouseover = () => menuBtn.style.background = '#5a6fd8';
        menuBtn.onmouseout = () => menuBtn.style.background = '#667eea';
        
        menuRow.appendChild(menuInfo);
        menuRow.appendChild(menuBtn);
        box.appendChild(menuRow);
        box.appendChild(mkHr());
    }

    // Script toggles
    if (_registry.length) {
        box.appendChild(mkH(STR.scripts));
        _sortedRegistry().forEach(entry => {
            const row = mk('div'); row.style.cssText = 'display:flex;align-items:center;justify-content:space-between;padding:10px 0;border-bottom:1px solid #f0f0f0';
            const name = mk('span'); name.textContent = entry.icon + ' ' + entry.label; name.style.cssText = 'font-size:13px;font-weight:500';
            const swLbl = mk('label'); swLbl.style.cssText = 'position:relative;display:inline-block;width:46px;height:26px;cursor:pointer;flex-shrink:0';
            const inp = mk('input'); inp.type = 'checkbox'; inp.checked = _isEnabled(entry.id); inp.style.cssText = 'opacity:0;width:0;height:0;position:absolute';
            const trk = mk('span'); trk.style.cssText = `position:absolute;inset:0;border-radius:26px;background:${inp.checked?'#6f42c1':'#ccc'};transition:.25s`;
            const knob = mk('span'); knob.style.cssText = `position:absolute;height:20px;width:20px;left:${inp.checked?'23px':'3px'};bottom:3px;background:#fff;border-radius:50%;transition:.25s;box-shadow:0 1px 3px rgba(0,0,0,.3)`;
            trk.appendChild(knob);
            inp.onchange = () => {
                const v = inp.checked;
                trk.style.background = v ? '#6f42c1' : '#ccc';
                knob.style.left = v ? '23px' : '3px';
                _setEnabled(entry.id, v);
                if (!v) entry.onUndo?.();
                _rebuild();
            };
            swLbl.append(inp, trk); row.append(name, swLbl); box.appendChild(row);
        });
        box.appendChild(mkHr());
    }

    ov.onclick = e => { if (e.target === ov) ov.remove(); };
    ov.appendChild(box); document.body.appendChild(ov);
}

// ─── CUSTOMIZE (LANGUAGE IMPORT/EXPORT) ──────────────────────────────────────
function _openCustomize(parentOv) {
    const LC_KEYS = {
        helper: 'ppc_lc_helper',
        social: 'ppc_lc_social',
        social_mobile: 'ppc_lc_social_mobile',
        depot: 'ppc_lc_depot',
        guide: 'ppc_lc_guide',
        route49: 'ppc_lc_route49',
    };
    const hasCustom = Object.values(LC_KEYS).some(k => localStorage.getItem(k));

    const ov = mk('div');
    ov.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.75);z-index:100001;display:flex;align-items:center;justify-content:center;padding:16px;box-sizing:border-box';
    const box = mk('div');
    box.style.cssText = 'background:#fff;border-radius:14px;padding:20px;width:100%;max-width:480px;max-height:90vh;overflow-y:auto;box-sizing:border-box;position:relative;font-family:inherit';

    // Header
    const hdr = mk('div');
    hdr.style.cssText = 'display:flex;justify-content:space-between;align-items:center;margin-bottom:16px';
    const title = mk('span');
    title.textContent = '🌍 Custom Language (Customize)';
    title.style.cssText = 'font-weight:700;font-size:16px';
    const xBtn = mk('button');
    xBtn.textContent = 'βœ•'; xBtn.type = 'button';
    xBtn.style.cssText = 'background:none;border:none;font-size:20px;cursor:pointer;color:#aaa;padding:0';
    xBtn.onclick = () => ov.remove();
    hdr.append(title, xBtn);
    box.appendChild(hdr);

    // Info section
    const infoRow = mk('div');
    infoRow.style.cssText = 'background:#e8f4fd;border-radius:8px;padding:12px;margin-bottom:16px;font-size:12px;line-height:1.6;color:#1a5276';
    infoRow.innerHTML = `
        <div style="font-weight:600;margin-bottom:8px">With PopControl's <strong>Customize</strong> feature, you can translate all scripts' interfaces into any language:</div>
        <div style="margin-left:12px;margin-bottom:4px">1. <strong>πŸ“‹ Copy Export JSON + Prompt</strong> β€” copy content</div>
        <div style="margin-left:12px;margin-bottom:4px">2. Paste into <a href="https://gemini.google.com" target="_blank" style="color:#1a5276;font-weight:600">Google Gemini</a>, specify the target language</div>
        <div style="margin-left:12px;margin-bottom:4px">3. Load the returned JSON via <strong>Import</strong></div>
        <div style="margin-left:12px">4. All scripts instantly switch to the new language</div>
    `;
    box.appendChild(infoRow);

    const mkHr = () => { const hr = mk('hr'); hr.style.cssText = 'border:none;border-top:1px solid #eee;margin:14px 0'; return hr; };

    // Export
    box.appendChild(Object.assign(mk('div'), {
        textContent: 'πŸ“€ Export',
        style: 'font-weight:700;font-size:13px;margin-bottom:6px'
    }));
    
    const expBtn = mk('button');
    expBtn.textContent = 'πŸ“‹ Copy Export JSON';
    expBtn.type = 'button';
    expBtn.style.cssText = 'width:100%;padding:10px;background:#0d6efd;color:#fff;border:none;border-radius:8px;cursor:pointer;font-size:13px;font-weight:600;font-family:inherit';
    expBtn.onclick = () => {
        const collected = {};
        _registry.forEach(entry => {
            if (entry.strings && Object.keys(entry.strings).length) {
                collected[entry.id] = entry.strings;
            }
        });
        if (!Object.keys(collected).length) {
            expBtn.textContent = '⚠️ No scripts registered yet';
            setTimeout(() => expBtn.textContent = 'πŸ“‹ Copy Export JSON', 2500);
            return;
        }
        const promptText = 'Translate JSON values below to the target language.\nRules: keep all emojis, {n}, %s and \\n exactly as-is. Return ONLY valid JSON, no markdown, no explanation.\n\nTarget language: [ENTER TARGET LANGUAGE HERE]\n\n' + JSON.stringify(collected, null, 2);
        navigator.clipboard.writeText(promptText);
        expBtn.textContent = 'βœ… Copied!';
        setTimeout(() => expBtn.textContent = 'πŸ“‹ Copy Export JSON', 2500);
    };
    box.appendChild(expBtn);
    box.appendChild(mkHr());

    // Import
    box.appendChild(Object.assign(mk('div'), {
        textContent: 'πŸ“₯ Import',
        style: 'font-weight:700;font-size:13px;margin-bottom:6px'
    }));
    
    const impTa = mk('textarea');
    impTa.placeholder = '{ "helper": { "save": "Speichern", ... }, "social": { ... }, ... }';
    impTa.style.cssText = 'width:100%;height:160px;font-size:11px;font-family:monospace;padding:8px;border:1px solid #ddd;border-radius:6px;box-sizing:border-box;resize:vertical;margin-bottom:8px';
    box.appendChild(impTa);

    const errDiv = mk('div');
    errDiv.style.cssText = 'font-size:12px;min-height:18px;margin-bottom:8px';
    box.appendChild(errDiv);

    const applyBtn = mk('button');
    applyBtn.textContent = 'βœ… Apply & Reload';
    applyBtn.type = 'button';
    applyBtn.style.cssText = 'width:100%;padding:10px;background:#198754;color:#fff;border:none;border-radius:8px;cursor:pointer;font-size:13px;font-weight:600;font-family:inherit';
    applyBtn.onclick = () => {
        try {
            const raw = impTa.value.trim();
            if (!raw) { errDiv.style.color='#dc3545'; errDiv.textContent='Paste translated JSON first.'; return; }
            const data = JSON.parse(raw);
            let applied = 0;
            Object.entries(LC_KEYS).forEach(([id, lsKey]) => {
                if (data[id] && typeof data[id] === 'object') {
                    localStorage.setItem(lsKey, JSON.stringify(data[id]));
                    applied++;
                }
            });
            if (!applied) { errDiv.style.color='#dc3545'; errDiv.textContent='No matching script keys found.'; return; }
            errDiv.style.color = '#198754';
            errDiv.textContent = 'βœ… Applied to ' + applied + ' script(s) β€” reloading...';
            setTimeout(() => { ov.remove(); if (parentOv) parentOv.remove(); location.reload(); }, 1200);
        } catch (err) {
            errDiv.style.color = '#dc3545';
            errDiv.textContent = '❌ Invalid JSON: ' + err.message;
        }
    };
    box.appendChild(applyBtn);

    box.appendChild(mkHr());

    // Reset
    const resetBtn = mk('button');
    resetBtn.textContent = 'πŸ—‘οΈ Reset to Default Language';
    resetBtn.type = 'button';
    resetBtn.style.cssText = 'width:100%;padding:8px;background:none;color:#dc3545;border:1px solid #dc3545;border-radius:8px;cursor:pointer;font-size:12px;font-family:inherit';
    resetBtn.onclick = () => {
        if (!confirm('Remove all custom language data and restore defaults?')) return;
        Object.values(LC_KEYS).forEach(k => localStorage.removeItem(k));
        ov.remove(); if (parentOv) parentOv.remove(); location.reload();
    };
    if (hasCustom) box.appendChild(resetBtn);

    ov.onclick = e => { if (e.target === ov) ov.remove(); };
    ov.appendChild(box);
    document.body.appendChild(ov);
}
        // ─── API & INTEGRATION ────────────────────────────────────────────────────────
const _processed = new Set();
const _queue = window.PopControl && window.PopControl._q ? window.PopControl._q : [];

const API = {
    register({ id, icon, label, buttons, strings, onUndo }) {
        if (_registry.some(r => r.id === id)) return;
        _registry.push({ id, icon: icon || 'πŸ”Œ', label: label || id, buttons: buttons || [], strings: strings || {}, onUndo });
        log(`Registered: ${id}`);
        _queueRebuild();
    },
    unregister(id) {
        const i = _registry.findIndex(r => r.id === id);
        if (i < 0) return;
        const [entry] = _registry.splice(i, 1);
        if (entry._cleanup) entry._cleanup();
        entry.onUndo?.();
        log(`Unregistered: ${id}`);
        _queueRebuild();
    },
    isEnabled: _isEnabled,
    getLang: () => LANG,
    getConnectionStatus: () => ({
        registryCount: _registry.length,
        queueLength: _queue.length,
        scripts: _registry.map(r => ({ id: r.id, label: r.label }))
    }),

    // ─── MENU MANAGER ─────────────────────────────────────────────────────────────
    MenuManager: {
        menuConfigs: new Map(),
        builtMenus: new Set(),
        _favDragActive:  false,   // Favoriler sΔ±ralama modu
        _tvipDragActive: false,   // TOP VIP sΔ±ralama modu

        registerMenu(config) {
            const { id, title, position, items = [], draggable = false, collapsible = true } = config;
            
            if (this.menuConfigs.has(id)) {
                // Merge β€” id'ye gΓΆre dedup, aynΔ± item iki kez eklenmesin
                const existing = this.menuConfigs.get(id);
                const newItems = items.filter(item => !existing.items.some(e => e.id === item.id));
                if (newItems.length) {
                    existing.items.push(...newItems);
                    log(`Updated menu: ${id} +${newItems.length} item(s)`);
                } else {
                    log(`Menu ${id}: tΓΌm item'lar zaten mevcut, atlandΔ±`);
                }
            } else {
                this.menuConfigs.set(id, { id, title, position, items: [...items], draggable, collapsible });
                log(`Registered menu: ${id}`);
            }
            
            this.rebuildMenus();
        },
        
        rebuildMenus() {
            // Only rebuild on character page
            if (!location.href.includes('/World/Popmundo.aspx/Character')) return;
            
            // Remove existing built menus
            this.builtMenus.forEach(menuId => {
                const existing = document.getElementById(menuId);
                if (existing) existing.remove();
            });
            this.builtMenus.clear();
            
            // Build each menu
            this.menuConfigs.forEach(config => {
                this.buildMenu(config);
            });

            // Favoriler + gizleme her zaman son olarak uygulanΔ±r
            this.rebuildFavoritesMenu();
            this.applyNativeItemVisibility();
        },
        
        buildMenu(config) {
            const { id, title, position, items, collapsible } = config;
            const isTopVip = id === 'top-vip';

            // Hedef menΓΌyΓΌ bul (dil-agnostik)
            let targetMenu;
            if (position === 'above-career') {
                targetMenu = [...document.querySelectorAll('.menu h3')]
                    .find(h => /Kariyer|Career|Carreira/.test(h.textContent.trim()))?.closest('.menu');
            }
            if (!targetMenu) { log(`Target menu not found for position: ${position}`); return; }

            // TOP VIP iΓ§in kayΔ±tlΔ± sΔ±rayΔ± uygula
            let orderedItems = [...items];
            if (isTopVip) {
                const order = this._getTopVipOrder();
                if (order.length) {
                    orderedItems.sort((a, b) => {
                        const ai = order.indexOf(a.id), bi = order.indexOf(b.id);
                        if (ai < 0) return 1; if (bi < 0) return -1; return ai - bi;
                    });
                }
            }

            const menuElement = document.createElement('div');
            menuElement.id = id + '-menu'; menuElement.className = 'menu';

            // Başlık + badge
            const header = document.createElement('h3');
            header.style.cssText = 'background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);color:white;text-align:center;padding:8px;margin:0;border-radius:6px 6px 0 0;box-shadow:0 2px 8px rgba(102,126,234,0.3);cursor:pointer;user-select:none;';
            header.textContent = title + (orderedItems.length ? ` (${orderedItems.length})` : '');

            const content = document.createElement('div');
            content.style.cssText = 'padding:0;background:#f8f9fa;border:1px solid #e9ecef;border-top:none;border-radius:0 0 6px 6px;box-shadow:0 2px 4px rgba(0,0,0,0.1);overflow:hidden;';

            const ul = document.createElement('ul');
            ul.style.cssText = 'margin:0;padding:8px 0 4px;list-style:none;';

            if (!orderedItems.length) {
                // Boş durum placeholder
                const empty = document.createElement('li');
                empty.style.cssText = 'padding:6px 12px;font-size:11px;color:#aaa;font-style:italic;';
                empty.textContent = _D('HenΓΌz buton eklenmedi', 'No buttons added yet', 'Nenhum botΓ£o adicionado');
                ul.appendChild(empty);
            } else {
                const MM = this;
                orderedItems.forEach(item => {
                    const li = document.createElement('li');
                    li.id = item.id;
                    li.dataset.tvipKey = item.id;
                    li.draggable = MM._tvipDragActive;
                    li.style.cssText = 'margin:2px 0;display:flex;align-items:center;';

                    // Grip β€” sadece sΔ±ralama modunda gΓΆrΓΌnΓΌr
                    const grip = document.createElement('span');
                    grip.textContent = 'β Ώ';
                    grip.style.cssText = `color:#bbb;cursor:grab;padding:4px 2px 4px 8px;flex-shrink:0;font-size:14px;line-height:1;display:${MM._tvipDragActive ? 'inline' : 'none'};`;

                    const a = document.createElement('a');
                    a.href = '#';
                    a.textContent = item.label;
                    a.style.cssText = 'color:#667eea;font-weight:600;text-decoration:none;display:block;padding:4px 12px;border-radius:4px;transition:all 0.2s;flex:1;';
                    a.addEventListener('mouseover', () => { a.style.background = '#667eea'; a.style.color = 'white'; });
                    a.addEventListener('mouseout',  () => { a.style.background = '';        a.style.color = '#667eea'; });
                    a.addEventListener('click', e => { e.preventDefault(); item.fn?.(); });

                    li.append(grip, a);
                    ul.appendChild(li);
                });
                if (isTopVip && this._tvipDragActive) this._attachTopVipDrag(ul);
            }

            content.appendChild(ul);
            menuElement.append(header, content);

            // SΔ±ralama kulakçığı β€” menΓΌnΓΌn ALTINDA, iΓ§eriğin dışında (2+ item ve TOP VIP)
            const spacer = document.createElement('div');
            spacer.id = id + '-spacer'; spacer.style.cssText = 'height:6px;';

            targetMenu.before(menuElement);
            menuElement.after(spacer);

            this.builtMenus.add(id + '-menu');
            this.builtMenus.add(id + '-spacer');

            if (isTopVip && orderedItems.length > 1) {
                const MM = this;
                const tab = document.createElement('div');
                tab.id = id + '-drag-tab';
                tab.title = _D('SΔ±ralama modunu aΓ§/kapat', 'Toggle reorder mode', 'Alternar modo de reordenaΓ§Γ£o');
                tab.textContent = 'β‡… ' + (this._tvipDragActive
                    ? _D('Bitti', 'Done', 'ConcluΓ­do')
                    : _D('SΔ±rala', 'Reorder', 'Reordenar'));
                tab.style.cssText = [
                    'display:block;margin:0 auto;width:fit-content;padding:3px 14px',
                    `background:${this._tvipDragActive ? '#667eea' : '#f0f0f0'}`,
                    `color:${this._tvipDragActive ? '#fff' : '#999'}`,
                    `border:1px solid ${this._tvipDragActive ? '#667eea' : '#ddd'}`,
                    'border-top:none;border-radius:0 0 10px 10px',
                    'font-size:11px;cursor:pointer;transition:all .2s;user-select:none;'
                ].join(';');
                tab.onmouseover = () => { if (!this._tvipDragActive) { tab.style.background = '#e8e8e8'; tab.style.color = '#666'; } };
                tab.onmouseout  = () => { if (!this._tvipDragActive) { tab.style.background = '#f0f0f0'; tab.style.color = '#999'; } };
                tab.onclick = () => { MM._tvipDragActive = !MM._tvipDragActive; MM.rebuildMenus(); };
                menuElement.after(tab);
                tab.after(spacer);
                this.builtMenus.add(id + '-drag-tab');
            }

            if (collapsible) this.makeCollapsible(menuElement);
            this.applyNativeItemVisibility();
        },
        
        makeCollapsible(menuElement) {
            const header  = menuElement.querySelector('h3');
            const content = menuElement.querySelector(':scope > div'); // <ul> wrapper'Δ± β€” kesin seΓ§im
            const storageKey = menuElement.id === 'top-vip-menu' ? 'top-vip-collapsed' : `menu-${menuElement.id}-collapsed`;
            
            let isCollapsed = localStorage.getItem(storageKey) === 'true';
            if (isCollapsed && content) content.style.display = 'none';
            
            if (!header) return;
            header.addEventListener('click', () => {
                isCollapsed = !isCollapsed;
                localStorage.setItem(storageKey, isCollapsed);
                if (content) content.style.display = isCollapsed ? 'none' : '';
            });
        },
        
        // ── FAVORITES STORAGE ─────────────────────────────────────────────────────
        _getFavorites() { return JSON.parse(localStorage.getItem('ppc-favorites') || '[]'); },
        _saveFavorites(arr) { localStorage.setItem('ppc-favorites', JSON.stringify(arr)); },

        // Sondaki karakter ID'sini sil: /OfferItem/3117642 β†’ /OfferItem/
        _normalizePath(p) { return p.replace(/\/\d+\/?$/, '/'); },
        _getTopVipOrder() { return JSON.parse(localStorage.getItem('ppc-tvip-order') || '[]'); },
        _saveTopVipOrder(arr) { localStorage.setItem('ppc-tvip-order', JSON.stringify(arr)); },

        toggleFavorite(key, text, href) {
            const favs = this._getFavorites();
            const idx  = favs.findIndex(f => f.key === key);
            if (idx > -1) favs.splice(idx, 1);
            else favs.push({ key, text, href: href || '#' });
            this._saveFavorites(favs);
            this.rebuildFavoritesMenu();
        },

        reorderFavorites(fromKey, toKey) {
            const favs = this._getFavorites();
            const fi = favs.findIndex(f => f.key === fromKey);
            const ti = favs.findIndex(f => f.key === toKey);
            if (fi < 0 || ti < 0 || fi === ti) return;
            favs.splice(ti, 0, favs.splice(fi, 1)[0]);
            this._saveFavorites(favs);
            this.rebuildFavoritesMenu();
        },

        // ── FAVORITES MENU DOM ─────────────────────────────────────────────────────
        rebuildFavoritesMenu() {
            if (!location.href.includes('/World/Popmundo.aspx/Character')) return;
            document.getElementById('ppc-fav-menu')?.remove();
            document.getElementById('ppc-fav-spacer')?.remove();
            document.getElementById('ppc-fav-drag-tab')?.remove();

            const favs = this._getFavorites();
            if (!favs.length) return;

            const anchor = document.getElementById('top-vip-menu') ||
                [...document.querySelectorAll('.menu h3')]
                    .find(h => /Kariyer|Career|Carreira/.test(h.textContent))?.closest('.menu');
            if (!anchor) return;

            const isCol = localStorage.getItem('ppc-fav-collapsed') === 'true';
            const _Df = (tr, en, pt) => ({ TR: tr, EN: en, PT: pt }[LANG] || tr);
            const MM = this;

            const menu = document.createElement('div');
            menu.id = 'ppc-fav-menu'; menu.className = 'menu';

            // Başlık + badge
            const h3 = document.createElement('h3');
            h3.textContent = '⭐ ' + _Df('Sık Kullanılanlar', 'Favorites', 'Favoritos') + ` (${favs.length})`;
            h3.style.cssText = 'background:linear-gradient(135deg,#f093fb,#f5576c);color:#fff;text-align:center;padding:8px;margin:0;border-radius:6px 6px 0 0;cursor:pointer;box-shadow:0 2px 8px rgba(245,87,108,.25);user-select:none;font-size:inherit;font-weight:bold;';

            const content = document.createElement('div');
            content.style.cssText = `background:#fff9fe;border:1px solid #f0c0e8;border-top:none;border-radius:0 0 6px 6px;overflow:hidden;${isCol ? 'display:none;' : ''}`;

            const ul = document.createElement('ul');
            ul.id = 'ppc-fav-list';
            ul.style.cssText = 'margin:0;padding:6px 0 4px;list-style:none;';

            favs.forEach(fav => {
                const li = this._buildFavItem(fav, this._favDragActive);
                if (li) ul.appendChild(li);
            });
            if (this._favDragActive) this._attachFavDrag(ul);

            h3.onclick = () => {
                const open = content.style.display === 'none';
                content.style.display = open ? '' : 'none';
                localStorage.setItem('ppc-fav-collapsed', !open);
            };

            content.appendChild(ul);

            menu.append(h3, content);

            const spacer = document.createElement('div');
            spacer.id = 'ppc-fav-spacer'; spacer.style.cssText = 'height:6px;';

            anchor.before(menu);
            menu.after(spacer);

            // SΔ±ralama kulakçığı β€” menΓΌnΓΌn ALTINDA (2+ favori varsa)
            if (favs.length > 1) {
                const tab = document.createElement('div');
                tab.id = 'ppc-fav-drag-tab';
                tab.title = _Df('SΔ±ralama modunu aΓ§/kapat', 'Toggle reorder mode', 'Alternar modo de reordenaΓ§Γ£o');
                tab.textContent = 'β‡… ' + (this._favDragActive
                    ? _Df('Bitti', 'Done', 'ConcluΓ­do')
                    : _Df('SΔ±rala', 'Reorder', 'Reordenar'));
                tab.style.cssText = [
                    'display:block;margin:0 auto;width:fit-content;padding:3px 14px',
                    `background:${this._favDragActive ? '#f5576c' : '#f0f0f0'}`,
                    `color:${this._favDragActive ? '#fff' : '#999'}`,
                    `border:1px solid ${this._favDragActive ? '#f5576c' : '#ddd'}`,
                    'border-top:none;border-radius:0 0 10px 10px',
                    'font-size:11px;cursor:pointer;transition:all .2s;user-select:none;'
                ].join(';');
                tab.onmouseover = () => { if (!this._favDragActive) { tab.style.background = '#e8e8e8'; tab.style.color = '#666'; } };
                tab.onmouseout  = () => { if (!this._favDragActive) { tab.style.background = '#f0f0f0'; tab.style.color = '#999'; } };
                tab.onclick = () => { MM._favDragActive = !MM._favDragActive; MM.rebuildFavoritesMenu(); };
                menu.after(tab);
                tab.after(spacer);
            }
        },

        _buildFavItem(fav, dragActive) {
            const MM = this;
            // Canlı href: DOM'dan normalize edilmiş key ile eşleştir
            let liveHref = fav.href || '#';
            if (fav.key.startsWith('#')) {
                const el = document.getElementById(fav.key.slice(1));
                const a  = el?.querySelector('a[href]') || (el?.tagName === 'A' ? el : null);
                if (a) liveHref = a.href;
            } else {
                // Normalize path β†’ canlΔ± DOM'dan bul (karakter ID değişse de Γ§alışır)
                const match = [...document.querySelectorAll('.menu a[href]')]
                    .find(a => { try { return MM._normalizePath(new URL(a.href).pathname) === fav.key; } catch { return false; } });
                if (match) liveHref = match.href;
            }

            const li = document.createElement('li');
            li.dataset.favKey = fav.key;
            li.draggable = !!dragActive;
            li.style.cssText = 'margin:2px 0;display:flex;align-items:center;cursor:default;';

            // Grip β€” sadece sΔ±ralama modunda gΓΆrΓΌnΓΌr
            const grip = document.createElement('span');
            grip.textContent = 'β Ώ';
            grip.title = _D('SΔ±ralamak iΓ§in sΓΌrΓΌkle', 'Drag to reorder', 'Arraste p/ reordenar');
            grip.style.cssText = `color:#ccc;cursor:grab;padding:4px 2px 4px 8px;flex-shrink:0;font-size:14px;line-height:1;display:${dragActive ? 'inline' : 'none'};`;

            const a = document.createElement('a');
            a.href = liveHref;
            a.textContent = fav.text;
            a.style.cssText = 'color:#c0392b;font-weight:600;text-decoration:none;display:block;padding:4px 4px 4px 2px;border-radius:4px;transition:all .2s;flex:1;font-size:inherit;';
            a.onmouseover = () => { a.style.background = '#f5576c'; a.style.color = '#fff'; };
            a.onmouseout  = () => { a.style.background = '';        a.style.color = '#c0392b'; };

            li.append(grip, a);
            return li;
        },

        _attachFavDrag(ul) {
            let _fdk = null, _fdEl = null, _fdOver = null;
            const MM = this;
            ul.addEventListener('dragstart', e => {
                _fdEl = e.target.closest('li[data-fav-key]');
                if (!_fdEl) return;
                _fdk = _fdEl.dataset.favKey;
                e.dataTransfer.effectAllowed = 'move';
                setTimeout(() => { if (_fdEl) _fdEl.style.opacity = '.4'; }, 0);
            });
            ul.addEventListener('dragend', () => {
                if (_fdEl) _fdEl.style.opacity = '1';
                if (_fdOver) _fdOver.style.outline = '';
                _fdEl = null; _fdk = null; _fdOver = null;
            });
            ul.addEventListener('dragover', e => {
                e.preventDefault();
                const over = e.target.closest('li[data-fav-key]');
                if (_fdOver && _fdOver !== over) _fdOver.style.outline = '';
                if (over && over !== _fdEl) { over.style.outline = '2px dashed #f5576c'; _fdOver = over; }
            });
            ul.addEventListener('dragleave', e => {
                const over = e.target.closest('li[data-fav-key]');
                if (over) over.style.outline = '';
            });
            ul.addEventListener('drop', e => {
                e.preventDefault();
                const over = e.target.closest('li[data-fav-key]');
                if (over) over.style.outline = '';
                if (!_fdk || !over || over.dataset.favKey === _fdk) return;
                MM.reorderFavorites(_fdk, over.dataset.favKey);
            });
        },

        _attachTopVipDrag(ul) {
            let _dk = null, _dEl = null, _dOver = null;
            const MM = this;
            ul.addEventListener('dragstart', e => {
                _dEl = e.target.closest('li[data-tvip-key]');
                if (!_dEl) return;
                _dk = _dEl.dataset.tvipKey;
                e.dataTransfer.effectAllowed = 'move';
                setTimeout(() => { if (_dEl) _dEl.style.opacity = '.4'; }, 0);
            });
            ul.addEventListener('dragend', () => {
                if (_dEl) _dEl.style.opacity = '1';
                if (_dOver) _dOver.style.outline = '';
                _dEl = null; _dk = null; _dOver = null;
            });
            ul.addEventListener('dragover', e => {
                e.preventDefault();
                const over = e.target.closest('li[data-tvip-key]');
                if (_dOver && _dOver !== over) _dOver.style.outline = '';
                if (over && over !== _dEl) { over.style.outline = '2px dashed #667eea'; _dOver = over; }
            });
            ul.addEventListener('dragleave', e => {
                const over = e.target.closest('li[data-tvip-key]');
                if (over) over.style.outline = '';
            });
            ul.addEventListener('drop', e => {
                e.preventDefault();
                const over = e.target.closest('li[data-tvip-key]');
                if (over) over.style.outline = '';
                if (!_dk || !over || over.dataset.tvipKey === _dk) return;
                const cfg = MM.menuConfigs.get('top-vip');
                if (!cfg) return;
                const order = cfg.items.map(i => i.id);
                const fi = order.indexOf(_dk), ti = order.indexOf(over.dataset.tvipKey);
                if (fi < 0 || ti < 0) return;
                order.splice(ti, 0, order.splice(fi, 1)[0]);
                MM._saveTopVipOrder(order);
                MM.rebuildMenus();
            });
        },

        // ── NATIVE SECTIONS (grouped, for settings UI) ─────────────────────────────
        getNativeMenuSections() {
            const _Ds = (tr, en, pt) => ({ TR: tr, EN: en, PT: pt }[LANG] || tr);
            const sections = [];
            document.querySelectorAll('.box > .menu, .box > div > .menu').forEach(menuDiv => {
                if (['top-vip-menu','ppc-fav-menu'].includes(menuDiv.id)) return;
                const h3 = menuDiv.querySelector(':scope > h3');
                const title = h3 ? h3.textContent.trim() : _Ds('Karakter', 'Character', 'Personagem');
                const items = [];
                menuDiv.querySelectorAll('li').forEach(li => {
                    const a    = li.querySelector('a[href]');
                    const elId = li.id || li.querySelector('[id]')?.id;
                    const text = (a || li.querySelector('a') || li).textContent.trim();
                    if (!text) return;
                    let key = null, href = '#';
                    if (elId) {
                        key = '#' + elId;
                        href = a?.href || '#';
                    } else if (a) {
                        try { const p = new URL(a.href).pathname; key = this._normalizePath(p); href = a.href; } catch { key = a.getAttribute('href'); href = key; }
                    }
                    if (key && !items.some(i => i.key === key)) items.push({ key, text, href });
                });
                if (items.length) sections.push({ title, items });
            });
            return sections;
        },

        showMenuSettings() {
            this.openMenuCustomizationUI();
        },

        openMenuCustomizationUI() {
            if (document.getElementById('ppc-menu-settings')) return;

            const _Dm = (tr, en, pt) => ({ TR: tr, EN: en, PT: pt }[LANG] || tr);
            const MM = this;

            // ── CSS sabitleri ─────────────────────────────────────────────────────
            const CSS_OV  = 'position:fixed;inset:0;background:rgba(0,0,0,.75);z-index:100002;display:flex;align-items:center;justify-content:center;padding:16px;box-sizing:border-box';
            const CSS_BOX = 'background:#fff;border-radius:14px;padding:0;width:100%;max-width:540px;max-height:88vh;display:flex;flex-direction:column;box-sizing:border-box;font-family:inherit;box-shadow:0 10px 40px rgba(0,0,0,.3);overflow:hidden;';
            const CSS_HDR = 'display:flex;justify-content:space-between;align-items:center;padding:18px 20px 14px;border-bottom:2px solid #e9ecef;flex-shrink:0;';
            const CSS_SEC_WRAP  = 'margin-bottom:14px;';
            const CSS_SEC_HDR   = 'font-size:12px;font-weight:700;color:#fff;border-radius:6px;padding:5px 10px;margin-bottom:4px;cursor:pointer;user-select:none;display:flex;justify-content:space-between;align-items:center;';
            const CSS_SEC_LIST  = 'border-radius:0 0 6px 6px;border:1px solid #e9ecef;border-top:none;overflow:hidden;';
            const CSS_ROW_EVEN  = 'display:flex;align-items:center;gap:8px;padding:5px 10px;font-size:12px;background:#fff;transition:opacity .2s;';
            const CSS_ROW_ODD   = 'display:flex;align-items:center;gap:8px;padding:5px 10px;font-size:12px;background:#f8f9fa;transition:opacity .2s;';
            const CSS_ACT_BTN   = 'background:none;border-radius:4px;cursor:pointer;padding:2px 5px;flex-shrink:0;transition:all .2s;';
            const CSS_X_BTN     = 'background:none;border:none;font-size:22px;cursor:pointer;color:#aaa;padding:0;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:6px;';

            // ── BΓΆlΓΌm başlığı oluşturucu (collapsed state kalΔ±cΔ±) ─────────────────
            const mkSecHdr = (label, gradient) => {
                const sKey = 'ppc-sec-' + label.replace(/\W+/g, '_');
                let open = localStorage.getItem(sKey) === 'true';
                const wrap = mk('div'); wrap.style.cssText = CSS_SEC_WRAP;
                const hdr  = mk('div');
                hdr.style.cssText = CSS_SEC_HDR + `background:${gradient || 'linear-gradient(135deg,#667eea,#764ba2)'};`;
                const ttl = mk('span'); ttl.textContent = label;
                const arr = mk('span'); arr.textContent = 'β–Ό';
                arr.style.cssText = 'font-size:9px;opacity:.7;transition:transform .2s;';
                if (!open) arr.style.transform = 'rotate(-90deg)';
                hdr.append(ttl, arr);
                const list = mk('div');
                list.style.cssText = CSS_SEC_LIST + `background:${gradient ? '#fffdf8' : '#f8f9fa'};` + (open ? '' : 'display:none;');
                hdr.onclick = () => {
                    open = !open;
                    localStorage.setItem(sKey, open);
                    list.style.display = open ? '' : 'none';
                    arr.style.transform = open ? '' : 'rotate(-90deg)';
                };
                wrap.append(hdr, list);
                return { wrap, list };
            };

            // ── SatΔ±r oluşturucu ──────────────────────────────────────────────────
            const mkItemRow = (item, idx, isFav, isHidden, onFav, onVis) => {
                const row = mk('div');
                row.style.cssText = (idx % 2 === 0 ? CSS_ROW_EVEN : CSS_ROW_ODD) + (isHidden ? 'opacity:.4;' : '');
                const itemText = mk('span'); itemText.textContent = item.text; itemText.style.cssText = 'flex:1;color:#2c3e50;';
                if (onFav !== null) {
                    const favBtn = mk('button'); favBtn.type = 'button';
                    favBtn.textContent = isFav ? '⭐' : 'β˜†';
                    favBtn.title = isFav ? _Dm('Favorilerden Γ§Δ±kar','Remove','Remover') : _Dm('Favorilere ekle','Add to favorites','Adicionar');
                    favBtn.style.cssText = CSS_ACT_BTN + `border:1px solid ${isFav ? '#f5576c' : '#ddd'};font-size:13px;`;
                    favBtn.onmouseover = () => { favBtn.style.background = isFav ? '#fff0f0' : '#fffbe0'; };
                    favBtn.onmouseout  = () => { favBtn.style.background = 'none'; };
                    favBtn.onclick = onFav;
                    row.appendChild(favBtn);
                }
                const visBtn = mk('button'); visBtn.type = 'button';
                visBtn.textContent = isHidden ? '🚫' : 'πŸ‘';
                visBtn.title = isHidden ? _Dm('GΓΆster','Show','Mostrar') : _Dm('Gizle','Hide','Ocultar');
                visBtn.style.cssText = CSS_ACT_BTN + `border:1px solid ${isHidden ? '#dc3545' : '#ddd'};font-size:12px;`;
                visBtn.onmouseover = () => { visBtn.style.background = '#f8f9fa'; };
                visBtn.onmouseout  = () => { visBtn.style.background = 'none'; };
                visBtn.onclick = onVis;
                row.append(itemText, visBtn);
                return row;
            };

            // ── Overlay & kutu ────────────────────────────────────────────────────
            const ov = mk('div');
            ov.id = 'ppc-menu-settings';
            ov.style.cssText = CSS_OV;
            const box = mk('div');
            box.style.cssText = CSS_BOX;

            // ── BaşlΔ±k ────────────────────────────────────────────────────────────
            const hdr = mk('div');
            hdr.style.cssText = CSS_HDR;
            const title = mk('span');
            title.textContent = 'πŸ—‚οΈ ' + _Dm('MenΓΌ YΓΆnetimi', 'Menu Manager', 'Gerenciar Menu');
            title.style.cssText = 'font-weight:700;font-size:17px;color:#2c3e50;';
            const xBtn = mk('button');
            xBtn.textContent = 'βœ•'; xBtn.type = 'button';
            xBtn.style.cssText = CSS_X_BTN;
            xBtn.onmouseover = () => xBtn.style.background = '#f8f9fa';
            xBtn.onmouseout  = () => xBtn.style.background = 'none';
            xBtn.onclick = () => ov.remove();
            hdr.append(title, xBtn);
            box.appendChild(hdr);

            // ── Δ°pucu bandΔ± ───────────────────────────────────────────────────────
            const tip = mk('div');
            tip.style.cssText = 'background:#e8f4fd;padding:8px 20px;font-size:11px;color:#1a5276;display:flex;gap:20px;flex-shrink:0;border-bottom:1px solid #d6eaf8;flex-wrap:wrap;';
            tip.innerHTML = `
                <span>⭐ ${_Dm('Favori ekle', 'Add to favorites', 'Adicionar favorito')}</span>
                <span>πŸ‘ ${_Dm('GΓΆster/Gizle', 'Show/Hide', 'Mostrar/Ocultar')}</span>
                <span>β‡… ${_Dm('MenΓΌ altΔ±ndaki kulakΓ§Δ±k ile sΔ±rala', 'Use the tab below each menu to reorder', 'Use a aba abaixo do menu p/ reordenar')}</span>
            `;
            box.appendChild(tip);

            // ── Scrollable iΓ§erik ─────────────────────────────────────────────────
            const body = mk('div');
            body.style.cssText = 'overflow-y:auto;flex:1;padding:12px 16px 16px;';
            box.appendChild(body);

            const hidden = JSON.parse(localStorage.getItem('hidden-native-menu-items') || '[]');
            const favs   = this._getFavorites();

            // ── TOP VIP bΓΆlΓΌmΓΌ ────────────────────────────────────────────────────
            const tvipCfg = this.menuConfigs.get('top-vip');
            if (tvipCfg && tvipCfg.items.length) {
                const { wrap: tvWrap, list: tvList } = mkSecHdr(
                    '⭐ TOP VIP (' + tvipCfg.items.length + ')',
                    'linear-gradient(135deg,#667eea 0%,#764ba2 100%)'
                );
                tvipCfg.items.forEach((item, idx) => {
                    const key = '#' + item.id;
                    const isHidden = hidden.includes(key);
                    const row = mkItemRow(
                        { text: item.label, key },
                        idx, false, isHidden,
                        null,
                        () => { MM.toggleNativeItemVisibility(key, isHidden); ov.remove(); MM.openMenuCustomizationUI(); }
                    );
                    row.querySelector('span').style.cssText = 'flex:1;color:#667eea;font-weight:600;';
                    tvList.appendChild(row);
                });
                body.appendChild(tvWrap);
            }

            // ── Favoriler ΓΆzeti (tag cloud) ───────────────────────────────────────
            if (favs.length) {
                const favHdr = mk('div');
                favHdr.style.cssText = 'font-weight:600;font-size:13px;color:#c0392b;margin:4px 0 8px;display:flex;align-items:center;gap:6px;';
                favHdr.innerHTML = `⭐ ${_Dm('SΔ±k KullanΔ±lanlar', 'Favorites', 'Favoritos')} <span style="font-weight:400;font-size:11px;color:#888;">(${_Dm('menΓΌ altΔ±ndaki β‡… ile sΔ±rala', 'use β‡… tab below menu to reorder', 'use aba β‡… abaixo p/ reordenar')})</span>`;
                body.appendChild(favHdr);
                const favList = mk('div');
                favList.style.cssText = 'background:#fff0fb;border:1px solid #f0c0e8;border-radius:8px;padding:6px 10px;margin-bottom:14px;display:flex;flex-wrap:wrap;gap:4px;';
                favs.forEach(fav => {
                    const tag = mk('span');
                    tag.style.cssText = 'background:#f5576c;color:#fff;border-radius:20px;padding:2px 10px 2px 8px;font-size:11px;display:inline-flex;align-items:center;gap:4px;';
                    tag.innerHTML = `${fav.text} <button type="button" style="background:none;border:none;color:#fff;cursor:pointer;font-size:13px;padding:0;line-height:1;opacity:.8;" title="${_Dm('Favorilerden Γ§Δ±kar','Remove','Remover')}">βœ•</button>`;
                    tag.querySelector('button').onclick = () => { MM.toggleFavorite(fav.key,fav.text,fav.href); ov.remove(); MM.openMenuCustomizationUI(); };
                    favList.appendChild(tag);
                });
                body.appendChild(favList);
            }

            // ── BΓΆlΓΌm bazlΔ± native menΓΌ linkleri ─────────────────────────────────
            const sections = this.getNativeMenuSections();
            sections.forEach(sec => {
                const { wrap: secWrap, list: secList } = mkSecHdr(sec.title);
                sec.items.forEach((item, idx) => {
                    const isFav    = favs.some(f => f.key === item.key);
                    const isHidden = hidden.includes(item.key);
                    const row = mkItemRow(
                        item, idx, isFav, isHidden,
                        () => { MM.toggleFavorite(item.key, item.text, item.href); ov.remove(); MM.openMenuCustomizationUI(); },
                        () => { MM.toggleNativeItemVisibility(item.key, isHidden); ov.remove(); MM.openMenuCustomizationUI(); }
                    );
                    secList.appendChild(row);
                });
                body.appendChild(secWrap);
            });

            if (!sections.length) {
                const empty = mk('div');
                empty.style.cssText = 'text-align:center;color:#aaa;padding:32px;font-size:13px;';
                empty.textContent = _Dm('Karakter sayfasΔ±nda aΓ§Δ±n.', 'Open on the character page.', 'Abra na pΓ‘gina do personagem.');
                body.appendChild(empty);
            }

            // ── Alt buton ─────────────────────────────────────────────────────────
            const footer = mk('div');
            footer.style.cssText = 'padding:12px 20px;border-top:1px solid #e9ecef;display:flex;gap:8px;flex-shrink:0;background:#fafafa;border-radius:0 0 14px 14px;';

            const resetAllBtn = mk('button');
            resetAllBtn.type = 'button';
            resetAllBtn.textContent = 'πŸ”„ ' + _Dm('TΓΌmΓΌnΓΌ SΔ±fΔ±rla', 'Reset All', 'Redefinir Tudo');
            resetAllBtn.style.cssText = 'padding:8px 14px;background:#6c757d;color:#fff;border:none;border-radius:6px;cursor:pointer;font-size:12px;font-weight:600;transition:all .2s;';
            resetAllBtn.onmouseover = () => resetAllBtn.style.background = '#5a6268';
            resetAllBtn.onmouseout  = () => resetAllBtn.style.background = '#6c757d';
            resetAllBtn.onclick = () => {
                if (!confirm(_Dm('TΓΌm gizleme ve favori ayarlarΔ± sΔ±fΔ±rlansΔ±n mΔ±?', 'Reset all hide/favorite settings?', 'Redefinir todas as configuraΓ§Γ΅es?'))) return;
                localStorage.removeItem('hidden-native-menu-items');
                localStorage.removeItem('ppc-favorites');
                localStorage.removeItem('top-vip-collapsed');
                localStorage.removeItem('ppc-fav-collapsed');
                localStorage.removeItem('ppc-tvip-order');
                MM._favDragActive  = false;
                MM._tvipDragActive = false;
                MM.rebuildMenus();
                ov.remove();
            };

            const closeBtn = mk('button');
            closeBtn.type = 'button';
            closeBtn.textContent = _Dm('Kapat', 'Close', 'Fechar');
            closeBtn.style.cssText = 'flex:1;padding:8px;background:#3498db;color:#fff;border:none;border-radius:6px;cursor:pointer;font-size:13px;font-weight:600;transition:all .2s;';
            closeBtn.onmouseover = () => closeBtn.style.background = '#2980b9';
            closeBtn.onmouseout  = () => closeBtn.style.background = '#3498db';
            closeBtn.onclick = () => ov.remove();

            footer.append(resetAllBtn, closeBtn);
            box.appendChild(footer);

            ov.onclick = e => { if (e.target === ov) ov.remove(); };
            ov.appendChild(box);
            document.body.appendChild(ov);
        },

        getNativeMenuItems() {
            return this.getNativeMenuSections().flatMap(s => s.items);
        },

        toggleNativeItemVisibility(key, show) {
            const hidden = JSON.parse(localStorage.getItem('hidden-native-menu-items') || '[]');
            const idx = hidden.indexOf(key);
            if (show  && idx > -1) hidden.splice(idx, 1);
            if (!show && idx < 0)  hidden.push(key);
            localStorage.setItem('hidden-native-menu-items', JSON.stringify(hidden));
            this.applyNativeItemVisibility();
        },

        applyNativeItemVisibility() {
            const hidden = JSON.parse(localStorage.getItem('hidden-native-menu-items') || '[]');
            document.querySelectorAll('.menu li').forEach(li => {
                if (li.closest('#ppc-fav-menu')) return;
                const a    = li.querySelector('a[href]');
                const elId = li.id || li.querySelector('[id]')?.id;
                let key = null;
                if (elId) {
                    key = '#' + elId;
                } else if (a) {
                    try { key = this._normalizePath(new URL(a.href).pathname); } catch { key = a.getAttribute('href'); }
                }
                if (!key) return;
                li.style.display = hidden.includes(key) ? 'none' : '';
            });
        }
    }
};

// Global API
const _finalAPI = {
    ...API,
    register: (cfg) => {
        if (!_processed.has(cfg.id)) {
            API.register(cfg);
            _processed.add(cfg.id);
        } else {
            log(`Already registered: ${cfg.id}, skipping`);
        }
    },
    isReady: false
};

window.PopControl = _finalAPI;
if (typeof unsafeWindow !== 'undefined') {
    unsafeWindow.PopControl = _finalAPI;
}

// Process queue
_queue.forEach(cfg => {
    if (!_processed.has(cfg.id)) {
        API.register(cfg);
        _processed.add(cfg.id);
    }
});
log(`Processed ${_queue.length} queued items, ${_processed.size} total registered`);

// Ready signal
let _readyFired = false;
const _fireReady = () => {
    if (_readyFired) return;
    _readyFired = true;
    _finalAPI.isReady = true;
    document.dispatchEvent(new CustomEvent('PopControlReady'));
    console.log('[PopControl] Ready signal sent, API is now available');
};

setTimeout(_fireReady, 20);

// ─── KEYBOARD SHORTCUT ─────────────────────────────────────────────────────────
document.addEventListener('keydown', function(e) {
    if (e.altKey && (e.key === 'p' || e.key === 'P')) {
        e.preventDefault();
        const bar = document.getElementById('ppc-bar');
        const fab = document.getElementById('ppc-fab');
        if (!bar) { _setCollapsed(!_collapsed); return; }
        _setCollapsed(!_collapsed);
        bar.style.display = _collapsed ? 'none' : '';
        if (fab) {
            fab.style.display = _collapsed ? 'flex' : 'none';
            if (_collapsed) _positionFab(fab);
        }
    }
});

// ─── INITIALIZATION ───────────────────────────────────────────────────────────
(function _init() {
    const go = () => {
        _rebuild();
        // MenuManager sadece karakter sayfasΔ±nda, tek seferlik
        if (location.href.includes('/World/Popmundo.aspx/Character')) {
            // PopControl'ΓΌn kendi TOP VIP butonu
            const _ppcBtn = { id: 'mnu-ppc-settings', label: _D('πŸ› οΈ PopControl Ayarlar', 'πŸ› οΈ PopControl Settings', 'πŸ› οΈ Config PopControl'), fn: _openSettings };
            API.MenuManager.registerMenu({ id: 'top-vip', title: '⭐ TOP VIP ⭐', position: 'above-career', items: [_ppcBtn], collapsible: true });
            setTimeout(() => API.MenuManager.rebuildMenus(), 200);
        }
    };
    
    if (document.getElementById('ppm-main') || document.getElementById('ppm-footer')) { go(); return; }
    
    const obs = new MutationObserver(() => {
        if (document.getElementById('ppm-main') || document.getElementById('ppm-footer')) { 
            obs.disconnect(); 
            go(); 
        }
    });
    obs.observe(document.body, { childList: true, subtree: true });
    setTimeout(() => { obs.disconnect(); go(); }, 4000);
    
    // SPA navigasyon β€” throttle + subtree:false (performans)
    let _lastUrl = location.href;
    let _spaTimer = null;
    new MutationObserver(() => {
        if (location.href === _lastUrl) return;
        _lastUrl = location.href;
        clearTimeout(_spaTimer);
        _spaTimer = setTimeout(() => {
            if (location.href.includes('/World/Popmundo.aspx/Character')) {
                API.MenuManager.rebuildMenus();
            }
        }, 300);
    }).observe(document.body, { childList: true, subtree: false });
})();

})();