Greasy Fork is available in English.
Popmundo'nun en kapsamlı mobil sosyal scripti — Raf, Radar, Speed Calling, Karakter Kartı, İlgilenme Rehberi ve daha fazlası.
// ==UserScript==
// @name 🌐 Social Mobile
// @name:en 🌐 Social Mobile
// @name:pt-BR 🌐 Social Mobile
// @namespace popmundo.social.mobile
// @version 2.6
// @description Popmundo'nun en kapsamlı mobil sosyal scripti — Raf, Radar, Speed Calling, Karakter Kartı, İlgilenme Rehberi ve daha fazlası.
// @description:en The most comprehensive mobile social script for Popmundo — Shelf, Radar, Speed Calling, Character Card, Interaction Guide and more.
// @description:pt-BR O script social móvel mais completo do Popmundo — Prateleira, Radar, Speed Calling, Cartão de Personagem, Guia de Interação e mais.
// @author luke-james-gibson
// @license MIT
// @id smbl7x
// @match https://*.popmundo.com/*
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @run-at document-end
// @grant unsafeWindow
// ==/UserScript==
(function () {
try {
'use strict';
// POPCONTROL DISABLE CHECK
try { const _ppc = JSON.parse(localStorage.getItem('ppc_enabled')||'{}'); if (_ppc['social_mobile'] === false) return; } catch {}
// DEVICE BLOCK — Masaüstünde çalışmaz; override için ppsm_sm_desk_ack=1 set et
(function() {
const _isDesk = !/Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent);
if (!_isDesk) return; // Mobil — devam
if (localStorage.getItem('ppsm_sm_desk_ack')) return; // Kullanıcı bypass seçti
const ov = document.createElement('div');
ov.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,.7);z-index:99999;display:flex;align-items:center;justify-content:center;font-family:sans-serif;padding:16px';
ov.innerHTML = '<div style="background:#fff;border-radius:12px;padding:24px;max-width:340px;width:100%;text-align:center">'
+ '<div style="font-size:36px;margin-bottom:8px">🖥️</div>'
+ '<div style="font-weight:bold;font-size:15px;margin-bottom:8px">Masaüstü Cihaz Tespit Edildi</div>'
+ '<div style="font-size:13px;color:#555;margin-bottom:16px">Bu script mobil cihazlar için tasarlanmıştır. Masaüstü kullanım için <b>Social</b> scriptini kullanmanız önerilir.</div>'
+ '<a href="https://greasyfork.org/tr/scripts/567869-social" target="_blank" style="display:inline-block;margin-bottom:16px;color:#6f42c1;font-weight:bold;font-size:13px;text-decoration:none">📥 Social — İndir / Install</a>'
+ '<div style="display:flex;gap:8px;justify-content:center">'
+ '<button id="_psmsm_ack" style="background:#6f42c1;color:#fff;border:none;border-radius:6px;padding:8px 18px;cursor:pointer;font-size:13px;font-family:inherit">Yine de Kullan</button>'
+ '<button id="_psmsm_close" style="background:#eee;border:none;border-radius:6px;padding:8px 18px;cursor:pointer;font-size:13px;font-family:inherit">Kapat</button>'
+ '</div></div>';
document.body ? document.body.appendChild(ov) : document.addEventListener('DOMContentLoaded', () => document.body.appendChild(ov));
document.addEventListener('click', function _h(e) {
if (e.target.id === '_psmsm_ack') { localStorage.setItem('ppsm_sm_desk_ack','1'); location.reload(); }
if (e.target.id === '_psmsm_ack' || e.target.id === '_psmsm_close') { ov.remove(); document.removeEventListener('click', _h); }
});
throw new Error('__ppsm_device_block__');
})();
// CSS
document.head.appendChild(Object.assign(document.createElement('style'), { textContent: `
*{-webkit-tap-highlight-color:transparent}
#psm-bar,#psm-bar *,.psm-bar-btn,.psm-ov,.psm-ov *,.psm-sheet,.psm-sheet *,.psm-cpop,.psm-cpop *,.psm-minipop,.psm-minipop *,.psm-toast{box-sizing:border-box}
/* BAR */
#psm-bar{position:fixed;bottom:env(safe-area-inset-bottom,0);left:0;right:0;z-index:9980;background:#f5f0ff;border-top:1px solid #c9b8f0;display:flex;flex-direction:column;box-shadow:0 -2px 8px rgba(0,0,0,.12)}
.psm-hub-row{display:flex;align-items:stretch;width:100%;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.psm-hub-row::-webkit-scrollbar{display:none}
#psm-hub-row2{display:none;border-top:1px solid #e0d0ff}
.psm-bar-btn{display:flex;flex-direction:column;align-items:center;justify-content:center;min-width:calc(100vw / 6.5);max-width:72px;min-height:52px;background:none;border:none;cursor:pointer;padding:4px 6px;gap:2px;font-family:inherit;flex-shrink:0;flex-grow:1}
.psm-bar-btn:active{background:rgba(111,66,193,.12)}
.psm-bar-btn .bi{font-size:19px;line-height:1}
.psm-bar-btn .bl{font-size:9px;color:#6f42c1;font-weight:600;white-space:nowrap;line-height:1.2}
.psm-bar-add{background:#6f42c1}
.psm-bar-add .bi,.psm-bar-add .bl{color:#fff}
.psm-bar-add:active{background:#5a32a3}
/* HUB COLLAPSE */
#psm-hub-collapse{position:fixed;bottom:calc(env(safe-area-inset-bottom,0) + 60px);right:0;z-index:9981;width:18px;height:28px;background:#c9b8f0;border:none;border-radius:4px 0 0 4px;cursor:pointer;font-size:10px;color:#6f42c1;padding:0;display:flex;align-items:center;justify-content:center}
#psm-hub-fab{position:fixed;bottom:calc(env(safe-area-inset-bottom,0) + 8px);right:8px;z-index:9981;width:46px;height:46px;background:#6f42c1;border:none;border-radius:50%;cursor:pointer;font-size:22px;display:none;align-items:center;justify-content:center;box-shadow:0 2px 10px rgba(0,0,0,.3)}
/* OVERLAY & SHEET */
.psm-ov{position:fixed;inset:0;background:rgba(0,0,0,.55);z-index:9990;display:flex;flex-direction:column;overflow:hidden}
.psm-sheet{background:#fff;border-radius:16px 16px 0 0;width:100%;max-height:92dvh;overflow:hidden;display:flex;flex-direction:column;margin-top:auto;padding-bottom:env(safe-area-inset-bottom,0)}
.psm-sheet-handle{width:40px;height:4px;background:#ddd;border-radius:2px;margin:10px auto 4px;flex-shrink:0}
.psm-sheet-head{padding:8px 14px 8px;display:flex;align-items:center;gap:8px;border-bottom:1px solid #f0f0f0;flex-shrink:0;background:#fff}
.psm-sheet-title{font-weight:700;font-size:14px;flex:1;color:#2d1e6b}
.psm-sheet-close{min-width:36px;min-height:36px;background:none;border:none;font-size:20px;cursor:pointer;color:#aaa;display:flex;align-items:center;justify-content:center;border-radius:50%;padding:0}
.psm-sheet-body{padding:10px 14px 16px;flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch}
/* TOAST */
.psm-toast{position:fixed;bottom:calc(env(safe-area-inset-bottom,0) + 68px);left:50%;transform:translateX(-50%);background:#2d1e6b;color:#fff;font-size:12px;padding:9px 20px;border-radius:20px;z-index:99999;opacity:0;transition:opacity .25s;pointer-events:none;white-space:nowrap;max-width:90vw;overflow:hidden;text-overflow:ellipsis}
.psm-toast.show{opacity:1}
/* COMMON */
.psm-sec{font-size:10px;font-weight:700;color:#888;margin:12px 0 5px;text-transform:uppercase;letter-spacing:.5px}
.psm-hr{border:none;border-top:1px solid #f0f0f0;margin:8px 0}
.psm-chk{display:flex;align-items:flex-start;gap:10px;padding:10px 0;font-size:13px;border-bottom:1px solid #f8f8f8;cursor:pointer;line-height:1.35}
.psm-chk input{width:20px;height:20px;flex-shrink:0;cursor:pointer;accent-color:#6f42c1;margin-top:1px}
.psm-row{display:flex;align-items:center;gap:8px;padding:8px 0}
.btn-g,.btn-b,.btn-r,.btn-v,.btn-grey{padding:10px 18px;border:none;border-radius:8px;cursor:pointer;font-size:13px;font-family:inherit;min-height:44px;font-weight:600}
.btn-g{background:#218838;color:#fff}
.btn-b{background:#17a2b8;color:#fff}
.btn-r{background:#e74c3c;color:#fff}
.btn-v{background:#6f42c1;color:#fff}
.btn-grey{background:#6c757d;color:#fff}
.btn-sm{padding:6px 12px!important;font-size:11px!important;min-height:36px!important}
.btn-full{width:100%;margin-bottom:8px}
/* RAF */
.psm-tabs{display:flex;gap:6px;overflow-x:auto;padding:4px 0 8px;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.psm-tabs::-webkit-scrollbar{display:none}
.psm-tab{flex-shrink:0;padding:8px 14px;border-radius:20px;border:2px solid #ccc;font-size:12px;cursor:pointer;font-weight:600;background:#fff;white-space:nowrap;min-height:44px;display:flex;align-items:center;gap:4px;font-family:inherit}
.psm-tab.active{color:#fff}
.psm-tab-badge{font-size:9px;background:rgba(0,0,0,.18);border-radius:8px;padding:0 5px;min-width:16px;text-align:center}
.psm-raf-col-name{font-weight:700;font-size:11px;color:#6f42c1;padding:8px 0 4px;text-transform:uppercase;letter-spacing:.3px}
.psm-raf-card{display:flex;align-items:center;gap:8px;padding:10px 8px;background:#fff;border:1px solid #e8e8e8;border-radius:8px;margin-bottom:6px;min-height:48px;touch-action:none}
.psm-raf-card.dragging{opacity:.4;border:2px dashed #6f42c1;background:#f5f0ff}
.psm-raf-card.drag-over{border-top:3px solid #6f42c1}
.psm-drag-handle{font-size:17px;color:#ccc;cursor:grab;padding:0 4px;flex-shrink:0;touch-action:none;user-select:none}
.psm-raf-ico{font-size:18px;flex-shrink:0}
.psm-raf-lbl{flex:1;text-decoration:none;color:#333;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.psm-raf-del{min-width:36px;min-height:36px;background:#fff5f5;border:1px solid #fcc;border-radius:6px;color:#e74c3c;font-size:14px;cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.psm-colwrap{margin-bottom:14px}
/* RADAR */
.psm-tcard{display:flex;align-items:center;gap:8px;padding:8px 10px;border:1px solid #e0e0e0;border-radius:10px;margin-bottom:8px;background:#fafafa;min-height:56px;cursor:pointer;position:relative}
.psm-tcard.tc-stale{border:2px solid #e74c3c;background:#fff8f8}
.psm-tcard.dragging{opacity:.4}
.psm-tcard.drag-over{border-top:3px solid #6f42c1}
.psm-tc-avatar{width:48px;height:60px;border-radius:4px;flex-shrink:0;background:linear-gradient(160deg,#ddd5ff,#9b72f0);display:flex;align-items:center;justify-content:center;font-size:20px;overflow:hidden}
.psm-tc-avatar img{width:48px;height:60px;object-fit:cover;display:block}
.psm-tc-body{flex:1;min-width:0}
.psm-tc-name{font-weight:700;font-size:12px;color:#6f42c1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}
.psm-tc-row{font-size:10px;color:#666;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-top:1px}
.psm-tc-stale{font-size:10px;color:#e74c3c;font-weight:700;margin-top:1px}
.psm-tc-del{min-width:32px;min-height:32px;background:#fff5f5;border:1px solid #fcc;border-radius:6px;color:#e74c3c;font-size:13px;cursor:pointer;display:flex;align-items:center;justify-content:center;flex-shrink:0}
/* BG FETCH INDICATOR */
#psm-bg-prog{position:fixed;bottom:calc(env(safe-area-inset-bottom,0) + 58px);right:12px;background:#1a1035;color:#fff;font-size:11px;padding:7px 12px;border-radius:20px;z-index:9985;display:flex;align-items:center;gap:8px;box-shadow:0 2px 8px rgba(0,0,0,.4)}
#psm-bg-prog-txt{flex:1;white-space:nowrap}
#psm-bg-prog-stop{background:none;border:1px solid rgba(255,255,255,.4);color:#fff;border-radius:4px;font-size:10px;padding:2px 7px;cursor:pointer;font-family:inherit}
/* CHAR POPUP */
.psm-cpop{position:fixed;z-index:9995;background:#fff;border-radius:12px;width:min(96vw,400px);box-shadow:0 8px 32px rgba(0,0,0,.28);overflow:hidden}
.psm-cpop-top{display:flex}
.psm-cpop-img{width:88px;min-width:88px;background:linear-gradient(160deg,#ddd5ff,#9b72f0);display:flex;align-items:center;justify-content:center;font-size:32px;flex-shrink:0;overflow:hidden;align-self:stretch}
.psm-cpop-img img{width:88px;height:100%;object-fit:cover;display:block}
.psm-cpop-right{flex:1;display:flex;flex-direction:column;border-left:1px solid #ede9ff;min-width:0}
.psm-cpop-head{background:#f5f0ff;padding:8px 10px 6px;border-bottom:1px solid #ede9ff}
.psm-cpop-name{font-weight:700;font-size:13px;color:#2d1e6b;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.psm-cpop-online{font-size:10px;margin-top:2px;display:flex;align-items:center;gap:3px}
.psm-cpop-dot{width:7px;height:7px;border-radius:50%;display:inline-block;flex-shrink:0}
.psm-cpop-body{padding:5px 10px;font-size:11px;color:#444;flex:1}
.psm-cpop-row{display:flex;align-items:baseline;gap:4px;margin-bottom:3px;overflow:hidden;white-space:nowrap}
.psm-cpop-lbl{color:#bbb;min-width:44px;flex-shrink:0;font-size:10px}
.psm-cpop-val{overflow:hidden;text-overflow:ellipsis;flex:1}
.psm-cpop-val a{color:#17a2b8;text-decoration:none}
.psm-cpop-cash{color:#218838;font-weight:700}
.psm-cpop-links{padding:6px 8px 8px;border-top:1px solid #f0f0f0;display:flex;gap:5px;align-items:center;flex-wrap:wrap}
.psm-cpop-link{font-size:17px;min-width:32px;min-height:32px;display:flex;align-items:center;justify-content:center;text-decoration:none;border-radius:7px;background:#f8f8f8;border:1px solid #eee}
.psm-cpop-link:active{background:#ede9ff}
.psm-cpop-idbtn{font-size:10px;padding:0 7px;min-height:28px;background:#f0f0f0;border:1px solid #ddd;border-radius:6px;cursor:pointer;font-family:inherit;color:#555;font-weight:600}
.psm-cpop-rfbtn{font-size:10px;padding:0 7px;min-height:28px;background:#f5f0ff;border:1px solid #c9b8f0;border-radius:6px;cursor:pointer;font-family:inherit;color:#6f42c1;font-weight:600;margin-left:auto}
.psm-cpop-trkbtn{font-size:11px;padding:3px 9px;min-height:30px;border-radius:6px;border:1px solid #c9b8f0;background:#ede9ff;color:#6f42c1;cursor:pointer;font-family:inherit;font-weight:600;white-space:nowrap}
.psm-cpop-trkbtn.tracked{background:#6f42c1;color:#fff;border-color:#6f42c1}
/* RADAR PAGE PICKER */
.psm-page-picker{position:fixed;z-index:9999;background:#fff;border-radius:10px;box-shadow:0 6px 24px rgba(0,0,0,.25);padding:10px;min-width:200px;max-height:60vh;overflow-y:auto}
.psm-page-picker-title{font-size:10px;font-weight:700;color:#888;margin-bottom:6px;text-transform:uppercase}
/* QUICK LINKS */
.psm-ql{display:inline-flex;gap:3px;margin-left:5px;vertical-align:middle}
.psm-ql a{display:inline-flex;align-items:center;justify-content:center;min-width:32px;min-height:32px;font-size:14px;text-decoration:none;background:#f5f0ff;border:1px solid #e0d0ff;border-radius:6px}
/* INTERACT */
.psm-ih-bar{display:flex;gap:6px;flex-wrap:wrap;padding:8px;background:#f5f0ff;border:1px solid #c9b8f0;border-radius:8px;margin-bottom:8px}
.psm-ih-btn{padding:8px 14px;border-radius:20px;border:2px solid #c9b8f0;background:#fff;color:#6f42c1;font-size:12px;cursor:pointer;font-weight:600;min-height:40px;font-family:inherit}
.psm-ih-btn.active{background:#6f42c1;color:#fff;border-color:#6f42c1}
.psm-ih-btn.af.active{background:#2196f3;border-color:#2196f3}
.psm-ih-btn.ar.active{background:#e91e63;border-color:#e91e63}
.psm-ih-btn.an.active{background:#f44336;border-color:#f44336}
.psm-ih-warn{background:#fff3cd;border:1px solid #ffc107;border-radius:8px;padding:8px 12px;font-size:12px;color:#856404;margin-bottom:8px}
/* PLANNER */
.psm-pl-task{background:#fff;border-radius:8px;padding:10px 12px;margin-bottom:8px;box-shadow:0 1px 4px rgba(0,0,0,.08);position:relative;font-size:12px;border-left:4px solid #ccc}
.psm-pl-task-date{font-size:10px;color:#6f42c1;font-weight:700;margin-bottom:2px}
.psm-pl-del{position:absolute;right:6px;top:50%;transform:translateY(-50%);background:none;border:none;font-size:18px;color:#ccc;cursor:pointer;min-width:36px;min-height:36px;display:flex;align-items:center;justify-content:center;padding:0}
.psm-prio-row{display:flex;gap:6px;margin:8px 0}
.psm-prio{flex:1;padding:8px;border:2px solid #ddd;border-radius:8px;text-align:center;cursor:pointer;font-size:13px;min-height:44px;display:flex;align-items:center;justify-content:center;font-family:inherit}
.psm-prio.sg{border-color:#2ecc71;background:#f0fff4}
.psm-prio.sy{border-color:#f1c40f;background:#fffde7}
.psm-prio.sr{border-color:#e74c3c;background:#fff5f5}
/* SPEED CALLING */
#psm-sc-bar{position:fixed;top:0;left:0;right:0;z-index:9999;background:#1a1035;color:#fff;font-size:13px;padding:calc(env(safe-area-inset-top,0) + 8px) 12px 8px;display:flex;align-items:center;gap:8px;box-shadow:0 2px 8px rgba(0,0,0,.4)}
.psm-sc-stat{flex:1;font-size:12px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.psm-sc-name{color:#c9b8f0;font-weight:600}
.psm-sc-timer{color:#ffd700;font-weight:700;min-width:30px;text-align:center;font-size:14px}
.psm-sc-stop{background:#e74c3c;border:none;color:#fff;border-radius:6px;font-size:12px;padding:6px 14px;cursor:pointer;min-height:36px;flex-shrink:0;font-family:inherit}
.psm-sc-resume{background:#218838;border:none;color:#fff;border-radius:6px;font-size:12px;padding:6px 14px;cursor:pointer;min-height:36px;flex-shrink:0;display:none;font-family:inherit}
.psm-sc-warn{background:#fff3cd;color:#856404;border-radius:6px;padding:4px 8px;font-size:10px;flex-shrink:0;max-width:140px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:none}
/* MISC */
.psm-search{width:100%;padding:10px 12px;border:1px solid #c9b8f0;border-radius:10px;font-size:14px;margin-bottom:10px;font-family:inherit}
.psm-inp{width:100%;padding:10px 12px;border:1px solid #ccc;border-radius:8px;font-size:13px;font-family:inherit;min-height:44px;margin-bottom:6px}
.psm-empty{font-size:12px;color:#bbb;padding:16px 4px;text-align:center;font-style:italic}
.psm-cnote{width:100%;padding:8px;border:1px solid #f0c040;border-radius:8px;font-size:12px;resize:vertical;min-height:50px;font-family:inherit;margin-top:4px;background:#fffde7}
.psm-lang-row{display:flex;gap:6px;margin:8px 0}
.psm-lang-btn{flex:1;padding:10px 4px;border:2px solid #ccc;border-radius:8px;cursor:pointer;font-size:12px;background:#f8f9fa;text-align:center;min-height:44px;font-family:inherit}
.psm-lang-btn.active{background:#6f42c1;color:#fff;border-color:#6f42c1;font-weight:700}
.psm-frl-btn{display:inline-flex;align-items:center;justify-content:center;min-width:34px;min-height:34px;margin-left:5px;padding:0 6px;border-radius:6px;border:1px solid #c9b8f0;background:#f5f0ff;color:#6f42c1;font-size:13px;cursor:pointer;vertical-align:middle;font-family:inherit}
.psm-frl-btn.on{background:#6f42c1;color:#fff;border-color:#6f42c1}
.psm-sh-row{display:flex;gap:8px;align-items:baseline;padding:8px 0;border-bottom:1px solid #f5f5f5;font-size:12px}
.psm-sh-pre{font-weight:700;color:#6f42c1;min-width:54px;flex-shrink:0;font-size:10px}
.psm-clip-row{display:flex;align-items:center;gap:8px;padding:10px;border-bottom:1px solid #f8f8f8;min-height:48px}
.psm-sc-charlist{max-height:180px;overflow-y:auto;border:1px solid #e0e0e0;border-radius:8px;margin:6px 0}
.psm-sc-crow{display:flex;align-items:center;gap:8px;padding:8px 10px;border-bottom:1px solid #f5f5f5;min-height:44px}
.psm-sc-badge{font-size:10px;padding:2px 7px;border-radius:10px;font-weight:700;flex-shrink:0}
.psm-sc-badge.r{background:#fce4ec;color:#b71c1c}
.psm-sc-badge.a{background:#e3f2fd;color:#1565c0}
/* MINI POPUP (locale/artist/city/forum cards) */
.psm-minipop{position:fixed;z-index:9995;background:#fff;border-radius:10px;box-shadow:0 6px 24px rgba(0,0,0,.22);overflow:hidden;min-width:200px}
.psm-minipop-title{font-size:14px;font-weight:700;color:#2d1e6b;padding:10px 14px 8px;background:#f5f0ff;border-bottom:1px solid #e0d0ff;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:260px}
.psm-minipop-btn{display:block;width:100%;padding:13px 16px;border:none;background:#fff;font-size:14px;text-align:left;cursor:pointer;border-bottom:1px solid #f5f5f5;font-family:inherit;font-weight:500}
.psm-minipop-btn:last-child{border-bottom:none}
.psm-minipop-btn:active{background:#f5f0ff}
/* INTERACT SELECT */
select#ctl00_cphTopColumn_ctl00_ddlInteractionTypes{width:100%!important;min-height:44px!important;font-size:14px!important;border:1px solid #c9b8f0!important;border-radius:8px!important;padding:8px!important;margin-bottom:8px!important;display:block!important}
.psm-cpick{display:flex;flex-wrap:wrap;gap:6px;margin:8px 0 10px;align-items:center}
.psm-cpick-sw{width:28px;height:28px;border-radius:8px;border:2px solid transparent;cursor:pointer;padding:0;flex-shrink:0}
.psm-cpick-sw.sel{border-color:#333;transform:scale(1.15)}
.psm-cpick-custom{width:32px;height:28px;padding:0;border:1px solid #ccc;border-radius:8px;cursor:pointer;margin-left:4px}
.psm-tc-moved{border:2px solid #e74c3c;background:#fff8f8}
.psm-tc-updated{border-left:3px solid #f0c040;background:#fffef5}
.psm-badge-mv{background:rgba(231,76,60,.9);color:#fff;font-weight:700;padding:3px 8px;border-radius:8px;font-size:10px;margin-bottom:4px;display:inline-block}
.psm-badge-upd{background:rgba(240,192,64,.9);color:#333;font-weight:700;padding:3px 8px;border-radius:8px;font-size:10px;margin-bottom:4px;display:inline-block}
.psm-tc-warn{font-size:11px;color:#e74c3c;font-weight:700;margin-top:2px}
.psm-tc-warn.upd{color:#c8900a}
.psm-tc-note{font-size:12px;border:1px solid #e0e0e0;border-radius:8px;padding:8px;width:100%;box-sizing:border-box;resize:none;font-family:inherit;color:#555;height:48px;margin-top:6px}
.psm-raf-recent-tab{padding:8px 14px;border-radius:20px;border:2px dashed #c9b8f0;font-size:12px;cursor:pointer;font-weight:600;background:#fdf8ff;color:#6f42c1;white-space:nowrap;min-height:44px;display:flex;align-items:center;gap:4px;font-family:inherit}
.psm-raf-recent-tab.active{background:#6f42c1;color:#fff;border-color:#6f42c1}
.psm-raf-edit{background:#f8f9fa;border:1px solid #ddd;border-radius:12px;padding:12px;margin-bottom:10px;font-size:13px}
.psm-tab-edit-pop{position:fixed;z-index:99999;background:#fff;border:1px solid #c9b8f0;border-radius:12px;padding:12px;box-shadow:0 8px 32px rgba(0,0,0,.25);min-width:260px}
` }));
// UTILS
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 gmGet = (k,def=null)=>{ try{const v=GM_getValue(k,null);return v!==null?(typeof v==='string'&&(v[0]==='['||v[0]==='{')?JSON.parse(v):v):def;}catch{return def;}};
const gmSet = (k,v)=>GM_setValue(k,typeof v==='object'?JSON.stringify(v):v);
const gmDel = k=>GM_deleteValue(k);
const mk = (tag,cls,txt)=>{const e=document.createElement(tag);if(cls)e.className=cls;if(txt!==undefined)e.textContent=txt;return e;};
const mkB = (txt,cls,fn)=>Object.assign(mk('button',cls,txt),{onclick:fn,type:'button'});
const isOnDef = (k,def=false)=>{const v=CK.get(k);return v!==null?v==='1':def;};
const guard = (key,...urls)=>isOnDef(key,true)&&(!urls.length||urls.some(u=>location.href.includes(u)));
const PM = '/World/Popmundo.aspx';
const normUrl = href=>{try{const u=new URL(href,location.href);return u.pathname+u.search;}catch{return href;}};
// iOS AudioContext warm-up
let _actx=null;
document.addEventListener('touchstart',()=>{try{_actx=new(window.AudioContext||window.webkitAudioContext)();}catch(e){}},{once:true,passive:true});
const showToast = (msg,dur=2500)=>{
document.querySelector('.psm-toast')?.remove();
const t=mk('div','psm-toast',msg);document.body.appendChild(t);
requestAnimationFrame(()=>t.classList.add('show'));
setTimeout(()=>{t.classList.remove('show');setTimeout(()=>t.remove(),300);},dur);
};
// LANG
const LANG=CK.get('ppm_lang')||'TR';
const _D=(tr,en,pt)=>({TR:tr,EN:en,PT:pt});
const STR={
close:_D('✕','✕','✕'),
save:_D('✔ Kaydet','✔ Save','✔ Salvar'),
cancel:_D('İptal','Cancel','Cancelar'),
backup:_D('📤 Yedekle','📤 Backup','📤 Exportar'),
restore:_D('📥 Geri Yükle','📥 Restore','📥 Importar'),
restoreErr:_D('Geçersiz dosya.','Invalid file.','Arquivo inválido.'),
restoreQ:_D('Mevcut veriler ne olsun?','What to do with current data?','O que fazer com os dados atuais?'),
merge:_D('Birleştir','Merge','Mesclar'),
replace:_D('Üzerine Yaz','Replace','Substituir'),
langLabel:_D('Dil','Language','Idioma'),
secView:_D('GÖRÜNÜM','VIEW','APARÊNCIA'),
secSocial:_D('SOSYAL','SOCIAL','SOCIAL'),
secTools:_D('ARAÇLAR','TOOLS','FERRAMENTAS'),
barAdd:_D('Ekle','Add','Adicionar'),
barShelf:_D('Raf','Shelf','Prat.'),
barClip:_D('Pano','Clip','Painel'),
barRadar:_D('Radar','Radar','Radar'),
barCall:_D('Ara','Call','Ligar'),
barSocial:_D('Social','Social','Social'),
pins:_D('📌 Rafım','📌 Shelf','📌 Prateleira'),
charCard:_D('⭐ Karakter Kartı','⭐ Character Card','⭐ Cartão'),
radar:_D('📍 Radar & Yakın Takip','📍 Radar','📍 Radar'),
interact:_D('👋 İlgilenme Rehberi','👋 Interaction Guide','👋 Guia'),
quickLinks:_D('🔗 Hızlı Bağlantılar','🔗 Quick Links','🔗 Links'),
note:_D('📝 Karakter Notu','📝 Char Note','📝 Nota'),
speedcall:_D('📞 Speed Calling','📞 Speed Calling','📞 Speed Calling'),
diary:_D('🔍 Günlük Filtresi','🔍 Diary Filter','🔍 Filtro Diário'),
moneyFmt:_D('💰 Para Biçimlendirici','💰 Money Formatter','💰 Moeda'),
cash:_D('Nakit','Cash','Dinheiro'),
genrePopup:_D('🎼 Tür Popülerliği','🎼 Genre Popularity','🎼 Popularidade'),
serenadeHelper:_D('🎵 Serenat Helper','🎵 Serenade Helper','🎵 Serenata'),
pinBtn:_D('📌 Rafım','📌 Shelf','📌 Prateleira'),
rafForum:_D('Forum','Forum','Fórum'),
rafArtist:_D('Sanatçılar','Artists','Artistas'),
rafLocale:_D('Mekanlar','Locales','Locais'),
rafCity:_D('Şehirler','Cities','Cidades'),
rafFav:_D('Favoriler','Favourites','Favoritos'),
rafChars:_D('Karakterler','Characters','Personagens'),
rafWork:_D('İş & Stüdyo','Work & Studio','Trabalho & Estúdio'),
rafGoals:_D('Hedefler','Goals','Objetivos'),
rafCol:_D('Sütun','Column','Coluna'),
quickAdd:_D('📌 Rafa Ekle','📌 Add to Shelf','📌 Adicionar'),
addWhere:_D('Nereye ekleyelim?','Where to add?','Onde adicionar?'),
delEntry:_D('Bu kaydı sil?','Delete this entry?','Excluir?'),
recentTab:_D('🕐 Son Eklenenler','🕐 Recent','🕐 Recentes'),
tkTitle:_D('📍 Radar','📍 Radar','📍 Radar'),
tkNoChars:_D('Bu sekmede karakter yok.','No characters.','Nenhum personagem.'),
tkStale:_D('⚠️ Bilgiler eski','⚠️ Info outdated','⚠️ Info antiga'),
tkUpdate:_D('🔄 Sayfayı Güncelle','🔄 Update Page','🔄 Atualizar'),
tkUpdating:_D('🔄 Güncelleniyor {n}/{t}','🔄 Updating {n}/{t}','🔄 Atualizando {n}/{t}'),
tkUpdateDone:_D('✅ Radar güncellendi','✅ Radar updated','✅ Radar atualizado'),
cpAddFriend:_D('👥 Arkadaş Ekle','👥 Add as Friend','👥 Amigo'),
cpAddRom:_D('💕 Romantik Ekle','💕 Add as Romantic','💕 Romântico'),
cpAlreadyFriend:_D('Zaten arkadaş olarak ekli.','Already added as friend.','Já adicionado como amigo.'),
cpAlreadyRom:_D('Zaten romantik olarak ekli.','Already added as romantic.','Já adicionado como romântico.'),
cpAdded:_D('✅ Eklendi','✅ Added','✅ Adicionado'),
hubPos:_D('Hub Konumu','Hub Position','Posição do Hub'),
hubBottom:_D('⬇️ Aşağıda','⬇️ Bottom','⬇️ Abaixo'),
hubTop:_D('⬆️ Yukarıda','⬆️ Top','⬆️ Acima'),
hubClassic:_D('🔲 Klasik (Hub Kapalı)','🔲 Classic (Hub Off)','🔲 Clássico (Hub Desativado)'),
hubUndo:_D('↩ Geri Al','↩ Undo','↩ Desfazer'),
scAskSC:_D('Speed Calling listesine de eklensin mi?','Add to Speed Calling list?','Adicionar à lista Speed Calling?'),
yes:_D('Evet','Yes','Sim'),
chTitle:_D('📋 Pano','📋 Clipboard','📋 Painel'),
chClear:_D('Tümünü Temizle','Clear All','Limpar Tudo'),
wtOnline:_D('çevrimiçi!','is online!','está online!'),
interactAll:_D('🌐 Standart','🌐 Standard','🌐 Padrão'),
interactFriend:_D('👥 Arkadaşlık','👥 Friendship','👥 Amizade'),
interactRom:_D('💕 Romantizm','💕 Romance','💕 Romance'),
interactHate:_D('😡 Nefret','😡 Hatred','😡 Ódio'),
interactWarn:_D('⚠️ Romantizm 70+ — Kıskançlık riski!','⚠️ Romance 70+ — Jealousy risk!','⚠️ Romance 70+ — Ciúme!'),
interactJNo:_D("Kıskanmam","Won't be jealous",'Não ciúmo'),
interactJYes:_D('Kıskanırım','Will be jealous','Vou ciúmar'),
interactJeal:_D('💘 Kıskançlık:','💘 Jealousy:','💘 Ciúme:'),
plTabDef:_D('Sekme','Tab','Aba'),
plDescPlh:_D('Görev gir...','Enter task...','Digite a tarefa...'),
plAdd:_D('EKLE','ADD','ADICIONAR'),
plNoTasks:_D('Görev yok.','No tasks.','Sem tarefas.'),
scTitle:_D('📞 Speed Calling','📞 Speed Calling','📞 Speed Calling'),
scInterval:_D('Arama arası (sn):','Interval (sec):','Intervalo (seg):'),
scIntervalNote:_D('+ 0-2sn rastgele','+ 0-2s random','+ 0-2s aleatório'),
scPhoneNote:_D('Virgülle ayır','Comma separated','Vírgula'),
scFriendIds:_D('Arkadaş:','Friends:','Amizade:'),
scRomIds:_D('Romantik:','Romantic:','Romântico:'),
scWho:_D('Kimler aransın?','Who to call?','Quem ligar?'),
scWhoFriend:_D('Arkadaşlar','Friends','Amigos'),
scWhoRom:_D('Romantikler','Romantics','Românticos'),
scStart:_D('▶ Başlat','▶ Start','▶ Iniciar'),
scResume:_D('▶ Devam','▶ Resume','▶ Retomar'),
scReset:_D('↺ Sıfırla','↺ Reset','↺ Reiniciar'),
scNoChars:_D('Kayıtlı karakter bulunamadı.','No saved characters.','Nenhum personagem.'),
scBarOf:_D('/','/','/'),
scBarNext:_D('Sonraki:','Next:','Próximo:'),
scBarDone:_D('✅ Tamamlandı!','✅ Done!','✅ Concluído!'),
scBarStop:_D('Durdur','Stop','Parar'),
scBarResume:_D('Devam','Resume','Continuar'),
scBarFail:_D('⚠️ 2 ardışık hata','⚠️ 2 errors','⚠️ 2 erros'),
scBarNoId:_D('ID yok — atlandı','No ID — skipped','ID não encontrado'),
shBtn:_D('🎵 Serenat Helper','🎵 Serenade Helper','🎵 Serenata'),
shLastUpd:_D('Son güncelleme:','Last update:','Última atualização:'),
shUpdateBtn:_D('🔄 Güncelle','🔄 Update','🔄 Atualizar'),
shRadioLink:_D('📻 Radyo Sıralamaları','📻 Radio Charts','📻 Paradas'),
shFetching:_D('📻 Yükleniyor: {n}/17','📻 Fetching: {n}/17','📻 Buscando: {n}/17'),
shDone:_D('✅ Güncellendi!','✅ Done!','✅ Concluído!'),
shWarn1:_D('Çarşamba 10:00 CET\'e kadar güncelleme gerekmez.','No update needed until Wed 10:00 CET.','Sem necessidade até quarta.'),
shWarn2:_D('Güncelleme gerekli mi?','Really update?','Atualizar mesmo?'),
genreBtn:_D('🎼 Tür Popülerliğini Gör','🎼 View Genre Popularity','🎼 Ver Popularidade'),
genreTitle:_D('🎼 Müzik Türü Popülerliği','🎼 Genre Popularity','🎼 Popularidade'),
copyId:_D('📋 ID Kopyala','📋 Copy ID','📋 Copiar ID'),
cpAttitude:_D('Tavır','Attitude','Atitude'),
cpState:_D('Durum','State','Estado'),
cpOffline:_D('Çevrimdışı','Offline','Offline'),
cpRefresh:_D('🔄 Güncelle','🔄 Refresh','🔄 Atualizar'),
cpTrack:_D('☆ Radar\'a Ekle','☆ Add to Radar','☆ Adicionar'),
cpTracked:_D('⭐ Radarda','⭐ On Radar','⭐ No Radar'),
tkPageSelect:_D('Hangi sayfaya?','Which page?','Qual página?'),
tkPageMove:_D('Hangi sayfaya taşınsın?','Move to?','Mover para?'),
tkRemove:_D('⭐ Radardan Çıkar','⭐ Remove from Radar','⭐ Remover'),
tkPageFull:_D('Sayfa dolu.','Page full.','Página cheia.'),
tkTabEdit:_D('Sekmeyi Düzenle','Edit Tab','Editar Aba'),
tkGoTo:_D('Yanına Git','Go To','Ir Para'),
badgeMoved:_D('📍 TAŞINDI','📍 MOVED','📍 MUDOU'),
badgeUpdated:_D('✎ Güncellendi','✎ Updated','✎ Atualizado'),
tcWarnMoved:_D('⚠️ Önceki:','⚠️ Previous:','⚠️ Anterior:'),
tcWarnUpdated:_D('✎ Tavır/durum değişti','✎ Attitude/status changed','✎ Atitude mudou'),
localeGo:_D('➡️ Git','➡️ Go','➡️ Ir'),
localeVisit:_D('🏠 Mekandakiler','🏠 Who\'s there','🏠 Quem está'),
artistUpcoming:_D('🎵 Gelecek Konserler','🎵 Upcoming Gigs','🎵 Próximos Shows'),
artistRecent:_D('🎸 Son Konserler','🎸 Recent Gigs','🎸 Shows Recentes'),
cityFly:_D('✈️ Uçuş','✈️ Fly','✈️ Voar'),
cityVip:_D('✈️ VIP Jet','✈️ VIP Jet','✈️ VIP Jet'),
cityBus:_D('🚌 Kara Ulaşımı','🚌 Bus','🚌 Ônibus'),
};
const isColorDark=hex=>{const h=hex.replace('#','');if(h.length<6)return false;const r=parseInt(h.slice(0,2),16),g=parseInt(h.slice(2,4),16),b=parseInt(h.slice(4,6),16);return(0.299*r+0.587*g+0.114*b)<155;};
const PRESET_COLORS=['#6f42c1','#9b59b6','#007bff','#17a2b8','#28a745','#dc3545','#fd7e14','#ffc107','#e83e8c','#343a40'];
const mkColorPicker=(container,initial)=>{
let sel=initial||'#6f42c1';const wrap=mk('div','psm-cpick');
PRESET_COLORS.forEach(c=>{
const sw=mk('button','psm-cpick-sw'+(c===sel?' sel':''));sw.type='button';sw.style.background=c;
sw.onclick=()=>{sel=c;wrap.querySelectorAll('.psm-cpick-sw').forEach(x=>x.classList.remove('sel'));sw.classList.add('sel');};
wrap.appendChild(sw);
});
const ci=mk('input','psm-cpick-custom');ci.type='color';ci.value=sel;
ci.oninput=()=>{sel=ci.value;wrap.querySelectorAll('.psm-cpick-sw').forEach(x=>x.classList.remove('sel'));};
wrap.appendChild(ci);container.appendChild(wrap);return ()=>sel;
};
const _clSM = (() => { try { const v = localStorage.getItem('ppc_lc_social_mobile'); return v ? JSON.parse(v) : null; } catch { return null; } })();
const s=k=>{ if(_clSM && _clSM[k]) return _clSM[k]; const v=STR[k];if(!v)return k;return v[LANG]??v['TR']??k; };
// KEYS
const K={
pins:'tvis_feat_pins',charPopup:'tvis_feat_chpopup',tracking:'tvis_feat_tracking',
ia:'tvis_feat_ia',note:'tvis_feat_cnote',diary:'tvis_feat_dfl',
moneyFmt:'tvis_feat_moneyFmt',
interact:'tvis_feat_interact',genrePopup:'tvis_feat_genrepopup',
serenadeHelper:'tvis_feat_serenade',speedcall:'tvis_feat_speedcall',
};
const DK={
PINS:'tvis_pins',RAF:'tvis_raf',CLIP:'tvis_clip',
IA:'tvis_ia_',CACHE:'tvis_char_cache',
TRACK_V2:'tvis_track_v2_',RADAR_TABS:'tvis_radar_tabs',
NOTES:'tvis_notes',
INTERACT_TYPE:'tvis_interact_type_',INTERACT_CUSTOM:'tvis_interact_custom',
RADIO_CACHE:'tvis_radio_cache',
SPEEDCALL_Q:'tvis_sc_queue',SPEEDCALL_STATE:'tvis_sc_state',SPEEDCALL_CFG:'tvis_sc_cfg',
SC_CHARS:'tvis_sc_chars',
};
// RADAR HELPERS
const RP=9,RMAX=20;
const getRP=i=>gmGet(DK.TRACK_V2+i,[])||[];
const setRP=(i,a)=>gmSet(DK.TRACK_V2+i,a);
const trackedPage=cid=>{for(let i=0;i<RP;i++)if(getRP(i).some(e=>String(e.charId)===String(cid)))return i;return -1;};
const isTracked=cid=>trackedPage(cid)>=0;
const removeFromRadar=cid=>{for(let i=0;i<RP;i++){const p=getRP(i),x=p.findIndex(e=>String(e.charId)===String(cid));if(x>=0){p.splice(x,1);setRP(i,p);return true;}}return false;};
const addToRadar=(pi,entry)=>{if(getRP(pi).length>=RMAX)return false;if(isTracked(entry.charId))return false;const p=getRP(pi);p.push(entry);setRP(pi,p);return true;};
const allTracked=()=>{const a=[];for(let i=0;i<RP;i++)getRP(i).forEach(e=>a.push(e));return a;};
const updateInRadar=(cid,data)=>{const pi=trackedPage(cid);if(pi<0)return;const p=getRP(pi),x=p.findIndex(e=>String(e.charId)===String(cid));if(x>=0){p[x]={...p[x],...data,savedAt:Date.now()};setRP(pi,p);}};
const RADAR_TAB_DEFS=[
{icon:'👪',name:'AİLE',color:'#28a745'},
{icon:'🤝',name:'ARKADAŞ',color:'#007bff'},{icon:'🎯',name:'TAKİP',color:'#fd7e14'},
{icon:'⚔️',name:'RAKİP',color:'#dc3545'},{icon:'🎸',name:'BAND',color:'#6f42c1'},
{icon:'💼',name:'İŞ',color:'#17a2b8'},{icon:'🌐',name:'DÜNYA',color:'#20c997'},
{icon:'📌',name:'ÖZEL',color:'#e83e8c'},{icon:'📡',name:'DİĞER',color:'#6c757d'},
];
const getRadarTabs=()=>{const s=gmGet(DK.RADAR_TABS,null);if(s&&s.length>=RP)return s;return RADAR_TAB_DEFS.map(t=>({...t}));};
// BACKUP
const dbExport=()=>{
const data={v:2,script:'social',cookies:{},gm:{}};
Object.values(K).forEach(k=>{const v=CK.get(k);if(v!==null)data.cookies[k]=v;});
data.cookies['ppm_lang']=CK.get('ppm_lang')||'TR';
[DK.PINS,DK.RAF,DK.CLIP,DK.CACHE,DK.NOTES,DK.RADAR_TABS,DK.INTERACT_CUSTOM,DK.SPEEDCALL_CFG].forEach(k=>{const v=gmGet(k,null);if(v!==null)data.gm[k]=v;});
for(let i=0;i<RP;i++){const k=DK.TRACK_V2+i,v=gmGet(k,null);if(v!==null)data.gm[k]=v;}
['character','locale','artist','city'].forEach(sec=>{const k=DK.IA+sec,v=gmGet(k,null);if(v!==null)data.gm[k]=v;});
const d=new Date(),p=n=>String(n).padStart(2,'0');
const a=document.createElement('a');
a.href=URL.createObjectURL(new Blob([JSON.stringify(data,null,2)],{type:'application/json'}));
a.download=`ppm-social-${d.getFullYear()}-${p(d.getMonth()+1)}-${p(d.getDate())}.json`;
a.click();
};
const dbImport=()=>{
const inp=Object.assign(document.createElement('input'),{type:'file',accept:'.json'});
inp.onchange=()=>{
const f=inp.files[0];if(!f)return;
const r=new FileReader();
r.onload=ev=>{
let data;try{data=JSON.parse(ev.target.result);}catch{alert(s('restoreErr'));return;}
openSheet(s('restore'),cont=>{
cont.appendChild(mk('div','',s('restoreQ'))).style.cssText='font-size:13px;margin-bottom:12px';
const apply=mode=>{
closeTopSheet();
if(mode==='merge'){
if(data.cookies)Object.entries(data.cookies).forEach(([k,v])=>{if(CK.get(k)===null)CK.set(k,v);});
if(data.gm)Object.entries(data.gm).forEach(([k,v])=>{if(gmGet(k,null)===null)gmSet(k,v);});
}else{
if(data.cookies)Object.entries(data.cookies).forEach(([k,v])=>CK.set(k,v));
if(data.gm)Object.entries(data.gm).forEach(([k,v])=>gmSet(k,v));
}
location.reload();
};
const row=mk('div');row.style.cssText='display:flex;gap:8px;flex-wrap:wrap';
row.append(mkB(s('merge'),'btn-b',()=>apply('merge')),mkB(s('replace'),'btn-r',()=>apply('replace')),mkB(s('cancel'),'btn-grey',closeTopSheet));
cont.appendChild(row);
});
};
r.readAsText(f);
};
inp.click();
};
// TOUCH DRAG
const mkTouchDrag=(container,itemSel,onReorder)=>{
let dragEl=null,ghost=null,lastOver=null,startX=0,startY=0;
container.addEventListener('touchstart',e=>{
const h=e.target.closest('.psm-drag-handle');if(!h)return;
dragEl=h.closest(itemSel);if(!dragEl)return;
startX=e.touches[0].clientX;startY=e.touches[0].clientY;
const r=dragEl.getBoundingClientRect();
ghost=dragEl.cloneNode(true);
ghost.style.cssText=`position:fixed;left:${r.left}px;top:${r.top}px;width:${r.width}px;opacity:.65;pointer-events:none;z-index:99999;border:2px dashed #6f42c1;border-radius:8px;background:#f5f0ff`;
document.body.appendChild(ghost);
dragEl.classList.add('dragging');
},{passive:true});
container.addEventListener('touchmove',e=>{
if(!dragEl)return;
e.preventDefault();
const t=e.touches[0];
ghost.style.transform=`translate(${t.clientX-startX}px,${t.clientY-startY}px)`;
const over=document.elementFromPoint(t.clientX,t.clientY)?.closest(itemSel);
if(lastOver&&lastOver!==dragEl)lastOver.classList.remove('drag-over');
if(over&&over!==dragEl){over.classList.add('drag-over');lastOver=over;}
},{passive:false});
container.addEventListener('touchend',e=>{
if(!dragEl)return;
ghost?.remove();ghost=null;
dragEl.classList.remove('dragging');
if(lastOver&&lastOver!==dragEl)lastOver.classList.remove('drag-over');
const t=e.changedTouches[0];
const over=document.elementFromPoint(t.clientX,t.clientY)?.closest(itemSel);
if(over&&over!==dragEl){
const items=[...container.querySelectorAll(itemSel)];
const fi=items.indexOf(dragEl),ti=items.indexOf(over);
if(fi>=0&&ti>=0)onReorder(fi,ti);
}
dragEl=null;lastOver=null;
},{passive:true});
};
// BOTTOM SHEET
const _sheets=[];
const openSheet=(title,renderFn)=>{
const ov=mk('div','psm-ov');
const sheet=mk('div','psm-sheet');
const head=mk('div','psm-sheet-head');
head.append(mk('div','psm-sheet-title',title),mkB(s('close'),'psm-sheet-close',close));
const body=mk('div','psm-sheet-body');
sheet.append(mk('div','psm-sheet-handle'),head,body);
ov.appendChild(sheet);
function close(){ov.remove();const i=_sheets.indexOf(ov);if(i>=0)_sheets.splice(i,1);}
ov.addEventListener('click',e=>{if(e.target===ov)close();});
// Keyboard-aware scroll
sheet.addEventListener('focusin',()=>setTimeout(()=>{sheet.scrollIntoView({behavior:'smooth',block:'end'});},350));
renderFn(body,close);
document.body.appendChild(ov);
_sheets.push(ov);
return {close};
};
const closeTopSheet=()=>_sheets[_sheets.length-1]?.querySelector('.psm-sheet-close')?.click();
// CITIES PRE-POPULATION
const buildCityCols = () => {
const base = '/World/Popmundo.aspx/City/';
const cities = [
{n:'Amsterdam',id:8},{n:'Ankara',id:35},{n:'Antalya',id:61},
{n:'Bakü',id:58},{n:'Barselona',id:9},{n:'Belgrad',id:36},
{n:'Berlin',id:7},{n:'Brüksel',id:33},{n:'Budapeşte',id:42},
{n:'Buenos Aires',id:17},{n:'Bükreş',id:46},{n:'Cakarta',id:55},
{n:'Dubrovnik',id:29},{n:'Glasgow',id:27},{n:'Helsinki',id:19},
{n:'İstanbul',id:30},{n:'İzmir',id:47},{n:'Johannesburg',id:51},
{n:'Kopenhag',id:22},{n:'Kyiv',id:56},{n:'Londra',id:5},
{n:'Los Angeles',id:14},{n:'Madrid',id:24},{n:'Manila',id:54},
{n:'Melbourne',id:10},{n:'Mexico City',id:32},{n:'Milano',id:52},
{n:'Montreal',id:38},{n:'Moskova',id:18},{n:'Nashville',id:11},
{n:'New York',id:6},{n:'Paris',id:20},{n:'Porto',id:31},
{n:'Rio de Janeiro',id:25},{n:'Roma',id:23},{n:'Sao Paulo',id:21},
{n:'Saraybosna',id:49},{n:'Seattle',id:50},{n:'Singapur',id:39},
{n:'Sofya',id:53},{n:'Stokholm',id:1},{n:'Şangay',id:45},
{n:'Şikago',id:60},{n:'Tallinn',id:34},{n:'Tokyo',id:62},
{n:'Toronto',id:16},{n:'Tromsø',id:26},{n:'Varşova',id:48},
{n:'Vilnius',id:28},
];
const perCol = Math.ceil(cities.length / 5);
return Array.from({length:5}, (_,ci) => ({
name: `${s('rafCol')} ${ci+1}`,
items: cities.slice(ci*perCol, ci*perCol+perCol).map(c => ({
id:'city'+c.id, label:c.n, url:base+c.id,
icon:'🏙️', note:'', savedAt:0
}))
}));
};
// SHELF
const RAF_FOLDERS=[
{id:'chars', icon:'👤',nameKey:'rafChars', color:'#e83e8c', type:'character'},
{id:'cities', icon:'🏙️',nameKey:'rafCity', color:'#fd7e14', type:'city'},
{id:'locale', icon:'📍',nameKey:'rafLocale', color:'#28a745', type:'locale'},
{id:'artist', icon:'🎸',nameKey:'rafArtist', color:'#6f42c1', type:'artist'},
{id:'forum', icon:'📋',nameKey:'rafForum', color:'#17a2b8', type:'forum'},
{id:'fav', icon:'⭐',nameKey:'rafFav', color:'#ffc107', type:'any'},
{id:'work', icon:'💼',nameKey:'rafWork', color:'#343a40', type:'any'},
{id:'goals', icon:'🎯',nameKey:'rafGoals', color:'#dc3545', type:'any'}
];
const getShelf=()=>{
const saved=gmGet(DK.RAF,null);
if(saved?.folders){
let dirty=false;
RAF_FOLDERS.forEach(f=>{
if(!saved.folders[f.id]){
saved.folders[f.id]={icon:f.icon,name:s(f.nameKey),color:f.color,columns:Array.from({length:5},(_,i)=>({name:`${s('rafCol')} ${i+1}`,items:[]}))};
dirty=true;
}
});
const cc=saved.folders['cities']?.columns;
if(cc&&!cc.some(c=>c.items.length)){saved.folders['cities'].columns=buildCityCols();dirty=true;}
if(!saved.folderOrder){saved.folderOrder=RAF_FOLDERS.map(f=>f.id);dirty=true;}
if(dirty)saveShelf(saved);
return saved;
}
const folders={};
RAF_FOLDERS.forEach(f=>{folders[f.id]={icon:f.icon,name:s(f.nameKey),color:f.color,
columns:f.id==='cities'?buildCityCols():Array.from({length:5},(_,i)=>({name:`${s('rafCol')} ${i+1}`,items:[]}))};});
return{folders,folderOrder:RAF_FOLDERS.map(f=>f.id)};
};
const saveShelf=sh=>gmSet(DK.RAF,sh);
const isForumInRaf=url=>getShelf().folders['forum'].columns.flatMap(c=>c.items).some(it=>normUrl(it.url)===normUrl(url));
const addForumToRaf=(id,name,url,ci=-1)=>{
const sh=getShelf(),fd=sh.folders['forum'],nu=normUrl(url);
if(fd.columns.flatMap(c=>c.items).find(it=>normUrl(it.url)===nu))return false;
let tc=ci>=0&&ci<fd.columns.length?ci:fd.columns.findIndex(c=>c.items.length<20);
if(tc<0)tc=0;
fd.columns[tc].items.push({id:'f'+Date.now(),label:name,url:nu,icon:'📋',note:'',color:null,savedAt:Date.now()});
saveShelf(sh);return true;
};
const quickAddToShelf=()=>{
const sh=getShelf();
let label=(document.title||'').replace(/^Popmundo\s*[-–]\s*/i,'').trim()||location.pathname;
const href=location.href;
let fid='fav';
if(href.includes('/World/Popmundo.aspx/Artist/'))fid='artist';
else if(href.includes('/Locale/'))fid='locale';
else if(href.includes('/City/'))fid='cities';
else if(href.includes('/Thread/')||href.includes('/Forum/'))fid='forum';
else if(href.includes('/Character/'))fid='chars';
const fd=sh.folders[fid];
const openForm=(targetFid)=>{
const trg=sh.folders[targetFid];
openSheet(s('addWhere'),(body,close)=>{
trg.columns.forEach((col,ci)=>{
const btn=mkB(`${col.name} (${col.items.length})`,'btn-grey btn-full',()=>{
sh.folders[targetFid].columns[ci].items.push({id:'p'+Date.now(),label,url:normUrl(href),icon:'🔖',note:'',color:null,savedAt:Date.now()});
saveShelf(sh);close();showToast('📌 '+label);
});
body.appendChild(btn);
});
});
};
if(['artist','locale','cities','forum','chars'].includes(fid)) {
openForm(fid);
} else {
openSheet(s('addWhere'),(body,close)=>{
['fav','work','goals'].forEach(freeFid=>{
const fdr=sh.folders[freeFid];
const btn=mkB(`${fdr.icon} ${fdr.name}`,'btn-grey btn-full',()=>{close();openForm(freeFid);});
btn.style.borderColor=fdr.color; btn.style.color=fdr.color; btn.style.background='#fff'; btn.style.borderWidth='2px';
body.appendChild(btn);
});
});
}
};
const openRaf=()=>{
let activeFolder='';
const order=getShelf().folderOrder||RAF_FOLDERS.map(f=>f.id);
activeFolder=order.find(fid=>getShelf().folders[fid]?.columns.some(c=>c.items.length))||order[0];
openSheet(s('pinBtn'),(body)=>{
const render=()=>{
body.innerHTML='';
const sh=getShelf();
const tabRow=mk('div','psm-tabs');
order.forEach(fid=>{
const fd=sh.folders[fid];if(!fd)return;
const total=fd.columns.flatMap(c=>c.items).length;
const tab=mkB(`${fd.icon} ${fd.name}`,'psm-tab'+(fid===activeFolder?' active':''),()=>{activeFolder=fid;render();});
tab.style.borderColor=fd.color;
if(fid===activeFolder){tab.style.background=fd.color;tab.style.color='#fff';}
if(total)tab.appendChild(mk('span','psm-tab-badge',String(total)));
tabRow.appendChild(tab);
});
const recTab=mkB(s('recentTab'),'psm-raf-recent-tab'+(activeFolder==='__recent__'?' active':''),()=>{activeFolder='__recent__';render();});
tabRow.appendChild(recTab);
body.appendChild(tabRow);
const searchI=mk('input','psm-search');searchI.placeholder='🔍 Raflarda ara...';
let q='';
searchI.oninput=()=>{q=searchI.value.toLowerCase();renderCols();};
body.appendChild(searchI);
const colsWrap=mk('div');body.appendChild(colsWrap);
const renderCols=()=>{
colsWrap.innerHTML='';
const curFd=getShelf().folders[activeFolder];
if(activeFolder==='__recent__'){
const allItems=[];
order.forEach(fid=>{const fd2=getShelf().folders[fid];if(!fd2)return;
fd2.columns.forEach((col,ci)=>{col.items.forEach((item,ii)=>{
const ts=item.savedAt||0; if(ts>0)allItems.push({item,fid,ficon:fd2.icon,fname:fd2.name,colname:col.name,ts});
});});
});
allItems.sort((a,b)=>b.ts-a.ts);
const recent=allItems.slice(0,20);
if(!recent.length) colsWrap.appendChild(mk('div','psm-empty','Kayıt yok.'));
else {
const list=mk('div');
recent.forEach(r=>{
const card=mk('div','psm-raf-card');
if(r.item.color){card.style.background=r.item.color;card.style.color=isColorDark(r.item.color)?'#fff':'#222';card.style.borderColor=r.item.color;}
const meta=mk('span','',`${r.ficon} ${r.fname} › ${r.colname}`); meta.style.cssText='font-size:10px;color:#aaa;flex-shrink:0';
const lbl=mk('a','psm-raf-lbl',r.item.label);lbl.href=r.item.url;lbl.target='_blank';if(r.item.color)lbl.style.color='inherit';
card.append(meta,mk('span','psm-raf-ico',r.item.icon||'📌'),lbl);
list.appendChild(card);
});
colsWrap.appendChild(list);
}
return;
}
if(!curFd)return;
curFd.columns.forEach((col,ci)=>{
const filtered=q?col.items.filter(it=>(it.label+' '+(it.note||'')).toLowerCase().includes(q)):col.items;
if(!filtered.length&&q)return;
const cw=mk('div','psm-colwrap');
cw.appendChild(mk('div','psm-raf-col-name',col.name));
const list=mk('div');
filtered.forEach((item,ri)=>{
const realIdx=q?col.items.indexOf(item):ri;
const card=mk('div','psm-raf-card');
if(item.color){card.style.background=item.color;card.style.color=isColorDark(item.color)?'#fff':'#222';card.style.borderColor=item.color;}
const handle=mk('span','psm-drag-handle','⠿');
const ico=mk('span','psm-raf-ico',item.icon||'📌');
const lbl=mk('a','psm-raf-lbl',item.label);lbl.href=item.url;lbl.target='_blank';if(item.color)lbl.style.color='inherit';
const edit=mkB('✏️','psm-raf-del',()=>{
const EICOS=['📌','⭐','🎯','🏠','🎤','🎸','📋','💼','🔗','🌟','💡','🎵','🌆','📍','🏙️','🎪','🎭','🏆','🎮','🔖'];
let selIco=item.icon||'📌';
openSheet('✏️',body2=>{
const ni=mk('input','psm-inp');ni.value=item.label;body2.appendChild(ni);
const nte=mk('input','psm-inp');nte.value=item.note||'';nte.placeholder='Not...';body2.appendChild(nte);
const iconWrap=mk('div');iconWrap.style.cssText='display:flex;flex-wrap:wrap;gap:6px;padding:6px 0 10px';
const refreshIcons=()=>iconWrap.querySelectorAll('button').forEach(b=>{b.style.background=b.textContent===selIco?'#6f42c1':'';b.style.color=b.textContent===selIco?'#fff':'';});
EICOS.forEach(ei=>{const b=mkB(ei,'btn-grey btn-sm',()=>{selIco=ei;refreshIcons();});iconWrap.appendChild(b);});
body2.appendChild(iconWrap);refreshIcons();
const getColor=mkColorPicker(body2,item.color||null);
body2.appendChild(mkB(s('save'),'btn-g btn-full',()=>{
const sh=getShelf();const it=sh.folders[activeFolder].columns[ci].items[realIdx];
if(it){it.label=ni.value.trim()||it.label;it.note=nte.value.trim();it.icon=selIco;it.color=getColor();}
saveShelf(sh);closeTopSheet();renderCols();
}));
});
});
edit.style.cssText='font-size:13px';if(item.color){edit.style.background='rgba(255,255,255,.2)';edit.style.color='inherit';edit.style.borderColor='transparent';}
const del=mkB('✕','psm-raf-del',()=>{if(confirm(s('delEntry'))){const s2=getShelf();s2.folders[activeFolder].columns[ci].items.splice(realIdx,1);saveShelf(s2);renderCols();}});
if(item.color){del.style.background='rgba(255,255,255,.2)';del.style.color='inherit';del.style.borderColor='transparent';}
card.append(handle,ico,lbl,edit,del);
list.appendChild(card);
});
if(!q)mkTouchDrag(list,'.psm-raf-card',(fi,ti)=>{const s2=getShelf();const arr=s2.folders[activeFolder].columns[ci].items;const[m]=arr.splice(fi,1);arr.splice(ti,0,m);saveShelf(s2);renderCols();});
cw.appendChild(list);colsWrap.appendChild(cw);
});
};
renderCols();
};
render();
});
};
// CLIPBOARD
const addClip=(id,name,type)=>{const log=gmGet(DK.CLIP,[])||[];log.unshift({id,name,type,ts:Date.now()});if(log.length>25)log.length=25;gmSet(DK.CLIP,log);};
const openClip=()=>{
const log=gmGet(DK.CLIP,[])||[];
openSheet(s('chTitle'),body=>{
if(!log.length){body.appendChild(mk('div','psm-empty','—'));return;}
const clr=mkB(s('chClear'),'btn-r btn-sm',()=>{gmSet(DK.CLIP,[]);closeTopSheet();openClip();});
clr.style.marginBottom='10px';body.appendChild(clr);
const TI={character:'👤',artist:'🎤',locale:'🏠',city:'🌆'};
log.forEach(e=>{
const row=mk('div','psm-clip-row');
const copy=mkB('📋','btn-grey btn-sm',()=>{navigator.clipboard?.writeText(String(e.id)).catch(()=>{});showToast('📋 '+e.name);});
row.append(mk('span','',TI[e.type]||'🔖'),Object.assign(mk('span','',e.name),{style:'flex:1;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap'}),copy);
body.appendChild(row);
});
});
};
// SC CHARS (Speed Calling listesi — Radara bağımsız)
const getSCChars=()=>gmGet(DK.SC_CHARS,[])||[];
const setSCChars=a=>gmSet(DK.SC_CHARS,a);
const addSCChar=(charId,name,type)=>{const a=getSCChars();if(a.some(c=>String(c.charId)===String(charId)))return false;a.push({charId:String(charId),name,type});setSCChars(a);return true;};
const removeSCChar=charId=>{const a=getSCChars().filter(c=>String(c.charId)!==String(charId));setSCChars(a);};
// CHAR POPUP
const CACHE_TTL = 24*60*60*1000;
const CACHE_TTL_SHORT = 6*60*60*1000; // Radarda olmayan karakterler için
const parseCharPage = html => {
const doc = new DOMParser().parseFromString(html,'text/html');
const name = doc.querySelector('.charPresBox h2')?.textContent.trim(); if(!name)return null;
const pres = doc.querySelector('.characterPresentation');
const bandLink = pres?.querySelector('a[href*="/Artist/"]');
const cityLink = pres?.querySelector('a[href*="/City/"]');
const localeLink = [...(pres?.querySelectorAll('a[href*="/Locale/"]')||[])].find(a=>!a.href.includes('CharactersPresent')&&!a.href.includes('MoveToLocale'));
const onlineTxt = doc.getElementById('ctl00_cphLeftColumn_ctl00_lnkOnlineStatus')?.textContent.trim()
|| doc.getElementById('ctl00_cphLeftColumn_ctl00_trOnlineStatus')?.querySelector('td')?.textContent.replace(/Durum[u]?\s*:/,'').trim()||'';
const attitude = doc.getElementById('ctl00_cphLeftColumn_ctl00_lnkAttitude')?.textContent.trim()||'';
const stateImg = doc.getElementById('ctl00_cphLeftColumn_ctl00_imgState');
const state = stateImg?[...stateImg.closest('tr').querySelectorAll('td')].pop()?.textContent.trim()||'':'';
const avatarDiv = doc.querySelector('.avatar.idTrigger');
const avatarUrl = avatarDiv?.style.backgroundImage?.match(/url\(['"]?([^'"]+)['"]?\)/)?.[1]||'';
const cashRow = doc.getElementById('ctl00_cphLeftColumn_ctl00_imgCash');
const cash = cashRow?[...cashRow.closest('tr').querySelectorAll('td')].pop()?.textContent.trim()||'':'';
return {name,band:bandLink?.textContent.trim()||'',bandHref:bandLink?.getAttribute('href')||'',
city:cityLink?.textContent.trim()||'',cityHref:cityLink?.getAttribute('href')||'',
locale:localeLink?.textContent.trim()||'',localeHref:localeLink?.getAttribute('href')||'',
localeId:localeLink?.href.match(/\/Locale\/(\d+)/)?.[1]||'',
online:onlineTxt,attitude,state,avatarUrl,cash};
};
const onlineDot = online => {
const dateM=(online||'').match(/(\d{1,2}\.\d{2}\.\d{4})/);
const off=!online||/offline|çevrimdışı|desconectado/i.test(online)||!!dateM;
const txt=off?(dateM?`${s('cpOffline')} · ${dateM[1]}`:s('cpOffline')):online;
return {color:off?'#aaa':'#28a745',txt};
};
const showPagePicker=(anchorEl,onSelect,moveMode=false)=>{
document.getElementById('psm-page-picker')?.remove();
const tabs=getRadarTabs(),pop=mk('div','psm-page-picker');pop.id='psm-page-picker';
const r=anchorEl.getBoundingClientRect();
pop.style.cssText=`left:${Math.min(Math.max(8,r.left),window.innerWidth-210)}px;top:${Math.min(r.bottom+6,window.innerHeight-300)}px`;
pop.appendChild(mk('div','psm-page-picker-title',moveMode?s('tkPageMove'):s('tkPageSelect')));
tabs.forEach((tab,i)=>{
const arr=getRP(i),cnt=arr.length,full=cnt>=RMAX;
const btn=mkB(`${tab.icon} ${tab.name} (${cnt}/${RMAX})`,'btn-sm '+(full?'btn-grey':'btn-v'),()=>{
if(full){showToast(s('tkPageFull'));return;}
pop.remove();onSelect(i);
});
btn.style.cssText='width:100%;margin-bottom:3px;text-align:left;display:block';
pop.appendChild(btn);
});
document.body.appendChild(pop);
setTimeout(()=>document.addEventListener('click',e=>{if(!pop.contains(e.target))pop.remove();},{once:true,passive:true}),80);
};
const applyCharPopup=()=>{
if(!guard(K.charPopup))return;
const cache=gmGet(DK.CACHE,{})||{};
let activePop=null;
const closePop=()=>{activePop?.remove();activePop=null;};
document.addEventListener('click',e=>{if(activePop&&!activePop.contains(e.target)&&!e.target.closest('[data-psm-cp]'))closePop();},{passive:true});
const renderPop=(charId,data)=>{
closePop();
// Sync radar entry if tracked
if(isTracked(charId)&&data.name)updateInRadar(charId,{name:data.name,city:data.city,cityHref:data.cityHref,locale:data.locale,localeHref:data.localeHref,localeId:data.localeId,online:data.online,attitude:data.attitude,state:data.state,cash:data.cash,avatarUrl:data.avatarUrl,savedAt:Date.now()});
const pw=Math.min(window.innerWidth*0.96,400);
const pop=mk('div','psm-cpop');
pop.style.cssText=`left:${Math.max(4,(window.innerWidth-pw)/2)}px;top:70px;width:${pw}px`;
pop.setAttribute('data-psm-cp','1');
const imgWrap=mk('div','psm-cpop-img',data.avatarUrl?'':'👤');
if(data.avatarUrl){const img=mk('img');img.src=data.avatarUrl;imgWrap.appendChild(img);}
const right=mk('div','psm-cpop-right');
const head=mk('div','psm-cpop-head');
head.style.cssText='display:flex;align-items:center;gap:4px;flex-wrap:nowrap;';
// Radar button — left of name
const tracked=isTracked(charId);
const trkBtn=mk('button','psm-cpop-trkbtn'+(tracked?' tracked':''));
trkBtn.type='button'; trkBtn.textContent=tracked?'⭐':'☆';
trkBtn.title=tracked?s('cpTracked'):s('cpTrack');
trkBtn.onclick=()=>{
if(isTracked(charId)){
const rmPop=mk('div','psm-page-picker');rmPop.id='psm-page-picker';
const rr=trkBtn.getBoundingClientRect();
rmPop.style.cssText=`left:${Math.min(rr.left,window.innerWidth-200)}px;top:${rr.bottom+4}px`;
const rmBtn=mkB(s('tkRemove'),'btn-sm btn-r',()=>{removeFromRadar(charId);rmPop.remove();trkBtn.textContent='☆';trkBtn.classList.remove('tracked');});
rmBtn.style.cssText='width:100%;display:block';rmPop.appendChild(rmBtn);
document.body.appendChild(rmPop);
setTimeout(()=>document.addEventListener('click',e=>{if(!rmPop.contains(e.target))rmPop.remove();},{once:true,passive:true}),80);
}else{
showPagePicker(trkBtn,pi=>{
const ok=addToRadar(pi,{charId,name:data.name||charId,band:data.band||'',bandHref:data.bandHref||'',city:data.city||'',cityHref:data.cityHref||'',locale:data.locale||'',localeHref:data.localeHref||'',localeId:data.localeId||'',online:data.online||'',attitude:data.attitude||'',state:data.state||'',cash:data.cash||'',avatarUrl:data.avatarUrl||'',savedAt:Date.now()});
if(ok){trkBtn.textContent='⭐';trkBtn.classList.add('tracked');}
});
}
};
head.appendChild(trkBtn);
// Name and Online wrap
const nameWrap=mk('div');
nameWrap.style.cssText='display:flex;flex-direction:column;flex:1;min-width:0;';
const nameA=mk('a','psm-cpop-name',data.name||'...');
nameA.href=`${PM}/Character/${charId}`;nameA.target='_blank';
nameA.style.cssText='text-decoration:none;color:#2d1e6b;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;';
nameWrap.appendChild(nameA);
if(data.online!==undefined){
const od=onlineDot(data.online),oRow=mk('div','psm-cpop-online');
const dot=mk('span','psm-cpop-dot');dot.style.background=od.color;
oRow.append(dot,mk('span','',od.txt));nameWrap.appendChild(oRow);
}
head.appendChild(nameWrap);
// ID copy — right of name
const idBtn=mkB('📋','psm-cpop-idbtn',()=>{navigator.clipboard?.writeText(charId).catch(()=>{});addClip(charId,data.name||charId,'character');showToast('📋 '+charId);});
idBtn.title='ID: '+charId;
head.appendChild(idBtn);
right.appendChild(head);
const bdy=mk('div','psm-cpop-body');
const addRow=(lbl,val,href)=>{
if(!val)return;
const row=mk('div','psm-cpop-row');
row.appendChild(mk('span','psm-cpop-lbl',lbl));
const ve=mk('span','psm-cpop-val');
if(href){const a=mk('a','',val);a.href=href;a.target='_blank';ve.appendChild(a);}else ve.textContent=val;
row.appendChild(ve);bdy.appendChild(row);
};
addRow('🎸',data.band,data.bandHref);
addRow('🌆',data.city,data.cityHref);
addRow('📍',data.locale,data.localeHref);
addRow(s('cpAttitude'),data.attitude);
addRow(s('cpState'),data.state);
if(data.cash){
const row=mk('div','psm-cpop-row');
row.appendChild(mk('span','psm-cpop-lbl',s('cash')));
row.appendChild(mk('span','psm-cpop-val psm-cpop-cash',data.cash));
bdy.appendChild(row);
}
right.appendChild(bdy);
const links=mk('div','psm-cpop-links');
const al=(ico,url,title)=>{const a=mk('a','psm-cpop-link',ico);a.href=url;a.target='_blank';a.title=title||'';links.appendChild(a);};
al('✉️',`${PM}/Conversations/Conversation/${charId}`,'Mesaj');
al('👋',`${PM}/Interact/${charId}`,'İlgilen');
al('🎁',`${PM}/Character/OfferItem/${charId}`,'Eşya Ver');
al('💰',`${PM}/Character/GiveMoney/${charId}`,'Para Ver');
al('📖',`${PM}/Character/Blog/${charId}`,'Blog');
// Speed Calling — toggle, no confirm; bottom row: Arkadaş | Romantik | time | refresh
const bottomRow=mk('div');
bottomRow.style.cssText='display:flex;align-items:center;gap:4px;margin-top:6px;flex-wrap:nowrap;width:100%;';
const scLbl=mk('span','','Speed Calling');
scLbl.style.cssText='font-size:9px;color:#888;white-space:nowrap;flex-shrink:0;';
bottomRow.appendChild(scLbl);
let fBtn=mk('button','psm-cpop-trkbtn');
let rBtn=mk('button','psm-cpop-trkbtn');
fBtn.type='button'; rBtn.type='button';
const refreshSC=()=>{
const cur=getSCChars().find(c=>String(c.charId)===String(charId));
fBtn.textContent=cur?.type==='arkadaş'?'👥 ✓':'👥';
rBtn.textContent=cur?.type==='romantik'?'💕 ✓':'💕';
fBtn.className='psm-cpop-trkbtn'+(cur?.type==='arkadaş'?' tracked':'');
rBtn.className='psm-cpop-trkbtn'+(cur?.type==='romantik'?' tracked':'');
};
fBtn.onclick=()=>{
const cur=getSCChars().find(c=>String(c.charId)===String(charId));
if(cur?.type==='arkadaş')removeSCChar(charId);
else{if(cur)removeSCChar(charId);addSCChar(charId,data.name||charId,'arkadaş');}
refreshSC();
};
rBtn.onclick=()=>{
const cur=getSCChars().find(c=>String(c.charId)===String(charId));
if(cur?.type==='romantik')removeSCChar(charId);
else{if(cur)removeSCChar(charId);addSCChar(charId,data.name||charId,'romantik');}
refreshSC();
};
refreshSC();
bottomRow.append(fBtn,rBtn);
// Time + Refresh (right side of bottom row)
const timeStr=data.ts?new Date(data.ts).toLocaleTimeString([],{hour:'2-digit',minute:'2-digit'}):'';
if(timeStr){const ts=mk('span','',`🕐 ${timeStr}`);ts.style.cssText='font-size:10px;color:#bbb;flex-shrink:0;align-self:center;margin-left:auto;';bottomRow.appendChild(ts);}
const rfBtn=mkB(s('cpRefresh'),'psm-cpop-rfbtn',()=>{delete cache[charId];gmSet(DK.CACHE,cache);closePop();showPopFor(charId);});
bottomRow.appendChild(rfBtn);
links.appendChild(bottomRow);
right.appendChild(links);
const topDiv=mk('div','psm-cpop-top');topDiv.append(imgWrap,right);
pop.appendChild(topDiv);
document.body.appendChild(pop);
activePop=pop;
};
const showPopFor=async charId=>{
const cached=cache[charId];
const ttl=isTracked(charId)?CACHE_TTL:CACHE_TTL_SHORT;
const valid=cached&&(Date.now()-(cached.ts||0))<ttl;
if(valid){renderPop(charId,cached);return;}
// Eskimiş ve radarda olmayan → cache temizle
if(cached&&!isTracked(charId)&&(Date.now()-(cached.ts||0))>=CACHE_TTL_SHORT){delete cache[charId];gmSet(DK.CACHE,cache);}
if(cached)renderPop(charId,cached);
try{
const html=await fetch(`${PM}/Character/${charId}`).then(r=>r.ok?r.text():null);
if(!html)return;
const data=parseCharPage(html);if(!data)return;
cache[charId]={...data,ts:Date.now()};gmSet(DK.CACHE,cache);
if(activePop)renderPop(charId,cache[charId]);
}catch(e){}
};
const processed=new WeakSet();
const injectCP=()=>{
document.querySelectorAll('a[href*="/Character/"]').forEach(a=>{
if(processed.has(a))return;
const m=a.href.match(/\/Character\/(\d+)\/?$/);if(!m)return;
processed.add(a);
const charId=m[1];
a.addEventListener('click',e=>{e.preventDefault();e.stopPropagation();showPopFor(charId);});
});
};
injectCP();setTimeout(injectCP,800);
// Radar kartlarından tetiklenir
document.addEventListener('psm-show-char',e=>showPopFor(e.detail.charId));
};
// RADAR
const STALE_TTL=24*60*60*1000;
let radarUpdRunning=false,radarUpdCancelled=false;
// PERSISTENT BACKGROUND TASK SYSTEM
const showBgProg=(txt,onStop)=>{
document.getElementById('psm-bg-prog')?.remove();
const el=mk('div','');el.id='psm-bg-prog';
const t=mk('span','');t.id='psm-bg-prog-txt';t.textContent=txt;
const stop=mkB('⛔','',()=>{onStop?.();el.remove();});stop.id='psm-bg-prog-stop';
el.append(t,stop);document.body.appendChild(el);
return {setTxt:v=>t.textContent=v, remove:()=>el.remove()};
};
// Cross-page persistent task manager
const PersistentTaskManager = {
init() {
// Check for existing task on page load
const q = gmGet('tvis_bg_q', null);
if (q && q.list && q.list.length > 0) {
this.showPersistentProgress(q);
// Start processing after a short delay to allow page to settle
setTimeout(() => this.processQueue(), 1000);
}
// Monitor for task completion from other tabs
window.addEventListener('storage', (e) => {
if (e.key === 'tvis_bg_q') {
const newValue = e.newValue ? JSON.parse(e.newValue) : null;
if (!newValue || !newValue.list || newValue.list.length === 0) {
document.getElementById('psm-bg-prog')?.remove();
} else if (newValue) {
this.showPersistentProgress(newValue);
}
}
});
},
showPersistentProgress(q) {
const prog = showBgProg(
q.type === 'radar' ?
s('tkUpdating').replace('{n}', q.total - q.list.length).replace('{t}', q.total) :
s('shFetching').replace('{n}', q.total - q.list.length + 1),
() => {
// Stop button handler
gmSet('tvis_bg_q', null);
document.getElementById('psm-bg-prog')?.remove();
showToast('⛔ İşlem durduruldu');
}
);
// Update progress periodically
const updateInterval = setInterval(() => {
const currentQ = gmGet('tvis_bg_q', null);
if (!currentQ || !currentQ.list || currentQ.list.length === 0) {
clearInterval(updateInterval);
return;
}
prog.setTxt(
currentQ.type === 'radar' ?
s('tkUpdating').replace('{n}', currentQ.total - currentQ.list.length).replace('{t}', currentQ.total) :
s('shFetching').replace('{n}', currentQ.total - currentQ.list.length + 1)
);
}, 2000);
return prog;
},
async processQueue() {
let q = gmGet('tvis_bg_q', null);
if (!q || !q.list || !q.list.length) return;
if (window._bgTaskRunning) return;
window._bgTaskRunning = true;
try {
if (q.type === 'radar') {
await this.processRadarUpdate(q);
} else if (q.type === 'radio') {
await this.processRadioUpdate(q);
}
} finally {
window._bgTaskRunning = false;
}
},
async processRadarUpdate(q) {
const prog = this.showPersistentProgress(q);
const localCache = gmGet(DK.CACHE, {}) || {};
while (q.list.length > 0) {
const currentQ = gmGet('tvis_bg_q', null);
if (!currentQ || !currentQ.list || currentQ.list.length === 0) break;
const charId = currentQ.list.shift();
// Update queue with progress
gmSet('tvis_bg_q', currentQ);
try {
const html = await fetch(`${PM}/Character/${charId}`).then(r => r.ok ? r.text() : null);
if (html) {
const data = parseCharPage(html);
if (data) {
localCache[charId] = { ...data, ts: Date.now() };
updateInRadar(charId, { ...data, savedAt: Date.now() });
}
}
} catch (e) {
console.error('Radar update error:', e);
}
// Wait between requests to avoid rate limiting
if (currentQ.list.length > 0) {
await new Promise(r => setTimeout(r, 2000 + Math.random() * 2000));
}
}
gmSet(DK.CACHE, localCache);
gmSet('tvis_bg_q', null);
prog.remove();
showToast(s('tkUpdateDone'));
document.dispatchEvent(new CustomEvent('psm-radar-upd-done'));
},
async processRadioUpdate(q) {
const prog = this.showPersistentProgress(q);
try {
const baseResp = await fetch(`${PM}/Charts/Radio/`);
const baseDoc = new DOMParser().parseFromString(await baseResp.text(), 'text/html');
const gf = name => baseDoc.querySelector(`[name="${name}"]`)?.value || '';
const vs = gf('__VIEWSTATE'), vsg = gf('__VIEWSTATEGENERATOR'), ev = gf('__EVENTVALIDATION');
let cache = gmGet(DK.RADIO_CACHE, null) || { results: [], tracks: {} };
while (q.list.length > 0) {
const currentQ = gmGet('tvis_bg_q', null);
if (!currentQ || !currentQ.list || currentQ.list.length === 0) break;
const st = currentQ.list.shift();
// Update queue with progress
gmSet('tvis_bg_q', currentQ);
try {
const body = new URLSearchParams({
'__EVENTTARGET': 'ctl00$cphLeftColumn$ctl00$ddlRadioStations',
'__EVENTARGUMENT': '',
'__VIEWSTATE': vs,
'__VIEWSTATEGENERATOR': vsg,
'__EVENTVALIDATION': ev,
'ctl00$cphLeftColumn$ctl00$ddlRadioStations': st.id,
'ctl00$cphLeftColumn$ctl00$ddlGenres': '0',
'ctl00$cphLeftColumn$ctl00$ddlWeeksIntoThePast': '0',
'ctl00$cphLeftColumn$ctl00$ddlCountries': '2'
});
const resp = await fetch(`${PM}/Charts/Radio/`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: body.toString()
});
const doc = new DOMParser().parseFromString(await resp.text(), 'text/html');
const row = doc.querySelector('#tablechart tbody tr:first-child');
const tid = row?.querySelector('td:nth-child(2) a')?.href?.match(/\/Track\/(\d+)/)?.[1];
const tname = row?.querySelector('td:nth-child(2) a')?.textContent?.trim() || '';
if (tid) {
cache.tracks[String(tid)] = st.p;
cache.results.push({ prefix: st.p, trackId: tid, name: tname });
}
} catch (e) {
console.error('Radio update error:', e);
}
// Wait between requests
if (currentQ.list.length > 0) {
await new Promise(r => setTimeout(r, 2100 + Math.random() * 2900));
}
}
cache.ts = Date.now();
gmSet(DK.RADIO_CACHE, cache);
gmSet('tvis_bg_q', null);
prog.remove();
showToast(s('shDone'));
} catch (e) {
console.error('Radio fetch error:', e);
gmSet('tvis_bg_q', null);
prog.remove();
}
},
startTask(type, list) {
gmSet('tvis_bg_q', { type, list, total: list.length });
this.showPersistentProgress({ type, list, total: list.length });
this.processQueue();
}
};
const openTrackModal=()=>{
const tabs=getRadarTabs();let activePage=0;let radarSearchQ='';
openSheet(s('tkTitle'),body=>{
const render=()=>{
body.innerHTML='';
const searchI=mk('input','psm-inp');searchI.placeholder='🔍 Radarda ara...';searchI.value=radarSearchQ;
searchI.oninput=()=>{radarSearchQ=searchI.value;renderList();};
body.appendChild(searchI);
const tabRow=mk('div','psm-tabs');
tabs.forEach((tab,i)=>{
const cnt=getRP(i).length;
const btn=mkB(`${tab.icon} ${tab.name}`,'psm-tab'+(i===activePage?' active':''),()=>{activePage=i;radarSearchQ='';render();});
btn.style.borderColor=tab.color;
if(i===activePage){btn.style.background=tab.color;btn.style.color='#fff';}
if(cnt)btn.appendChild(mk('span','psm-tab-badge',String(cnt)));
const editBtn=mkB('✏️','',e=>{
e.stopPropagation();
openSheet(s('tkTabEdit'),b2=>{
const ni=mk('input','psm-inp');ni.value=tab.name;b2.appendChild(ni);
const getColor=mkColorPicker(b2,tab.color||'#6f42c1');
b2.appendChild(mkB(s('save'),'btn-g btn-full',()=>{
const t2=getRadarTabs();t2[i].name=ni.value.trim()||t2[i].name;t2[i].color=getColor();
gmSet(DK.RADAR_TABS,t2);closeTopSheet();render();
}));
});
});
editBtn.style.cssText='background:none;border:none;font-size:12px;padding:0 2px';btn.appendChild(editBtn);
tabRow.appendChild(btn);
});
body.appendChild(tabRow);
const listWrap=mk('div');body.appendChild(listWrap);
const renderList=()=>{
listWrap.innerHTML='';
let chars=[];
if(radarSearchQ){
const q=radarSearchQ.toLowerCase();
for(let i=0;i<RP;i++)getRP(i).forEach(e=>{if((e.name||'').toLowerCase().includes(q))chars.push(e);});
}else chars=getRP(activePage);
if(!chars.length){listWrap.appendChild(mk('div','psm-empty',s('tkNoChars')));return;}
if(!radarSearchQ){
// Check if there's an existing task running
const existingTask = gmGet('tvis_bg_q', null);
if (existingTask && existingTask.type === 'radar' && existingTask.list && existingTask.list.length > 0) {
// Show current progress
const progInfo = mk('div');
progInfo.style.cssText = 'background:#e3f2fd;border:1px solid #2196f3;border-radius:8px;padding:10px;margin-bottom:10px;font-size:12px;color:#1976d2';
progInfo.innerHTML = `
<div style="display:flex;align-items:center;gap;8px;margin-bottom:6px">
<span style="font-weight:700">🔄 Radar güncelleniyor...</span>
<span style="margin-left:auto">${existingTask.total - existingTask.list.length}/${existingTask.total}</span>
</div>
<div style="font-size:11px;color:#666">Sayfa değişseniz bile işlem devam edecek.</div>
`;
listWrap.appendChild(progInfo);
} else {
const updBtn=mkB(s('tkUpdate'),'btn-v btn-full',()=>{
const page=getRP(activePage);
PersistentTaskManager.startTask('radar', page.map(x=>x.charId));
});
listWrap.appendChild(updBtn);
}
}
const list=mk('div');
const cache=gmGet(DK.CACHE,{})||{};const notes=gmGet(DK.NOTES,{})||{};
chars.forEach((e)=>{
const d=cache[e.charId]||e;
const moved=cache[e.charId]?.localeId&&e.localeId&&cache[e.charId].localeId!==e.localeId;
const isOff=!d.online||/Çevrimdışı|Offline|Desconectado/.test(d.online)||/\d{1,2}\.\d{2}\.\d{4}/.test(d.online);
const updated=!moved&&cache[e.charId]&&(cache[e.charId].online!==e.online||cache[e.charId].attitude!==e.attitude||cache[e.charId].state!==e.state);
const card=mk('div','psm-tcard'+(moved?' psm-tc-moved':(updated?' psm-tc-updated':'')));
const av=mk('div','psm-tc-avatar',e.name?.[0]||'👤');
if(e.avatarUrl){const img=mk('img');img.src=e.avatarUrl;av.innerHTML='';av.appendChild(img);}
const bdy=mk('div','psm-tc-body');
const nm=mk('a','psm-tc-name',e.name||e.charId);nm.href=`${PM}/Character/${e.charId}`;nm.target='_blank';nm.style.textDecoration='none';
bdy.appendChild(nm);
if(moved)bdy.appendChild(mk('span','psm-badge-mv',s('badgeMoved')));
else if(updated)bdy.appendChild(mk('span','psm-badge-upd',s('badgeUpdated')));
else if(!isOff)bdy.appendChild(mk('span','psm-badge-on','● Çevrimiçi'));
const infoWrap=mk('div');infoWrap.style.cssText='display:flex;flex-wrap:wrap;gap:4px;margin-top:2px;font-size:10px;color:#555';
const addBadge=(ico,val)=>{if(val){const s=mk('span','',ico+' '+val);s.style.cssText='background:#f0f0f0;padding:2px 6px;border-radius:6px;border:1px solid #ddd;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%';infoWrap.appendChild(s);}};
addBadge('🎸',d.band);
addBadge('🌆',d.city);
addBadge('📍',d.locale);
addBadge('🎭',d.attitude);
addBadge('🧘',d.state);
if(d.cash) addBadge('💰',d.cash);
bdy.appendChild(infoWrap);
const acts=mk('div','psm-tcard-actions');
acts.style.marginTop='6px';
const goto=mk('a','btn-grey btn-sm','🗺️');goto.style.textDecoration='none';goto.target='_blank';
if(d.localeId)goto.href=`${PM}/Locale/MoveToLocale/${d.localeId}/${e.charId}`;else goto.style.opacity='0.3';
const mv=mkB('↕','btn-b btn-sm',()=>{showPagePicker(mv,pi=>{moveInRadar(e.charId,pi);renderList();},true);});
const del=mkB('✕','btn-r btn-sm',()=>{removeFromRadar(e.charId);renderList();});
if(moved){
const ok=mkB('✔','btn-g btn-sm',()=>{updateInRadar(e.charId,{locale:d.locale,localeId:d.localeId,city:d.city,cityHref:d.cityHref});renderList();});
acts.append(goto,ok,mv,del);
}else acts.append(goto,mv,del);
bdy.appendChild(acts);
card.append(av,bdy);list.appendChild(card);
});
listWrap.appendChild(list);
};
renderList();
};
render();
});
};
const moveInRadar=(cid,npi)=>{const pi=trackedPage(cid);if(pi<0)return false;const p1=getRP(pi),x=p1.findIndex(e=>String(e.charId)===String(cid));if(x<0)return false;const[en]=p1.splice(x,1);setRP(pi,p1);const p2=getRP(npi);p2.push(en);setRP(npi,p2);return true;};
// INTERACT HELPER DATA
const INTERACT_DATA = {
1:{sub:'temel',joy:'+2-3%',love:null,hate:'-1%',note:null},
3:{sub:'sözlü',joy:'+2-3%',love:null,hate:'-2%',note:null},
4:{sub:'özel',joy:'+1%',love:null,hate:'-1%',note:'🎭 ⭐ Komedi'},
5:{sub:'sözlü',joy:'+2-3%',love:null,hate:'-2%',note:null},
6:{sub:'fiziksel',joy:'+5%',love:null,hate:null,note:'👶 Bebeklere'},
7:{sub:'fiziksel',joy:null,love:'+2%',hate:null,note:'🍻 Bar/Rest'},
8:{sub:'fiziksel',joy:'+2-3%',love:null,hate:null,note:null},
9:{sub:'yakın temas',joy:null,love:'+5%',hate:null,note:null},
10:{sub:'yakın temas',joy:null,love:'+5%',hate:null,note:null},
11:{sub:'cinsel',joy:'-1%',love:'+5%',hate:null,note:'🔞 ⭐ Seks | 🏠 Ev/Otel/Park'},
12:{sub:'fiziksel',joy:null,love:'+2-3%',hate:'-1%',note:null},
13:{sub:'cinsel',joy:null,love:'+2-3%',hate:null,note:'🔞 ⭐ Seks | 🏠 Ev/Otel/Park'},
14:{sub:'sözlü',joy:null,love:'+2-3%',hate:null,note:null},
15:{sub:'temel',joy:'-1%',love:null,hate:'+5%',note:null},
16:{sub:'fiziksel',joy:null,love:null,hate:'+5%',note:null},
17:{sub:'yakın temas',joy:null,love:null,hate:'+10%',note:'👊 Karşılıklı vuruş: Kalıcı sağlık kaybı 🩹'},
18:{sub:'fiziksel',joy:'+5%',love:null,hate:'-4%',note:null},
19:{sub:'cinsel',joy:'-1%',love:'+5%',hate:null,note:'🔞 ⭐ Tantrik | 🏠 Ev/Otel'},
20:{sub:'cinsel',joy:null,love:'+5%',hate:null,note:'🏠 Ev/Otel'},
21:{sub:'özel',joy:'+2-3%',love:null,hate:'-2%',note:'🎤 ⭐ Şarkı'},
22:{sub:'özel',joy:null,love:null,hate:null,note:'📔 Sadece günlük yazısı'},
24:{sub:'telefon',joy:'+2-3%',love:null,hate:'-2%',note:null},
25:{sub:'telefon',joy:null,love:'+5%',hate:null,note:null},
26:{sub:'telefon',joy:'+2-3%',love:null,hate:'-2%',note:null},
29:{sub:'özel',joy:'+2%',love:null,hate:null,note:null},
30:{sub:'fiziksel',joy:null,love:'+5%',hate:null,note:null},
32:{sub:'tıbbi',joy:'+5%',love:null,hate:'-5%',note:'🩺 ⭐ Tıp'},
33:{sub:'özel',joy:'+2-8%',love:null,hate:'-6%',note:'🪄 ⭐ İllüzyon | Düşük Yetenek arkadaşlığı düşürür'},
34:{sub:'sözlü',joy:'+5%',love:null,hate:'-4%',note:null},
35:{sub:'fiziksel',joy:null,love:'+3-7%',hate:null,note:'💃 ⭐ Dans | 🍻 Bar/Rest/Stüdyo/Lahit'},
36:{sub:'fiziksel',joy:'-4-6%',love:null,hate:'+5-7%',note:null},
37:{sub:'ölümcül',joy:'-10%',love:null,hate:'+10%',note:null},
38:{sub:'ölümcül',joy:'-5%',love:null,hate:'+10%',note:null},
39:{sub:'ruhani',joy:'+1-2%',love:null,hate:null,note:'⛪ ⭐ Din | İbadet evi'},
41:{sub:'yakın temas',joy:'-2%',love:null,hate:'+2%',note:null},
42:{sub:'fiziksel',joy:null,love:null,hate:'+5%',note:null},
44:{sub:'tıbbi',joy:'+5%',love:null,hate:'-5%',note:null},
45:{sub:'ölümcül',joy:null,love:null,hate:'+10%',note:'🔫 ⭐ Silah'},
46:{sub:'telefon',joy:'-5%',love:'-5%',hate:'+10%',note:null},
47:{sub:'sözlü',joy:'+5%',love:null,hate:'-4%',note:null},
48:{sub:'yakın temas',joy:'-2%',love:null,hate:'+3%',note:null},
49:{sub:'fiziksel',joy:'-2-4%',love:'-2-3%',hate:'+3-5%',note:null},
51:{sub:'sözlü',joy:'+5%',love:null,hate:'-5%',note:null},
52:{sub:'sözlü',joy:'+2%',love:null,hate:null,note:'🤫 👶 Bebeklere'},
54:{sub:'temel',joy:'+0-1%',love:null,hate:'-1%',note:null},
55:{sub:'fiziksel',joy:'+2-3%',love:null,hate:'-2%',note:null},
56:{sub:'yakın temas',joy:'+2-3%',love:null,hate:'-2%',note:null},
57:{sub:'sözlü',joy:'+2-3%',love:null,hate:'-2-3%',note:null},
58:{sub:'telefon',joy:'+2-3%',love:'+2%',hate:'-1%',note:null},
59:{sub:'fiziksel',joy:'+2-3%',love:null,hate:'-2%',note:null},
60:{sub:'yakın temas',joy:'+5%',love:null,hate:'-4%',note:null},
61:{sub:'telefon',joy:'+2-3%',love:null,hate:'-2%',note:null},
62:{sub:'sözlü',joy:'+5%',love:null,hate:'-4%',note:null},
63:{sub:'fiziksel',joy:'+5%',love:null,hate:'-4%',note:null},
64:{sub:'yakın temas',joy:null,love:'+5%',hate:null,note:null},
65:{sub:'sözlü',joy:'+5%',love:null,hate:'-4%',note:null},
66:{sub:'fiziksel',joy:'+5%',love:null,hate:'-4%',note:null},
67:{sub:'yakın temas',joy:'+5%',love:null,hate:'-4%',note:null},
68:{sub:'sözlü',joy:'+2%',love:null,hate:null,note:null},
69:{sub:'en iyi arkadaş',joy:'+5%',love:'-1%',hate:null,note:null},
70:{sub:'en iyi arkadaş',joy:'+5%',love:'-1%',hate:null,note:null},
71:{sub:'sözlü',joy:null,love:'+2%',hate:null,note:null},
72:{sub:'fiziksel',joy:null,love:null,hate:'+5%',note:null},
73:{sub:'telefon',joy:null,love:'+2-3%',hate:'-2%',note:null},
74:{sub:'telefon',joy:null,love:'+2-3%',hate:null,note:null},
75:{sub:'sözlü',joy:null,love:'+5%',hate:null,note:null},
76:{sub:'sözlü',joy:null,love:'+5%',hate:null,note:null},
77:{sub:'sözlü',joy:null,love:'+5%',hate:null,note:null},
78:{sub:'özel',joy:null,love:'+5%',hate:'-2%',note:'🎤 ⭐ Şarkı'},
79:{sub:'sözlü',joy:null,love:null,hate:'+2%',note:null},
80:{sub:'telefon',joy:'-2-3%',love:null,hate:'+2-3%',note:null},
81:{sub:'sözlü',joy:null,love:null,hate:'+5%',note:null},
82:{sub:'yakın temas',joy:null,love:null,hate:'+5%',note:null},
83:{sub:'telefon',joy:null,love:null,hate:'+5%',note:null},
84:{sub:'sözlü',joy:'-5%',love:null,hate:'+5%',note:null},
85:{sub:'fiziksel',joy:null,love:null,hate:'+5%',note:null},
86:{sub:'telefon',joy:'-3%',love:'+3%',hate:'+2-3%',note:null},
87:{sub:'sözlü',joy:null,love:null,hate:'+5%',note:null},
88:{sub:'yakın temas',joy:null,love:null,hate:'+5%',note:null},
89:{sub:'fiziksel',joy:null,love:'+5%',hate:null,note:'🏋️ Spor/Sahil'},
93:{sub:'yakın temas',joy:'+5%',love:null,hate:null,note:'👶 🧒 Çocuk/Bebek'},
94:{sub:'sözlü',joy:'+2%',love:null,hate:null,note:'👶 Bebeklere'},
96:{sub:'özel',joy:'+3-5%',love:null,hate:null,note:'🎤 ⭐ Şarkı | 👶 Bebeklere'},
101:{sub:'sözlü',joy:'+5%',love:null,hate:null,note:'🧒 Çocuklara'},
102:{sub:'yakın temas',joy:'+2%',love:null,hate:null,note:'🧒 Çocuklara'},
103:{sub:'yakın temas',joy:'+5%',love:null,hate:null,note:'🧒 Çocuklara'},
104:{sub:'sözlü',joy:'+5%',love:null,hate:'-4%',note:'🧒 Çocuklara'},
105:{sub:'sözlü',joy:'+2%',love:null,hate:null,note:'🧒 Çocuklara'},
115:{sub:'sözlü',joy:null,love:null,hate:'+3%',note:null},
121:{sub:'telefon',joy:'+2-3%',love:null,hate:'+2-3%',note:null},
129:{sub:'fiziksel',joy:null,love:'+5%',hate:'-3%',note:'🌲 Park/Kırsal'},
133:{sub:'fiziksel',joy:null,love:null,hate:'+5%',note:'🎓 Üniversite'},
136:{sub:'sözlü',joy:'+5%',love:null,hate:null,note:'🪦 Mezarlık'},
137:{sub:'fiziksel',joy:null,love:null,hate:'+5%',note:null},
138:{sub:'ölümcül',joy:null,love:'-10%',hate:'+10%',note:'🚗 Yol/Üni'},
139:{sub:'sözlü',joy:'+5%',love:null,hate:null,note:'📚 Okul/Üni'},
154:{sub:'sözlü',joy:null,love:'-15%',hate:null,note:'💔 Aşk 📉'},
155:{sub:'sözlü',joy:null,love:null,hate:'-15%',note:'🕊️ Nefret 📉'},
156:{sub:'sözlü',joy:'-15%',love:null,hate:null,note:'☹️ Keyif 📉'},
157:{sub:'telefon',joy:'-3%',love:'-15%',hate:null,note:null},
158:{sub:'fiziksel',joy:'+5%',love:null,hate:null,note:'🐟 Alabalık Şart'},
161:{sub:'temel',joy:null,love:'+2%',hate:null,note:null},
162:{sub:'telefon',joy:'+1%',love:null,hate:null,note:null},
164:{sub:'cinsel',joy:'-1%',love:'+5%',hate:null,note:null},
166:{sub:'sözlü',joy:'+0-3%',love:null,hate:'-3%',note:null},
171:{sub:'telefon',joy:'+2%',love:null,hate:null,note:null}
};
const INTERACT_DEFAULTS={arkadaş:[34,62,1],romantik:[35,78,10],nefret:[15,16,84],özel:[154,155,156]};
// INTERACT HELPER
const applyInteractHelper=()=>{
if(!guard(K.interact))return;
if(!location.href.includes('/Interact/'))return;
if(location.hash.includes('ppmCall'))return;
const sel=document.getElementById('ctl00_cphTopColumn_ctl00_ddlInteractionTypes');if(!sel)return;
const m=location.href.match(/\/Interact\/(?:Details\/)?(\d+)/);
const charId=m?m[1]:'0';
let curType=gmGet(DK.INTERACT_TYPE+charId,'standart');
const iData=INTERACT_DATA;
// Decorate options
[...sel.options].forEach(opt=>{
if(!opt.value||opt.value==='0')return;
const id=parseInt(opt.value),d=iData[id];if(!d)return;
const parts=[];
if(d.joy)parts.push(`😊${d.joy}`);if(d.love)parts.push(`❤️${d.love}`);if(d.hate)parts.push(`😡${d.hate}`);
const base=opt.dataset.ihBase||opt.textContent;
opt.dataset.ihBase=base;opt.dataset.ihSub=d.sub;
if(parts.length)opt.textContent=`${base} (${parts.join(' ')})`;
});
const applyFilter=type=>{
curType=type;gmSet(DK.INTERACT_TYPE+charId,type);
[...sel.options].forEach(opt=>{
if(!opt.value||opt.value==='0'){opt.style.display='';return;}
if(type==='standart'){opt.style.display='';return;}
const id=parseInt(opt.value);const d=iData[id];if(!d){opt.style.display='none';return;}
const j=d.joy||'',l=d.love||'',h=d.hate||'',s=d.sub||'';
let isMatch=false;
if(s===type)isMatch=true;
else if(type==='arkadaş'){if(j.includes('+')&&!l.includes('+')&&!h.includes('+'))isMatch=true;}
else if(type==='romantik'){if(l.includes('+')||s==='cinsel')isMatch=true;}
else if(type==='nefret'){if(h.includes('+')||(j.includes('-')&&!j.includes('+')&&!l.includes('+')))isMatch=true;}
opt.style.display=isMatch?'':'none';
});
const defIds=INTERACT_DEFAULTS[type]||[];let selected=false;
for(const did of defIds){const o=[...sel.options].find(o=>o.value===String(did)&&o.style.display!=='none');if(o){sel.value=o.value;selected=true;break;}}
if(!selected){const first=[...sel.options].find(o=>o.value!=='0'&&o.style.display!=='none');if(first)sel.value=first.value;}
};
const getLove=()=>{for(const row of document.querySelectorAll('table.width100 tr')){const lbl=row.querySelector('td.nowrap');if(!lbl)continue;if(lbl.textContent.toLowerCase().includes('roman')){const sk=row.querySelector('.sortkey');return sk?parseInt(sk.textContent)||0:0;}}return 0;};
const jealousSel=document.getElementById('ctl00_cphTopColumn_ctl00_ddlSexCausesJealousy');
const content=document.getElementById('ppm-content')||document.querySelector('.content,.col-left');if(!content)return;
const wrap=mk('div','');wrap.id='psm-ih-wrap';
const love=getLove();
if(love>=70)wrap.appendChild(Object.assign(mk('div','psm-ih-warn',s('interactWarn')),{}));
const bar=mk('div','psm-ih-bar');
const types=[['standart',s('interactAll'),''],['arkadaş',s('interactFriend'),'af'],['romantik',s('interactRom'),'ar'],['nefret',s('interactHate'),'an'],['özel','🔄 Özel','ao']];
types.forEach(([type,label,cls])=>{
const btn=mkB(label,`psm-ih-btn${curType===type?' active':''} ${cls}`.trim(),()=>{
bar.querySelectorAll('.psm-ih-btn').forEach(b=>b.classList.remove('active'));
btn.classList.add('active');applyFilter(type);
});
bar.appendChild(btn);
});
wrap.appendChild(bar);
const target=content.querySelector('table,form,select')||content.firstChild;
content.insertBefore(wrap,target);
};
// CHAR NOTE
const applyCharNote=()=>{
if(!guard(K.note))return;
const m=location.href.match(/\/Character\/(\d+)\/?$/);if(!m)return;
const charId=m[1],notes=gmGet(DK.NOTES,{})||{};
const content=document.getElementById('ppm-content')||document.querySelector('.content');if(!content)return;
const wrap=mk('div','');wrap.style.cssText='margin:10px 0;padding:8px;background:#fffde7;border:1px solid #f0c040;border-radius:8px';
const lbl=mk('div','',`📝 Not`);lbl.style.cssText='font-size:11px;font-weight:700;color:#c8900a;margin-bottom:4px';
const ta=mk('textarea','psm-cnote');ta.rows=2;ta.value=notes[charId]||'';
let timer=null;
ta.oninput=()=>{clearTimeout(timer);timer=setTimeout(()=>{const n=gmGet(DK.NOTES,{})||{};n[charId]=ta.value.trim();gmSet(DK.NOTES,n);},700);};
wrap.append(lbl,ta);
const h1=content.querySelector('h1');
if(h1)h1.insertAdjacentElement('afterend',wrap);else content.prepend(wrap);
};
// DIARY FILTER
const applyDiaryFilter=()=>{
if(!isOnDef(K.diary,false)||!location.href.includes('/Character/Diary'))return;
const entries=document.querySelectorAll('table.data tr:not(:first-child)');if(!entries.length)return;
const inp=mk('input','psm-search');inp.placeholder='🔍 Günlükte ara...';inp.style.marginBottom='10px';
inp.oninput=()=>{const q=inp.value.toLowerCase();entries.forEach(tr=>{tr.style.display=(!q||tr.textContent.toLowerCase().includes(q))?'':'none';});};
document.querySelector('table.data')?.insertAdjacentElement('beforebegin',inp);
};
// PARA BİÇİMLENDİRİCİ
const applyMoneyFormatter=()=>{
if(!guard(K.moneyFmt))return;
const SEL=['txtPriceTag','txtAmount','txtPrice','txtMoney','txtCash','txtGive','txtPT','txtWithdrawAmount','txtDepositAmount']
.map(n=>`input[id*="${n}"]`).join(',');
const fmt=v=>v.replace(/\B(?=(\d{3})+(?!\d))/g,'.');
const raw=v=>v.replace(/\./g,'');
const applyTo=inp=>{
if(inp.dataset.mfmt)return;inp.dataset.mfmt='1';
inp.addEventListener('input',()=>{
const start=inp.selectionStart,oldLen=inp.value.length;
const digits=raw(inp.value).replace(/\D/g,'');
const nv=fmt(digits);inp.value=nv;
const shift=nv.length-oldLen;inp.setSelectionRange(start+shift,start+shift);
});
const strip=()=>{inp.value=raw(inp.value);};
inp.closest('form')?.addEventListener('submit',strip);
inp.closest('form')?.querySelectorAll('input[type=submit],input[type=image],button[type=submit]').forEach(b=>b.addEventListener('click',strip));
const init=raw(inp.value||'').replace(/\D/g,'');if(init)inp.value=fmt(init);
};
document.querySelectorAll(SEL).forEach(applyTo);
let moTimer;
const obs=new MutationObserver(()=>{
clearTimeout(moTimer);
moTimer=setTimeout(()=>document.querySelectorAll(SEL).forEach(applyTo),300);
});
obs.observe(document.body,{childList:true,subtree:true});
};
// CARD LINKS (locale / artist / city / forum)
const showMiniPop=(items,anchor,title)=>{
document.querySelector('.psm-minipop')?.remove();
const pop=mk('div','psm-minipop');
pop.appendChild(mk('div','psm-minipop-title',title));
items.forEach(({label,fn})=>{
pop.appendChild(mkB(label,'psm-minipop-btn',()=>{pop.remove();fn();}));
});
const pw=Math.min(window.innerWidth*0.85,240);
const r=anchor.getBoundingClientRect();
let left=r.left;
left=Math.max(8,Math.min(left,window.innerWidth-pw-8));
let top=r.bottom+4;
if(top+220>window.innerHeight)top=Math.max(8,r.top-230);
pop.style.cssText=`left:${left}px;top:${top}px;width:${pw}px`;
document.body.appendChild(pop);
setTimeout(()=>document.addEventListener('click',e=>{if(!pop.contains(e.target))pop.remove();},{once:true,passive:true}),80);
};
const applyCardLinks=()=>{
if(!guard(K.ia))return;
const done=new WeakSet();
const copyId=(id,name,type)=>{addClip(id,name,type);navigator.clipboard?.writeText(String(id)).catch(()=>{});showToast('📋 '+id);};
const inject=()=>{
// Locale links
document.querySelectorAll('a[href*="/Locale/"]').forEach(a=>{
if(done.has(a))return;
const m=a.href.match(/\/Locale\/(\d+)\/?$/);if(!m)return;
done.add(a);
const id=m[1],name=a.textContent.trim()||id;
a.addEventListener('click',e=>{
e.preventDefault();e.stopPropagation();
showMiniPop([
{label:s('localeGo'),fn:()=>location.href=`${PM}/Locale/MoveToLocale/${id}`},
{label:s('localeVisit'),fn:()=>location.href=`${PM}/Locale/CharactersPresent/${id}`},
{label:s('copyId'),fn:()=>copyId(id,name,'locale')},
],a,`🏠 ${name}`);
});
});
// Artist links
document.querySelectorAll('a[href*="/Artist/"]').forEach(a=>{
if(done.has(a))return;
const m=a.href.match(/\/Artist\/(\d+)\/?$/);if(!m)return;
done.add(a);
const id=m[1],name=a.textContent.trim()||id;
a.addEventListener('click',e=>{
e.preventDefault();e.stopPropagation();
showMiniPop([
{label:s('artistUpcoming'),fn:()=>location.href=`${PM}/Artist/Upcoming/${id}`},
{label:s('artistRecent'),fn:()=>location.href=`${PM}/Artist/${id}`},
{label:s('copyId'),fn:()=>copyId(id,name,'artist')},
],a,`🎤 ${name}`);
});
});
// City links
document.querySelectorAll('a[href*="/City/"]').forEach(a=>{
if(done.has(a))return;
const m=a.href.match(/\/City\/(\d+)\/?$/);if(!m)return;
done.add(a);
const id=m[1],name=a.textContent.trim()||id;
a.addEventListener('click',e=>{
e.preventDefault();e.stopPropagation();
showMiniPop([
{label:s('cityFly'),fn:()=>location.href=`${PM}/Travel/Fly/${id}`},
{label:s('cityVip'),fn:()=>location.href=`${PM}/Travel/VIPJet/${id}`},
{label:s('cityBus'),fn:()=>location.href=`${PM}/Travel/Bus/${id}`},
{label:s('copyId'),fn:()=>{navigator.clipboard?.writeText(id).catch(()=>{});showToast('📋 '+id);}},
],a,`🌆 ${name}`);
});
});
// Forum/Thread links
document.querySelectorAll('a[href*="/Thread/"]').forEach(a=>{
if(done.has(a))return;
const m=a.href.match(/\/Thread\/(\d+)/);if(!m)return;
done.add(a);
const id=m[1],name=a.textContent.trim()||id;
// Forum list button already handles add-to-shelf; here just add ID copy on long press
// Only inject on non-forum-list pages to avoid duplication
if(location.href.includes('/Forum/')||location.href.includes('/Thread/'))return;
a.addEventListener('click',e=>{
e.preventDefault();e.stopPropagation();
showMiniPop([
{label:s('copyId'),fn:()=>copyId(id,name,'forum')},
{label:'🔗 Aç',fn:()=>location.href=a.href},
],a,`📋 ${name}`);
});
});
};
inject();
setTimeout(inject,800);
};
// FORUM LIST
const applyForumList=()=>{
if(!isOnDef(K.pins,true))return;
if(!location.href.includes('/Forum/')&&!location.href.includes('/Thread/'))return;
const done=new WeakSet();
const inject=()=>{
document.querySelectorAll('table.data td a[href*="/Thread/"]').forEach(link=>{
if(done.has(link))return;done.add(link);
const id=link.href.match(/\/Thread\/(\d+)/)?.[1];if(!id)return;
const btn=mkB(isForumInRaf(link.href)?'📋':'⊕','psm-frl-btn'+(isForumInRaf(link.href)?' on':''),()=>{
if(isForumInRaf(link.href)){openRaf();return;}
const sh=getShelf();
openSheet(s('addWhere'),body=>{
sh.folders['forum'].columns.forEach((col,ci)=>{
body.appendChild(mkB(`${col.name} (${col.items.length})`,'btn-grey btn-full',()=>{
addForumToRaf(id,link.textContent.trim(),link.href,ci);
btn.textContent='📋';btn.className='psm-frl-btn on';closeTopSheet();
}));
});
});
});
link.after(btn);
});
};
inject();
let moTimer;
const obs=new MutationObserver(()=>{
clearTimeout(moTimer);
moTimer=setTimeout(inject,300);
});
obs.observe(document.body,{childList:true,subtree:true});
setTimeout(()=>obs.disconnect(),5000);
};
// GENRE POPUP
const applyGenrePopup=()=>{
if(!guard(K.genrePopup))return;
if(!location.href.includes('/Character/SongToArtist/'))return;
const content=document.getElementById('ppm-content')||document.querySelector('.content');if(!content)return;
const h1=content.querySelector('h1');if(!h1)return;
const btn=mkB(s('genreBtn'),'btn-v btn-sm',()=>openSheet(s('genreTitle'),body=>{
const iframe=document.createElement('iframe');iframe.style.cssText='width:100%;height:60vh;border:none;border-radius:8px';
iframe.src=`${PM}/Charts/GenrePopularity`;body.appendChild(iframe);
}));
btn.style.cssText='display:block;margin:8px 0 12px;min-height:44px';
h1.after(btn);
};
// SERENAT HELPER
let radioRunning=false,radioCancelled=false;
const RADIO_STATIONS=[
{id:3,p:'[ROCK]'},{id:4,p:'[MR]'},{id:5,p:'[HM]'},{id:6,p:'[PUNK]'},
{id:7,p:'[ELEC]'},{id:8,p:'[POP]'},{id:9,p:'[HH]'},{id:10,p:'[R&B]'},
{id:11,p:'[REG]'},{id:12,p:'[WM]'},{id:13,p:'[C&W]'},{id:14,p:'[JAZZ]'},
{id:15,p:'[BLU]'},{id:16,p:'[CLAS]'},{id:17,p:'[LAT]'},{id:18,p:'[AM]'},{id:19,p:'[FLA]'}
];
const applySerenadeHelper=()=>{
if(!guard(K.serenadeHelper))return;
if(!location.href.includes('/Locale/RestaurantOrderSerenade/'))return;
const content=document.getElementById('ppm-content')||document.querySelector('.content');if(!content)return;
const h1=content.querySelector('h1');if(!h1)return;
const nextWed=from=>{const d=new Date(from),dow=d.getUTCDay();let days=(3-dow+7)%7;if(days===0&&d.getUTCHours()>=9)days=7;const nw=new Date(d);nw.setUTCDate(d.getUTCDate()+days);nw.setUTCHours(9,0,0,0);return nw.getTime();};
const cacheValid=ts=>!!ts&&Date.now()<nextWed(ts);
const injectPfx=()=>{
const ddl=document.getElementById('ctl00_cphLeftColumn_ctl00_ddlSerenade');if(!ddl)return;
const cache=gmGet(DK.RADIO_CACHE,null);if(!cache?.tracks)return;
[...ddl.options].forEach(opt=>{
if(!opt.value||opt.value==='0')return;
const pfx=cache.tracks[String(opt.value)];
if(pfx&&!opt.text.startsWith('['))opt.text=`${pfx} ${opt.text}`;
});
};
const doFetch=(onDone)=>{
// Check if there's already a radio task running
const existingTask = gmGet('tvis_bg_q', null);
if (existingTask && existingTask.type === 'radio' && existingTask.list && existingTask.list.length > 0) {
// Show current progress
const progInfo = mk('div');
progInfo.style.cssText = 'background:#fff3cd;border:1px solid #ffc107;border-radius:8px;padding:10px;margin-bottom:10px;font-size:12px;color:#856404';
progInfo.innerHTML = `
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
<span style="font-weight:700">📻 Radyo sıralamaları güncelleniyor...</span>
<span style="margin-left:auto">${existingTask.total - existingTask.list.length}/${existingTask.total}</span>
</div>
<div style="font-size:11px;color:#666">Sayfa değişseniz bile işlem devam edecek.</div>
`;
body.appendChild(progInfo);
return;
}
PersistentTaskManager.startTask('radio', [...RADIO_STATIONS]);
// Listen for completion
const checkComplete = setInterval(() => {
const currentTask = gmGet('tvis_bg_q', null);
if (!currentTask || !currentTask.list || currentTask.list.length === 0) {
clearInterval(checkComplete);
injectPfx();
onDone?.();
}
}, 1000);
};
let warnState=0;
const btn=mkB(s('shBtn'),'btn-v btn-sm',()=>openSheet(s('shBtn'),body=>{
const c=gmGet(DK.RADIO_CACHE,null);
if(c?.ts){
const nextWedDate=new Date(nextWed(c.ts));
const updStr=new Date(c.ts).toLocaleString([],{day:'2-digit',month:'2-digit',hour:'2-digit',minute:'2-digit'});
const nextStr=nextWedDate.toLocaleString([],{day:'2-digit',month:'2-digit',hour:'2-digit',minute:'2-digit'});
body.appendChild(Object.assign(mk('div','',`${s('shLastUpd')} ${updStr}`),{style:'font-size:11px;color:#888;margin-bottom:2px'}));
body.appendChild(Object.assign(mk('div','',`⏭ Sonraki güncelleme: ${nextStr}`),{style:'font-size:11px;color:#6f42c1;margin-bottom:6px'}));
}
const warn=mk('div','');warn.style.cssText='font-size:12px;color:#c8900a;min-height:16px;margin-bottom:4px';
body.append(warn);
body.appendChild(mkB(s('shUpdateBtn'),'btn-v btn-sm btn-full',()=>{
if(radioRunning)return;
const cached=gmGet(DK.RADIO_CACHE,null);
if(cacheValid(cached?.ts)){if(warnState===0){warnState=1;warn.textContent=s('shWarn1');return;}if(warnState===1){warnState=2;warn.textContent=s('shWarn2');return;}}
warnState=0;warn.textContent='';
doFetch(()=>{
// refresh sheet content after done
const nc=gmGet(DK.RADIO_CACHE,null);
if(!nc?.results)return;
// redraw results
body.querySelectorAll('.psm-sh-results').forEach(el=>el.remove());
renderResults(nc,body);
});
}));
const rlink=mk('a','',s('shRadioLink'));rlink.href=`${PM}/Charts/Radio/3`;rlink.target='_blank';rlink.style.cssText='font-size:12px;color:#6f42c1;display:block;margin:8px 0';
body.appendChild(rlink);
const renderResults=(c,container)=>{
if(!c?.results?.length)return;
const sec=mk('div','psm-sh-results');
sec.appendChild(mk('div','psm-sec','📻 Parça Listesi'));
c.results.forEach(r=>{
const row=mk('div','psm-sh-row');
row.appendChild(mk('span','psm-sh-pre',r.prefix));
row.appendChild(mk('span','',r.name||r.trackId));
sec.appendChild(row);
});
container.appendChild(sec);
};
renderResults(c,body);
}));
btn.style.cssText='display:block;margin:8px 0 10px;min-height:44px';
h1.after(btn);injectPfx();
};
// SPEED CALLING
const SC_DEF={interval:3,phoneIds:{arkadaş:[24,171],romantik:[73,74]}};
const getScCfg=()=>Object.assign({},SC_DEF,gmGet(DK.SPEEDCALL_CFG,{})||{});
const getScQ=()=>gmGet(DK.SPEEDCALL_Q,[])||[];
const setScQ=a=>gmSet(DK.SPEEDCALL_Q,a);
const getScSt=()=>gmGet(DK.SPEEDCALL_STATE,{idx:0,running:false,failStreak:0})||{idx:0,running:false,failStreak:0};
const setScSt=st=>gmSet(DK.SPEEDCALL_STATE,st);
const buildScQ=types=>{const sc=getSCChars();return sc.filter(c=>types.includes(c.type));};
const openSpeedCallModal=()=>{
const cfg=getScCfg(),queue=getScQ(),state=getScSt();
openSheet(s('scTitle'),(body)=>{
// SC_CHARS list with remove
body.appendChild(mk('div','psm-sec',s('scWho')));
const chkF=Object.assign(mk('input'),{type:'checkbox',checked:true});
const chkR=Object.assign(mk('input'),{type:'checkbox',checked:true});
body.appendChild(Object.assign(mk('label','psm-chk'))).append(chkF,mk('span','',s('scWhoFriend')));
body.appendChild(Object.assign(mk('label','psm-chk'))).append(chkR,mk('span','',s('scWhoRom')));
const listWrap=mk('div','psm-sc-charlist');
const refreshList=()=>{
listWrap.innerHTML='';
const inc=[];if(chkF.checked)inc.push('arkadaş');if(chkR.checked)inc.push('romantik');
const chars=getSCChars().filter(c=>inc.includes(c.type));
if(!chars.length){listWrap.appendChild(mk('div','psm-empty',s('scNoChars')));return;}
chars.forEach(c=>{
const row=mk('div','psm-sc-crow');
const chk=Object.assign(mk('input'),{type:'checkbox',checked:true});
chk.dataset.cid=c.charId;chk.dataset.type=c.type;chk.dataset.name=c.name;
const del=mkB('✕','psm-raf-del',()=>{removeSCChar(c.charId);refreshList();});
del.style.cssText='min-width:28px;min-height:28px;font-size:12px';
row.append(chk,mk('span','psm-sc-badge '+(c.type==='romantik'?'r':'a'),c.type==='romantik'?'💕':'👥'),mk('span','',c.name),del);
listWrap.appendChild(row);
});
};
chkF.onchange=refreshList;chkR.onchange=refreshList;refreshList();
body.appendChild(listWrap);
body.appendChild(mk('hr','psm-hr'));
body.appendChild(mk('div','psm-sec',s('scInterval')));
const iRow=mk('div','psm-row');
const slider=Object.assign(mk('input'),{type:'range',min:1,max:10,value:cfg.interval});
slider.style.cssText='flex:1;min-height:44px';
const iLbl=mk('span','',cfg.interval+'s');iLbl.style.cssText='min-width:28px;font-weight:700;color:#6f42c1;font-size:14px';
slider.oninput=()=>iLbl.textContent=slider.value+'s';
iRow.append(slider,iLbl);body.appendChild(iRow);
body.appendChild(mk('div','',s('scIntervalNote'))).style.cssText='font-size:11px;color:#aaa;margin-bottom:6px';
body.appendChild(mk('hr','psm-hr'));
body.appendChild(mk('div','psm-sec',s('scPhoneNote')));
const mkPRow=(lk,tk)=>{
const row=mk('div','psm-row');
row.appendChild(mk('span','',s(lk))).style.cssText='min-width:80px;font-size:12px;flex-shrink:0';
const inp=mk('input','psm-inp');inp.value=(cfg.phoneIds[tk]||[]).join(', ');inp.dataset.t=tk;inp.style.marginBottom='0';
row.appendChild(inp);body.appendChild(row);return inp;
};
const inpF=mkPRow('scFriendIds','arkadaş'),inpR=mkPRow('scRomIds','romantik');
body.appendChild(mk('hr','psm-hr'));
const btns=mk('div');btns.style.cssText='display:flex;gap:8px;flex-wrap:wrap;margin-top:8px';
const doStart=resume=>{
const nc={interval:parseInt(slider.value)||3,phoneIds:{arkadaş:inpF.value.split(',').map(x=>parseInt(x.trim())).filter(n=>!isNaN(n)),romantik:inpR.value.split(',').map(x=>parseInt(x.trim())).filter(n=>!isNaN(n))}};
gmSet(DK.SPEEDCALL_CFG,nc);
if(!resume){
const checked=[...listWrap.querySelectorAll('input[type=checkbox]:checked')];
if(!checked.length)return;
setScQ(checked.map(c=>({charId:c.dataset.cid,type:c.dataset.type,name:c.dataset.name})));
setScSt({idx:0,running:true,failStreak:0});
}else setScSt({...getScSt(),running:true,failStreak:0});
closeTopSheet();
const q=getScQ(),st=getScSt(),first=q[st.idx];if(!first)return;
location.href=`${PM}/Interact/Phone/${first.charId}#ppmCall`;
};
btns.appendChild(mkB(s('scStart'),'btn-g',()=>doStart(false)));
if(queue.length&&state.idx>0&&state.idx<queue.length)btns.appendChild(mkB(`${s('scResume')} (${state.idx}/${queue.length})`,'btn-v',()=>doStart(true)));
btns.appendChild(mkB(s('scReset'),'btn-grey btn-sm',()=>{if(!confirm(s('scReset')+'?'))return;gmDel(DK.SPEEDCALL_Q);gmDel(DK.SPEEDCALL_STATE);closeTopSheet();}));
body.appendChild(btns);
});
};
const applySpeedCall=()=>{
if((!location.href.includes('/Interact/Phone/')&&!location.href.includes('/Interact/Details/'))||!location.hash.includes('ppmCall'))return;
const state=getScSt();if(!state.running)return;
const queue=getScQ(),cfg=getScCfg(),idx=state.idx,total=queue.length,cur=queue[idx];
if(!cur){setScSt({...state,running:false});return;}
const scBarH=parseInt(getComputedStyle(document.documentElement).getPropertyValue('--sat'))||0;
document.body.style.paddingTop=`calc(env(safe-area-inset-top,0) + 52px)`;
const bar=mk('div','');bar.id='psm-sc-bar';
const statEl=mk('span','psm-sc-stat');
const timerEl=mk('span','psm-sc-timer','');
const warnEl=mk('span','psm-sc-warn','');
let handle=null,paused=false;
const stopBtn=mkB(s('scBarStop'),'psm-sc-stop',()=>{
paused=true;clearTimeout(handle);setScSt({...getScSt(),running:false});
stopBtn.style.display='none';resumeBtn.style.display='';timerEl.textContent='';
});
const resumeBtn=mkB(s('scBarResume'),'psm-sc-resume',()=>{
setScSt({...getScSt(),running:true,failStreak:0});
resumeBtn.style.display='none';stopBtn.style.display='';
warnEl.style.display='none';proceedToNext();
});
bar.append(statEl,timerEl,warnEl,stopBtn,resumeBtn);
document.body.prepend(bar);
const updStat=(name,next)=>statEl.innerHTML=`📞 <b>${idx+1}${s('scBarOf')}${total}</b> <span class="psm-sc-name">${name||cur.charId}</span>`+(next?` › ${s('scBarNext')} <span class="psm-sc-name">${next}</span>`:'');
const countdown=(secs,done)=>{let left=secs;timerEl.textContent=left+'s';const tick=()=>{left--;timerEl.textContent=left+'s';if(left<=0){timerEl.textContent='';done();}else handle=setTimeout(tick,1000);};handle=setTimeout(tick,1000);};
const proceedToNext=()=>{
const ni=getScSt().idx+1;
if(ni>=total){setScSt({...getScSt(),running:false,idx:ni});statEl.innerHTML=`✅ <b>${s('scBarDone')}</b>`;timerEl.textContent='';stopBtn.style.display='none';return;}
setScSt({...getScSt(),idx:ni});
const next=queue[ni],after=queue[ni+1];
updStat(next.name,after?.name);
countdown(Math.round(cfg.interval+Math.random()*2),()=>location.href=`${PM}/Interact/Phone/${next.charId}#ppmCall`);
};
const doFail=()=>{
const st=getScSt(),streak=(st.failStreak||0)+1;setScSt({...st,failStreak:streak});
if(streak>=2){clearTimeout(handle);paused=true;stopBtn.style.display='none';resumeBtn.style.display='';warnEl.textContent=`${s('scBarFail')}`;warnEl.style.display='';}
else proceedToNext();
};
const sel=document.querySelector('#ctl00_cphTopColumn_ctl00_ddlInteractionTypes,select[id*="ddlInteraction"]');
const btn=document.querySelector('#ctl00_cphTopColumn_ctl00_btnInteract,input[id*="btnInteract"],button[id*="btnInteract"]');
const pids=(cfg.phoneIds[cur.type]||[]).map(String);
updStat(cur.name,queue[idx+1]?.name);
let called=false;
if(sel&&pids.length){
for(const pid of pids){const opt=[...sel.options].find(o=>o.value===pid&&o.style.display!=='none');if(opt){sel.value=pid;sel.dispatchEvent(new Event('change',{bubbles:true}));if(btn){setTimeout(()=>{btn.click();called=true;setScSt({...getScSt(),failStreak:0});countdown(Math.round(cfg.interval+Math.random()*2),proceedToNext);},400);}break;}}
}
if(!called){warnEl.textContent=s('scBarNoId');warnEl.style.display='';setTimeout(doFail,600);}
};
// SETTINGS
const openSettings=()=>{
// Full-screen modal (PopControl mode) or bottom sheet (standalone)
const connected = !!document.getElementById('ppc-bar') && !document.getElementById('psm-bar')?.style.display === '';
openSheet(s('settings'), (body, close) => {
const mkRow=(label,content)=>{const r=mk('div','psm-set-row');r.append(mk('div','psm-set-label',label),content);return r;};
const mkSec=(t)=>{const d=mk('div','psm-set-sec',t);return d;};
const mkHr=()=>{const hr=mk('hr','psm-hr');return hr;};
const mkChk=(key,label,def=true)=>{
const l=mk('label','psm-chk');
const c=Object.assign(mk('input'),{type:'checkbox',checked:gmGet(key,def)!==false&&gmGet(key,def)!==0&&gmGet(key,def)!=='0'});
c.onchange=()=>gmSet(key,c.checked);
l.append(c,mk('span','',label));return l;
};
body.appendChild(mkSec('AYARLAR / SETTINGS'));
body.appendChild(mkHr());
body.appendChild(mkChk(K.charPopup, s('charCard')));
body.appendChild(mkChk(K.tracking, s('radar')));
body.appendChild(mkChk(K.interact, s('interact')));
body.appendChild(mkChk(K.ia, s('quickLinks')));
body.appendChild(mkChk(K.note, s('note')));
body.appendChild(mkChk(K.speedcall, s('speedcall')));
body.appendChild(mkHr());
body.appendChild(mkSec('ARAÇLAR'));
body.appendChild(mkChk(K.diary, s('diary')));
body.appendChild(mkChk(K.moneyFmt, s('moneyFmt')));
body.appendChild(mkChk(K.genrePopup, s('genrePopup')));
body.appendChild(mkChk(K.serenadeHelper, s('serenadeHelper')));
body.appendChild(mkHr());
// Language
body.appendChild(mkSec(s('langLabel')));
const langRow=mk('div');langRow.style.cssText='display:flex;gap:6px;margin:6px 0';
[['TR','🇹🇷'],['EN','🇬🇧'],['PT','🇧🇷']].forEach(([code,flag])=>{
const b=mkB(flag+' '+code,'btn-b btn-sm',()=>{CK.set('ppm_lang',code);close();location.reload();});
if((CK.get('ppm_lang')||'TR')===code)b.style.background='#5a30a0';
langRow.appendChild(b);
});
// Beni Oku inline with lang buttons
const smReadMe = mk('a','btn-b btn-sm','📖 Beni Oku');
smReadMe.href='https://rentry.org/SocialMobileOku'; smReadMe.target='_blank';
smReadMe.style.textDecoration='none';
langRow.appendChild(smReadMe);
body.appendChild(langRow);
// Ecosystem links
const ecosystemRow = mk('div');
ecosystemRow.style.cssText = 'background:#f0f8ff;border-radius:8px;padding:16px;margin:6px 0 12px';
ecosystemRow.innerHTML = `
<div style="display:flex;gap:15px;justify-content:center;align-items:center;flex-wrap:wrap">
<div style="display:flex;align-items:center;gap:8px">
<span style="font-size:14px">🇹🇷</span>
<a href="https://rentry.org/PopControlEkosistemi" target="_blank" style="color:#1a5276;font-weight:500;text-decoration:none;font-size:11px">Beni Oku</a>
</div>
<div style="display:flex;align-items:center;gap:8px">
<span style="font-size:14px">🇬🇧</span>
<a href="https://rentry.org/PopControlEcosystem" target="_blank" style="color:#1a5276;font-weight:500;text-decoration:none;font-size:11px">Read Me</a>
</div>
<div style="display:flex;align-items:center;gap:8px">
<span style="font-size:14px">🇧🇷</span>
<a href="https://rentry.org/EcossistemaPopControl" target="_blank" style="color:#1a5276;font-weight:500;text-decoration:none;font-size:11px">Leia-me</a>
</div>
</div>
`;
body.appendChild(ecosystemRow);
body.appendChild(mkHr());
// Save / Backup / Restore
const actRow=mk('div');actRow.style.cssText='display:flex;flex-wrap:wrap;gap:6px;margin:6px 0';
actRow.append(
mkB(s('save'),'btn-g',()=>{close();location.reload();}),
mkB(s('backup'),'btn-b btn-sm',()=>dbExport()),
mkB(s('restore'),'btn-grey btn-sm',()=>dbImport())
);
body.appendChild(actRow);
});
};
// EN strings for PopControl export
window.__ppcStrSocialMobile = {"close": "✕", "save": "✔ Save", "cancel": "Cancel", "backup": "📤 Backup", "restore": "📥 Restore", "restoreErr": "Invalid file.", "restoreQ": "What to do with current data?", "merge": "Merge", "replace": "Replace", "langLabel": "Language", "secView": "VIEW", "secSocial": "SOCIAL", "secTools": "TOOLS", "barAdd": "Add", "barShelf": "Shelf", "barClip": "Clip", "barRadar": "Radar", "barCall": "Call", "barSocial": "Social", "pins": "📌 Shelf", "charCard": "⭐ Character Card", "radar": "📍 Radar", "interact": "👋 Interaction Guide", "quickLinks": "🔗 Quick Links", "note": "📝 Char Note", "speedcall": "📞 Speed Calling", "diary": "🔍 Diary Filter", "moneyFmt": "💰 Money Formatter", "genrePopup": "🎼 Genre Popularity", "serenadeHelper": "🎵 Serenade Helper", "pinBtn": "📌 Shelf", "rafForum": "Forum", "rafArtist": "Artists", "rafLocale": "Locales", "rafCity": "Cities", "rafFav": "Favourites", "rafCol": "Column", "quickAdd": "📌 Add to Shelf", "addWhere": "Where to add?", "delEntry": "Delete this entry?", "recentTab": "🕐 Recent", "tkTitle": "📍 Radar", "tkNoChars": "No characters.", "tkStale": "⚠️ Info outdated", "tkUpdate": "🔄 Update Page", "tkUpdating": "🔄 Updating {n}/{t}", "tkUpdateDone": "✅ Radar updated", "cpAddFriend": "👥 Add as Friend", "cpAddRom": "💕 Add as Romantic", "cpAlreadyFriend": "Already added as friend.", "cpAlreadyRom": "Already added as romantic.", "cpAdded": "✅ Added", "hubPos": "Hub Position", "hubBottom": "⬇️ Bottom", "hubTop": "⬆️ Top", "hubClassic": "🔲 Classic (Hub Off)", "hubUndo": "↩ Undo", "scAskSC": "Add to Speed Calling list?", "yes": "Yes", "chTitle": "📋 Clipboard", "wtOnline": "is online!", "interactAll": "🌐 Standard", "interactFriend": "👥 Friendship", "interactRom": "💕 Romance", "interactHate": "😡 Hatred", "interactWarn": "⚠️ Romance 70+ — Jealousy risk!", "interactJYes": "Will be jealous", "interactJeal": "💘 Jealousy:", "scTitle": "📞 Speed Calling", "scInterval": "Interval (sec):", "scIntervalNote": "+ 0-2s random", "scPhoneNote": "Comma separated", "scFriendIds": "Friends:", "scRomIds": "Romantic:", "scWho": "Who to call?", "scWhoFriend": "Friends", "scWhoRom": "Romantics", "scStart": "▶ Start", "scResume": "▶ Resume", "scReset": "↺ Reset", "scNoChars": "No saved characters.", "scBarOf": "/", "scBarNext": "Next:", "scBarDone": "✅ Done!", "scBarStop": "Stop", "scBarResume": "Resume", "scBarFail": "⚠️ 2 errors", "scBarNoId": "No ID — skipped", "shBtn": "🎵 Serenade Helper", "shLastUpd": "Last update:", "shUpdateBtn": "🔄 Update", "shRadioLink": "📻 Radio Charts", "shFetching": "📻 Fetching: {n}/17", "shDone": "✅ Done!", "shWarn2": "Really update?", "genreBtn": "🎼 View Genre Popularity", "genreTitle": "🎼 Genre Popularity", "copyId": "📋 Copy ID", "cpAttitude": "Attitude", "cpState": "State", "cpOffline": "Offline", "cpRefresh": "🔄 Refresh", "cpTracked": "⭐ On Radar", "tkPageSelect": "Which page?", "tkPageMove": "Move to?", "tkRemove": "⭐ Remove from Radar", "tkPageFull": "Page full.", "localeGo": "➡️ Go", "artistUpcoming": "🎵 Upcoming Gigs", "artistRecent": "🎸 Recent Gigs", "cityFly": "✈️ Fly", "cityVip": "✈️ VIP Jet", "cityBus": "🚌 Bus"};
// ─── POPCONTROL BAĞLANTISI ────────────────────────────────────────────────────
function _hideSMBar() {
const bar = document.getElementById('psm-bar');
const col = document.getElementById('psm-hub-collapse');
const fab = document.getElementById('psm-hub-fab');
if (bar) bar.style.display = 'none';
if (col) col.style.display = 'none';
if (fab) fab.style.display = 'none';
document.body.style.paddingBottom = '';
}
function _showSMBar() {
const bar = document.getElementById('psm-bar');
const col = document.getElementById('psm-hub-collapse');
if (bar) bar.style.display = '';
if (col) col.style.display = '';
document.body.style.paddingBottom = 'calc(env(safe-area-inset-bottom,0) + 58px)';
}
function _registerSocialMobile() {
if (window.PPC_SocialMobile_Done) return;
const pc = (typeof unsafeWindow !== 'undefined' && unsafeWindow.PopControl) || window.PopControl;
if (!pc?.register) return;
try {
pc.register({
id: 'social_mobile', icon: '📱', label: 'Social Mobile',
strings: window.__ppcStrSocialMobile || {},
buttons: [
{ icon: '➕', label: s('barAdd'), onClick: ()=>quickAddToShelf() },
{ icon: '📌', label: s('barShelf'), onClick: openRaf },
{ icon: '📋', label: s('barClip'), onClick: openClip },
{ icon: '📍', label: s('barRadar'), onClick: openTrackModal },
{ icon: '📞', label: s('barCall'), onClick: openSpeedCallModal },
{ icon: '🌐', label: s('barSocial'), onClick: openSettings },
],
onUndo: () => { window.PPC_SocialMobile_Done = false; _showSMBar(); },
});
_hideSMBar();
window.PPC_SocialMobile_Done = true;
_injectSMMenuItems();
console.log('[Social Mobile] PopControl bağlantısı başarılı');
} catch(e) {
console.error('[Social Mobile] PopControl bağlantı hatası:', e);
}
}
// BAR
const MENU=[
{ico:'➕',lbl:()=>s('barAdd'),fn:quickAddToShelf,add:true},
{ico:'📌',lbl:()=>s('barShelf'),fn:openRaf},
{ico:'📋',lbl:()=>s('barClip'),fn:openClip},
{ico:'📍',lbl:()=>s('barRadar'),fn:openTrackModal},
{ico:'📞',lbl:()=>s('barCall'),fn:openSpeedCallModal},
{ico:'🌐',lbl:()=>s('barSocial'),fn:openSettings},
];
const injectBar=()=>{
if(document.getElementById('psm-bar'))return;
const mode = 'bottom'; // PopControl handles position
const bar=mk('div','');bar.id='psm-bar';
// Row 1 — Social buttons
const row1=mk('div','psm-hub-row');
MENU.forEach(item=>{
const btn=mk('button','psm-bar-btn'+(item.add?' psm-bar-add':''));btn.type='button';
btn.append(mk('span','bi',item.ico),mk('span','bl',item.lbl()));
btn.onclick=item.fn;row1.appendChild(btn);
});
bar.appendChild(row1);
document.body.appendChild(bar);
document.body.style.paddingBottom='calc(env(safe-area-inset-bottom,0) + 58px)';
const colBtn=mk('button','');colBtn.id='psm-hub-collapse';colBtn.type='button';
colBtn.textContent='▼';colBtn.title='Küçült';
colBtn.onclick=()=>{
bar.style.display='none';colBtn.style.display='none';fab.style.display='flex';
document.body.style.paddingBottom='';
};
document.body.appendChild(colBtn);
const fab=mk('button','');fab.id='psm-hub-fab';fab.type='button';
fab.textContent='🌐';fab.title='Social Hub';
fab.onclick=()=>{
bar.style.display='';colBtn.style.display='';fab.style.display='none';
document.body.style.paddingBottom='calc(env(safe-area-inset-bottom,0) + 58px)';
};
document.body.appendChild(fab);
};
// INIT
injectBar();
// Initialize persistent task manager
PersistentTaskManager.init();
// PopControl bağlantısı
document.addEventListener('PopControlReady', () => setTimeout(_registerSocialMobile, 50), { once: true });
(function _checkPC(n) {
if (window.PPC_SocialMobile_Done) return;
const pc = (typeof unsafeWindow !== 'undefined' && unsafeWindow.PopControl) || window.PopControl;
if (pc?.register) _registerSocialMobile();
else if (n < 20) setTimeout(() => _checkPC(n + 1), 150);
})(0);
// Check for any existing background tasks and resume if needed
const existingTask = gmGet('tvis_bg_q', null);
if (existingTask && existingTask.list && existingTask.list.length > 0) {
// Task will be automatically resumed by PersistentTaskManager.init()
}
applySpeedCall();
applyInteractHelper();
applyCharNote();
applyDiaryFilter();
applyGenrePopup();
applySerenadeHelper();
applyForumList();
applyMoneyFormatter();
setTimeout(()=>{applyCharPopup();applyCardLinks();},150);
// ── PUBLIC API ──────────────────────────────────────────────────────────────
window.__social_mobile_api = {
quickAdd: () => typeof quickAddToShelf === 'function' && quickAddToShelf(),
openShelf: () => typeof openRaf === 'function' && openRaf(),
openClip: () => typeof openClip === 'function' && openClip(),
openRadar: () => typeof openTrackModal === 'function' && openTrackModal(),
openSC: () => typeof openSpeedCallModal === 'function' && openSpeedCallModal(),
openSettings: () => typeof openSettings === 'function' && openSettings(),
};
// ── TOP VIP MENÜSÜ ENJEKSİYONU ──────────────────────────────────────────────
function _injectSMMenuItems() {
if (!location.href.includes('/World/Popmundo.aspx/Character')) return;
const _D2 = (tr, en, pt) => ({ TR: tr, EN: en, PT: pt }[LANG] || tr);
const smButtons = [
{ id: 'mnu-social-mobile-add', label: _D2('➕ Ekle', '➕ Add', '➕ Adicionar'), fn: () => window.__social_mobile_api?.quickAdd() },
{ id: 'mnu-social-mobile-shelf', label: _D2('📌 Rafım', '📌 Shelf', '📌 Prateleira'), fn: () => window.__social_mobile_api?.openShelf() },
{ id: 'mnu-social-mobile-clip', label: _D2('📋 Pano', '📋 Clipboard', '📋 Painel'), fn: () => window.__social_mobile_api?.openClip() },
{ id: 'mnu-social-mobile-radar', label: _D2('📍 Radar', '📍 Radar', '📍 Radar'), fn: () => window.__social_mobile_api?.openRadar() },
{ id: 'mnu-social-mobile-sc', label: _D2('📞 Speed Calling', '📞 Speed Calling', '📞 Speed Calling'), fn: () => window.__social_mobile_api?.openSC() },
{ id: 'mnu-social-mobile-settings', label: _D2('🌐 Social Mobile Ayarlar', '🌐 Social Mobile Settings','🌐 Config Mobile'), fn: () => window.__social_mobile_api?.openSettings() },
];
const _pc = (typeof unsafeWindow !== 'undefined' && unsafeWindow.PopControl) || window.PopControl;
if (_pc?.MenuManager) {
_pc.MenuManager.registerMenu({id: 'top-vip', title: '⭐ TOP VIP ⭐', position: 'above-career', items: smButtons, collapsible: true });
return;
}
// ── Standalone fallback (PopControl yoksa) ──────────────────────────
if (document.getElementById('mnu-social-mobile-add')) return;
let ul = document.querySelector('#top-vip-menu ul');
if (!ul) {
const ref = [...document.querySelectorAll('.menu h3')]
.find(h => /Kariyer|Career|Carreira/.test(h.textContent))?.closest('.menu');
if (!ref) return;
const isCol = localStorage.getItem('top-vip-collapsed') === 'true';
const h3 = Object.assign(document.createElement('h3'), { textContent: '⭐ TOP VIP ⭐' });
h3.style.cssText = 'background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;text-align:center;padding:8px;margin:0;border-radius:6px 6px 0 0;cursor:pointer;box-shadow:0 2px 8px rgba(102,126,234,.3);user-select:none;';
ul = document.createElement('ul');
ul.style.cssText = `margin:0;padding:8px 0;background:#f8f9fa;border:1px solid #e9ecef;border-top:none;border-radius:0 0 6px 6px;${isCol ? 'display:none;' : ''}`;
h3.onclick = () => { const c = ul.style.display === 'none'; ul.style.display = c ? '' : 'none'; localStorage.setItem('top-vip-collapsed', !c); };
const menu = Object.assign(document.createElement('div'), { id: 'top-vip-menu', className: 'menu' });
menu.append(h3, ul); ref.before(menu);
menu.after(Object.assign(document.createElement('div'), { style: 'height:12px' }));
}
smButtons.forEach(btn => {
if (document.getElementById(btn.id)) return;
const a = Object.assign(document.createElement('a'), { href: '#', textContent: btn.label });
a.style.cssText = 'color:#667eea;font-weight:600;text-decoration:none;display:block;padding:4px 12px;border-radius:4px;transition:all .2s;';
a.onmouseover = () => { a.style.background = '#667eea'; a.style.color = '#fff'; };
a.onmouseout = () => { a.style.background = ''; a.style.color = '#667eea'; };
a.onclick = e => { e.preventDefault(); btn.fn(); };
const li = Object.assign(document.createElement('li'), { id: btn.id }); li.style.margin = '2px 0';
li.appendChild(a); ul.appendChild(li);
});
}
_injectSMMenuItems();
} catch(e) { if (!e.message || !e.message.includes('__ppsm_device_block__')) throw e; }
})();