FF Scouter Target Finder

Quick target finder using FF Scouter API

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey, Greasemonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

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

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

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

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्क्रिप्ट व्यवस्थापक एक्स्टेंशन इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्क्रिप्ट व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्टाईल व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

// ==UserScript==
// @name         FF Scouter Target Finder
// @namespace    http://tampermonkey.net/
// @version      2.3
// @description  Quick target finder using FF Scouter API
// @author       FFScouter
// @match        https://www.torn.com/*
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @connect      ffscouter.com
// @connect      api.torn.com
// ==/UserScript==

(function() {
    'use strict';

    // PDA API Key placeholder - Torn PDA replaces this at runtime when making requests
    const PDA_API_KEY = "###PDA-APIKEY###";

    // Detect mobile/touch device
    const isMobile = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0);

    // Default configuration
    const defaultConfig = {
        apiKey: '',
        easy: {
            minFF: 1.50,
            maxFF: 2.0,
            minLevel: 1,
            maxLevel: 100
        },
        good: {
            minFF: 2.50,
            maxFF: 3.00,
            minLevel: 1,
            maxLevel: 100
        },
        factionlessOnly: false,
        inactiveOnly: true,
        openInNewTab: true,
        verifyStatus: false,
        hasUsedTap: false,
        hasUsedHold: false,
        buttonPosition: {
            right: 12,
            top: 50,
            isPercent: true
        },
        buttonVisible: true
    };

    // Load or initialize configuration
    function getConfig() {
        const saved = GM_getValue('ffscouter_config');
        if (saved) {
            try {
                const config = JSON.parse(saved);
                if (config.normal && !config.good) {
                    config.good = config.normal;
                    delete config.normal;
                }
                if (config.openInNewTab === undefined) config.openInNewTab = true;
                if (config.verifyStatus === undefined) config.verifyStatus = false;
                if (config.hasUsedTap === undefined) config.hasUsedTap = false;
                if (config.hasUsedHold === undefined) config.hasUsedHold = false;
                if (config.hasSeenHint) {
                    config.hasUsedTap = true;
                    config.hasUsedHold = true;
                    delete config.hasSeenHint;
                }
                if (!config.buttonPosition) {
                    config.buttonPosition = defaultConfig.buttonPosition;
                }
                if (config.buttonVisible === undefined) config.buttonVisible = true;
                return config;
            } catch (e) {
                return defaultConfig;
            }
        }
        return defaultConfig;
    }

    function saveConfig(config) {
        GM_setValue('ffscouter_config', JSON.stringify(config));
    }

    function getApiKey() {
        const config = getConfig();
        if (config.apiKey && /^[a-zA-Z0-9]{16}$/.test(config.apiKey)) {
            return { key: config.apiKey, source: 'manual' };
        }
        return { key: PDA_API_KEY, source: 'pda' };
    }

    // Torn-style CSS
    GM_addStyle(`
        /* ===== SETTINGS POPUP ===== */
        .ffs-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.85);
            z-index: 999999;
            display: flex;
            justify-content: center;
            align-items: center;
            font-family: Arial, Helvetica, sans-serif;
            backdrop-filter: blur(3px);
        }

        .ffs-popup {
            background: linear-gradient(180deg, #2d2d2d 0%, #1a1a1a 100%);
            border-radius: 8px;
            width: 380px;
            max-width: 95vw;
            max-height: 90vh;
            overflow-y: auto;
            box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255,255,255,0.1);
            color: #ddd;
        }

        .ffs-popup::-webkit-scrollbar {
            width: 8px;
        }

        .ffs-popup::-webkit-scrollbar-track {
            background: #1a1a1a;
        }

        .ffs-popup::-webkit-scrollbar-thumb {
            background: #444;
            border-radius: 4px;
        }

        .ffs-header {
            background: linear-gradient(180deg, #3d3d3d 0%, #2a2a2a 100%);
            padding: 16px 20px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            border-bottom: 1px solid #444;
            position: sticky;
            top: 0;
            z-index: 10;
        }

        .ffs-header-title {
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .ffs-header-title svg {
            width: 22px;
            height: 22px;
            fill: #6ac46a;
        }

        .ffs-header h2 {
            margin: 0!important;
            color: #fff;
            font-size: 15px;
            font-weight: 600;
            letter-spacing: 0.5px;
        }

        .ffs-close {
            background: rgba(255,255,255,0.1);
            border: none;
            color: #888;
            font-size: 18px;
            cursor: pointer;
            padding: 0;
            width: 28px;
            height: 28px;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.2s;
        }

        .ffs-close:hover {
            background: rgba(255,100,100,0.2);
            color: #f66;
        }

        .ffs-content {
            padding: 16px;
        }

        /* API Status Banner */
        .ffs-api-banner {
            display: flex;
            align-items: center;
            gap: 12px;
            padding: 12px 14px;
            border-radius: 6px;
            margin-bottom: 16px;
            cursor: pointer;
            transition: all 0.2s;
        }

        .ffs-api-banner svg {
            width: 20px;
            height: 20px;
            flex-shrink: 0;
        }

        .ffs-api-banner-text {
            flex: 1;
        }

        .ffs-api-banner-title {
            font-size: 12px;
            font-weight: 600;
            margin-bottom: 2px;
        }

        .ffs-api-banner-sub {
            font-size: 10px;
            opacity: 0.7;
        }

        .ffs-api-banner.manual {
            background: linear-gradient(135deg, rgba(106, 196, 106, 0.15) 0%, rgba(80, 150, 80, 0.1) 100%);
            border: 1px solid rgba(106, 196, 106, 0.3);
        }

        .ffs-api-banner.manual svg {
            fill: #6c6;
        }

        .ffs-api-banner.manual:hover {
            background: linear-gradient(135deg, rgba(106, 196, 106, 0.25) 0%, rgba(80, 150, 80, 0.15) 100%);
        }

        .ffs-api-banner.auto {
            background: linear-gradient(135deg, rgba(106, 150, 196, 0.15) 0%, rgba(80, 120, 150, 0.1) 100%);
            border: 1px solid rgba(106, 150, 196, 0.3);
        }

        .ffs-api-banner.auto svg {
            fill: #6af;
        }

        .ffs-api-banner.auto:hover {
            background: linear-gradient(135deg, rgba(106, 150, 196, 0.25) 0%, rgba(80, 120, 150, 0.15) 100%);
        }

        .ffs-api-badge {
            background: rgba(255,255,255,0.1);
            padding: 3px 8px;
            border-radius: 10px;
            font-size: 9px;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }

        .ffs-api-banner.auto .ffs-api-badge {
            background: rgba(106, 170, 255, 0.2);
            color: #6af;
        }

        .ffs-api-banner.manual .ffs-api-badge {
            background: rgba(106, 196, 106, 0.2);
            color: #6c6;
        }

        /* Target Cards */
        .ffs-target-card {
            background: rgba(0,0,0,0.2);
            border: 1px solid #333;
            border-radius: 6px;
            margin-bottom: 12px;
            overflow: hidden;
        }

        .ffs-card-header {
            display: flex;
            align-items: center;
            gap: 10px;
            padding: 10px 14px;
            background: rgba(255,255,255,0.03);
            border-bottom: 1px solid #333;
        }

        .ffs-card-icon {
            width: 32px;
            height: 32px;
            border-radius: 6px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 16px;
        }

        .ffs-card-icon.easy {
            background: linear-gradient(135deg, #4a7c4a 0%, #3a5c3a 100%);
        }

        .ffs-card-icon.good {
            background: linear-gradient(135deg, #7c6a4a 0%, #5c4a3a 100%);
        }

        .ffs-card-title {
            flex: 1;
        }

        .ffs-card-title h3 {
            margin: 0!important;
            font-size: 13px;
            font-weight: 600;
            color: #eee;
        }

        .ffs-card-title span {
            font-size: 10px;
            color: #777;
        }

        .ffs-card-body {
            padding: 12px 14px;
            display: flex;
            flex-direction: column;
            gap: 10px;
        }

        .ffs-input-row {
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .ffs-input-label {
            font-size: 11px;
            color: #999;
            width: 55px;
            flex-shrink: 0;
        }

        .ffs-input-group {
            display: flex;
            align-items: center;
            gap: 6px;
            flex: 1;
        }

        .ffs-input {
            flex: 1;
            padding: 8px 10px;
            border: 1px solid #444;
            border-radius: 4px;
            background: #252525;
            color: #fff;
            font-size: 13px;
            text-align: center;
            transition: all 0.2s;
        }

        .ffs-input:focus {
            outline: none;
            border-color: #6ac46a;
            background: #2a2a2a;
            box-shadow: 0 0 0 2px rgba(106, 196, 106, 0.1);
        }

        .ffs-input-sep {
            color: #555;
            font-size: 11px;
        }

        /* Target Count Badge */
        .ffs-card-count {
            padding: 6px 14px;
            background: rgba(0,0,0,0.2);
            border-top: 1px solid #333;
            font-size: 11px;
            color: #888;
            display: flex;
            align-items: center;
            gap: 6px;
        }

        .ffs-card-count.loading {
            color: #666;
        }

        .ffs-card-count.error {
            color: #c66;
        }

        .ffs-card-count.warning {
            color: #c96;
        }

        .ffs-card-count.good {
            color: #6a6;
        }

        .ffs-count-num {
            font-weight: 600;
            color: #aaa;
        }

        .ffs-card-count.warning .ffs-count-num {
            color: #fc6;
        }

        .ffs-card-count.good .ffs-count-num {
            color: #6c6;
        }

        .ffs-card-count.error .ffs-count-num {
            color: #c66;
        }

        .ffs-count-spinner {
            width: 12px;
            height: 12px;
            border: 2px solid #444;
            border-top-color: #888;
            border-radius: 50%;
            animation: ffs-spin 0.8s linear infinite;
        }

        @keyframes ffs-spin {
            to { transform: rotate(360deg); }
        }

        /* Options Section */
        .ffs-options {
            background: rgba(0,0,0,0.2);
            border: 1px solid #333;
            border-radius: 6px;
            overflow: hidden;
            margin-bottom: 16px;
        }

        .ffs-options-header {
            padding: 10px 14px;
            background: rgba(255,255,255,0.03);
            border-bottom: 1px solid #333;
            font-size: 11px;
            font-weight: 600;
            color: #888;
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }

        .ffs-option {
            display: flex;
            align-items: center;
            padding: 12px 14px;
            border-bottom: 1px solid #2a2a2a;
            cursor: pointer;
            transition: background 0.15s;
        }

        .ffs-option:last-child {
            border-bottom: none;
        }

        .ffs-option:hover {
            background: rgba(255,255,255,0.02);
        }

        .ffs-option-text {
            flex: 1;
            margin-left: 12px;
        }

        .ffs-option-title {
            font-size: 12px;
            color: #ddd;
        }

        .ffs-option-desc {
            font-size: 10px;
            color: #666;
            margin-top: 2px;
        }

        .ffs-option-warn {
            color: #c96;
        }

        /* Custom Toggle Switch */
        .ffs-toggle {
            position: relative;
            width: 40px;
            height: 22px;
            flex-shrink: 0;
        }

        .ffs-toggle input {
            opacity: 0;
            width: 0;
            height: 0;
        }

        .ffs-toggle-slider {
            position: absolute;
            cursor: pointer;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: #3a3a3a;
            border-radius: 22px;
            transition: 0.2s;
            border: 1px solid #444;
        }

        .ffs-toggle-slider:before {
            position: absolute;
            content: "";
            height: 16px;
            width: 16px;
            left: 2px;
            bottom: 2px;
            background: #888;
            border-radius: 50%;
            transition: 0.2s;
        }

        .ffs-toggle input:checked + .ffs-toggle-slider {
            background: #4a7c4a;
            border-color: #5a5;
        }

        .ffs-toggle input:checked + .ffs-toggle-slider:before {
            transform: translateX(18px);
            background: #fff;
        }

        /* Footer */
        .ffs-footer {
            display: flex;
            gap: 10px;
            padding: 16px;
            background: rgba(0,0,0,0.2);
            border-top: 1px solid #333;
        }

        .ffs-btn {
            flex: 1;
            padding: 12px 20px;
            border: none;
            border-radius: 6px;
            font-size: 13px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.2s;
        }

        .ffs-btn-primary {
            background: linear-gradient(180deg, #5a9 0%, #4a8 100%);
            color: #fff;
            box-shadow: 0 2px 8px rgba(90, 170, 150, 0.3);
        }

        .ffs-btn-primary:hover {
            background: linear-gradient(180deg, #6ba 0%, #5a9 100%);
            transform: translateY(-1px);
            box-shadow: 0 4px 12px rgba(90, 170, 150, 0.4);
        }

        .ffs-btn-secondary {
            background: #333;
            color: #aaa;
            border: 1px solid #444;
        }

        .ffs-btn-secondary:hover {
            background: #3a3a3a;
            color: #ddd;
        }

        /* Keyboard hints */
        .ffs-kbd-hints {
            display: ${isMobile ? 'none' : 'flex'};
            justify-content: center;
            gap: 16px;
            padding: 12px;
            background: rgba(0,0,0,0.3);
            border-top: 1px solid #333;
        }

        .ffs-kbd-hint {
            display: flex;
            align-items: center;
            gap: 6px;
            font-size: 10px;
            color: #666;
        }

        .ffs-kbd {
            background: #333;
            padding: 3px 6px;
            border-radius: 3px;
            font-family: monospace;
            font-size: 10px;
            color: #999;
            border: 1px solid #444;
        }

        /* ===== TOAST ===== */
        .ffs-toast {
            position: fixed;
            bottom: ${isMobile ? '80px' : '20px'};
            right: 20px;
            left: ${isMobile ? '20px' : 'auto'};
            padding: 14px 18px;
            border-radius: 8px;
            color: #fff;
            font-size: 13px;
            font-weight: 500;
            z-index: 9999999;
            animation: ffs-slide-in 0.3s ease;
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
            max-width: ${isMobile ? 'none' : '320px'};
        }

        .ffs-toast-success {
            background: linear-gradient(135deg, #4a7c4a 0%, #3a5c3a 100%);
        }

        .ffs-toast-error {
            background: linear-gradient(135deg, #7c4a4a 0%, #5c3a3a 100%);
        }

        .ffs-toast-info {
            background: linear-gradient(135deg, #4a5c7c 0%, #3a4a5c 100%);
        }

        .ffs-toast-warning {
            background: linear-gradient(135deg, #7c6a4a 0%, #5c4a3a 100%);
        }

        @keyframes ffs-slide-in {
            from { transform: translateY(20px); opacity: 0; }
            to { transform: translateY(0); opacity: 1; }
        }

        /* ===== FLOATING BUTTON ===== */
        .ffs-fab-container {
            position: fixed;
            z-index: 999998;
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 6px;
        }

        .ffs-fab-container.hidden {
            display: none !important;
        }

        .ffs-fab {
            width: ${isMobile ? '48px' : '42px'};
            height: ${isMobile ? '48px' : '42px'};
            border-radius: 50%;
            background: linear-gradient(135deg, #4a7c4a 0%, #3a5c3a 100%);
            border: 2px solid #5a5;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.4);
            transition: all 0.2s;
            position: relative;
            user-select: none;
            -webkit-tap-highlight-color: transparent;
        }

        .ffs-fab:hover {
            transform: scale(1.08);
            box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5);
        }

        .ffs-fab:active {
            transform: scale(0.95);
        }

        .ffs-fab svg {
            width: 22px;
            height: 22px;
            fill: #fff;
            z-index: 2;
        }

        .ffs-fab-label {
            background: rgba(0,0,0,0.7);
            color: #fc6;
            font-size: 9px;
            font-weight: 600;
            padding: 3px 8px;
            border-radius: 10px;
            white-space: nowrap;
            text-transform: uppercase;
            letter-spacing: 0.5px;
            pointer-events: none;
        }

        .ffs-fab-progress {
            position: absolute;
            top: -4px;
            left: -4px;
            width: calc(100% + 8px);
            height: calc(100% + 8px);
            transform: rotate(-90deg);
            opacity: 0;
            transition: opacity 0.1s;
        }

        .ffs-fab-progress circle {
            fill: none;
            stroke: #fff;
            stroke-width: 3;
            stroke-dasharray: 160;
            stroke-dashoffset: 160;
            stroke-linecap: round;
        }

        .ffs-fab.pressing .ffs-fab-progress {
            opacity: 1;
        }

        .ffs-fab.pressing .ffs-fab-progress circle {
            animation: ffs-progress-fill 0.5s ease-out forwards;
        }

        @keyframes ffs-progress-fill {
            to { stroke-dashoffset: 0; }
        }

        .ffs-fab-hint {
            position: absolute;
            right: calc(100% + 12px);
            top: 50%;
            transform: translateY(-50%);
            background: #222;
            color: #ddd;
            padding: 10px 14px;
            border-radius: 8px;
            font-size: 12px;
            white-space: nowrap;
            box-shadow: 0 4px 15px rgba(0,0,0,0.5);
            opacity: 0;
            pointer-events: none;
            transition: opacity 0.3s;
            border: 1px solid #444;
        }

        .ffs-fab-hint::after {
            content: '';
            position: absolute;
            right: -6px;
            top: 50%;
            transform: translateY(-50%);
            border: 6px solid transparent;
            border-left-color: #444;
        }

        .ffs-fab-hint.show {
            opacity: 1;
        }

        .ffs-fab-hint.animate {
            animation: ffs-hint-bounce 0.5s ease;
        }

        @keyframes ffs-hint-bounce {
            0%, 100% { transform: translateY(-50%) translateX(0); }
            50% { transform: translateY(-50%) translateX(-5px); }
        }

        .ffs-hint-row {
            display: flex;
            align-items: center;
            gap: 10px;
            padding: 4px 0;
        }

        .ffs-hint-action {
            background: #333;
            padding: 2px 8px;
            border-radius: 4px;
            font-size: 10px;
            color: #999;
            min-width: 40px;
            text-align: center;
        }

        .ffs-hint-result {
            color: #ddd;
        }

        .ffs-hint-result.good {
            color: #fc6;
        }

        .ffs-hint-result.menu {
            color: #aaa;
        }

        /* ===== FLOATING MENU ===== */
        .ffs-menu {
            position: fixed;
            z-index: 999997;
            background: #1c1c1c;
            border: 1px solid #444;
            border-radius: 10px;
            box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5);
            overflow: hidden;
            opacity: 0;
            pointer-events: none;
            transition: all 0.2s ease;
            min-width: 180px;
        }

        .ffs-menu.active {
            opacity: 1;
            pointer-events: auto;
            transform: scale(1);
        }

        .ffs-menu-header {
            padding: 12px 16px;
            background: linear-gradient(135deg, #4a7c4a 0%, #3a5c3a 100%);
            color: #fff;
            font-size: 12px;
            font-weight: 600;
            letter-spacing: 0.5px;
        }

        .ffs-menu-item {
            display: flex;
            align-items: center;
            gap: 12px;
            padding: 14px 16px;
            color: #ccc;
            font-size: 13px;
            cursor: pointer;
            border-bottom: 1px solid #2a2a2a;
            transition: all 0.15s;
        }

        .ffs-menu-item:last-child {
            border-bottom: none;
        }

        .ffs-menu-item:hover {
            background: rgba(255,255,255,0.05);
            color: #fff;
        }

        .ffs-menu-item:active {
            background: rgba(255,255,255,0.08);
        }

        .ffs-menu-icon {
            font-size: 16px;
            width: 20px;
            text-align: center;
        }

        .ffs-menu-text {
            flex: 1;
        }

        .ffs-menu-kbd {
            background: #333;
            padding: 3px 7px;
            border-radius: 4px;
            font-family: monospace;
            font-size: 10px;
            color: #777;
            border: 1px solid #444;
            display: ${isMobile ? 'none' : 'block'};
        }

        .ffs-menu-item.easy { color: #7c7; }
        .ffs-menu-item.easy:hover { background: rgba(106, 196, 106, 0.1); color: #9f9; }

        .ffs-menu-item.good { color: #fc6; }
        .ffs-menu-item.good:hover { background: rgba(255, 204, 102, 0.1); color: #fd8; }

        .ffs-menu-item.move { color: #6af; }
        .ffs-menu-item.move:hover { background: rgba(102, 170, 255, 0.1); color: #8cf; }

        /* ===== REPOSITION MODE ===== */
        .ffs-fab-container.repositioning {
            cursor: grab;
            z-index: 9999999;
        }

        .ffs-fab-container.repositioning.dragging {
            cursor: grabbing;
        }

        .ffs-fab-container.repositioning .ffs-fab {
            animation: ffs-pulse 1.5s ease-in-out infinite;
            border-color: #6af;
            background: linear-gradient(135deg, #4a6c9c 0%, #3a4c6c 100%);
        }

        .ffs-fab-container.repositioning .ffs-fab:hover {
            transform: none;
        }

        @keyframes ffs-pulse {
            0%, 100% { box-shadow: 0 0 0 0 rgba(102, 170, 255, 0.5), 0 4px 15px rgba(0, 0, 0, 0.4); }
            50% { box-shadow: 0 0 0 10px rgba(102, 170, 255, 0), 0 4px 15px rgba(0, 0, 0, 0.4); }
        }

        .ffs-reposition-bar {
            position: fixed;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            background: #1c1c1c;
            border: 1px solid #444;
            border-radius: 12px;
            padding: 12px 20px;
            display: flex;
            align-items: center;
            gap: 16px;
            z-index: 99999999;
            box-shadow: 0 8px 30px rgba(0, 0, 0, 0.6);
            font-family: Arial, Helvetica, sans-serif;
        }

        .ffs-reposition-text {
            color: #ddd;
            font-size: 13px;
        }

        .ffs-reposition-text span {
            color: #6af;
            font-weight: 600;
        }

        .ffs-reposition-btns {
            display: flex;
            gap: 8px;
        }

        .ffs-reposition-btn {
            padding: 8px 16px;
            border: none;
            border-radius: 6px;
            font-size: 12px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.2s;
        }

        .ffs-reposition-btn.confirm {
            background: linear-gradient(180deg, #5a9 0%, #4a8 100%);
            color: #fff;
        }

        .ffs-reposition-btn.confirm:hover {
            background: linear-gradient(180deg, #6ba 0%, #5a9 100%);
        }

        .ffs-reposition-btn.cancel {
            background: #333;
            color: #aaa;
            border: 1px solid #444;
        }

        .ffs-reposition-btn.cancel:hover {
            background: #3a3a3a;
            color: #ddd;
        }

        .ffs-reposition-btn.reset {
            background: transparent;
            color: #888;
            padding: 8px 12px;
        }

        .ffs-reposition-btn.reset:hover {
            color: #c66;
        }

        /* ===== TORN SETTINGS MENU TOGGLE ===== */
        .ffs-torn-toggle .icon-wrapper svg {
            fill: #6ac46a;
        }
    `);

    // Toast notification
    function showToast(message, type = 'info', duration = 3000) {
        const existing = document.querySelector('.ffs-toast');
        if (existing) existing.remove();

        const toast = document.createElement('div');
        toast.className = `ffs-toast ffs-toast-${type}`;
        toast.textContent = message;
        document.body.appendChild(toast);

        setTimeout(() => {
            toast.style.animation = 'ffs-slide-in 0.3s ease reverse';
            setTimeout(() => toast.remove(), 300);
        }, duration);
    }

    // API Key prompt
    function promptApiKey() {
        const config = getConfig();
        const currentKey = config.apiKey || '';

        const newKey = prompt(
            "Enter your FF Scouter API Key (16 characters):\n\nIf you don't have one: \n    Get an api key from: \n        https://www.torn.com/preferences.php#tab=api \n    then register it in: ffscouter.com\n\nTorn PDA users: Leave empty to use automatic key",
            currentKey
        );

        if (newKey === null) return;

        const trimmedKey = newKey.trim();

        if (trimmedKey === '') {
            config.apiKey = '';
            saveConfig(config);
            showToast('Using automatic API key', 'success');
            return;
        }

        if (!/^[a-zA-Z0-9]{16}$/.test(trimmedKey)) {
            showToast('Invalid key format (must be 16 characters)', 'error');
            return;
        }

        config.apiKey = trimmedKey;
        saveConfig(config);
        showToast('API key saved!', 'success');
    }

    function getRandomElement(arr) {
        return arr[Math.floor(Math.random() * arr.length)];
    }

    function shuffleArray(arr) {
        const shuffled = [...arr];
        for (let i = shuffled.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
        }
        return shuffled;
    }

    // Check target status via Torn API
    function checkTargetStatus(playerId, apiKey) {
        return new Promise((resolve) => {
            GM_xmlhttpRequest({
                method: 'GET',
                url: `https://api.torn.com/v2/user/${playerId}/basic?striptags=true&key=${apiKey}`,
                timeout: 5000,
                onload: function(response) {
                    try {
                        const data = JSON.parse(response.responseText);
                        if (data.error) {
                            resolve({ success: false, error: data.error.error || 'API error' });
                            return;
                        }
                        const state = data.profile?.status?.state;
                        const isOkay = state === 'Okay';
                        resolve({
                            success: true,
                            isOkay,
                            state,
                            status: data.profile?.status
                        });
                    } catch (e) {
                        resolve({ success: false, error: 'Parse error' });
                    }
                },
                onerror: function() {
                    resolve({ success: false, error: 'Request failed' });
                },
                ontimeout: function() {
                    resolve({ success: false, error: 'Timeout' });
                }
            });
        });
    }

    // Fetch target count for preview
    function fetchTargetCount(settings, inactiveOnly, factionlessOnly) {
        return new Promise((resolve) => {
            const { key } = getApiKey();

            const params = new URLSearchParams({
                key: key,
                minff: settings.minFF,
                maxff: settings.maxFF,
                minlevel: settings.minLevel,
                maxlevel: settings.maxLevel,
                inactiveonly: inactiveOnly ? 1 : 0,
                factionless: factionlessOnly ? 1 : 0,
                limit: 50
            });

            const url = `https://ffscouter.com/api/v1/get-targets?${params.toString()}`;

            GM_xmlhttpRequest({
                method: 'GET',
                url: url,
                timeout: 10000,
                onload: function(response) {
                    try {
                        const data = JSON.parse(response.responseText);
                        if (data.error) {
                            resolve({ success: false, error: data.error });
                            return;
                        }
                        const count = data.targets?.length || 0;
                        resolve({ success: true, count });
                    } catch (e) {
                        resolve({ success: false, error: 'Parse error' });
                    }
                },
                onerror: function() {
                    resolve({ success: false, error: 'Request failed' });
                },
                ontimeout: function() {
                    resolve({ success: false, error: 'Timeout' });
                }
            });
        });
    }

    // Find a valid target (with optional status verification)
    async function findValidTarget(targets, apiKey, verifyStatus) {
        if (!verifyStatus) {
            return { target: getRandomElement(targets), checked: 0 };
        }

        const shuffled = shuffleArray(targets);
        let checked = 0;

        for (const target of shuffled) {
            checked++;
            const status = await checkTargetStatus(target.player_id, apiKey);

            if (!status.success) {
                console.warn('FFS: Status check failed:', status.error);
                return { target, checked, verifyFailed: true };
            }

            if (status.isOkay) {
                return { target, checked };
            }

            console.log(`FFS: Target ${target.name} is ${status.state}, trying next...`);
        }

        return { target: null, checked };
    }

    // API call function
    async function fetchTarget(targetType) {
        const { key, source } = getApiKey();
        const config = getConfig();
        const settings = targetType === 'easy' ? config.easy : config.good;

        const params = new URLSearchParams({
            key: key,
            minff: settings.minFF,
            maxff: settings.maxFF,
            minlevel: settings.minLevel,
            maxlevel: settings.maxLevel,
            inactiveonly: config.inactiveOnly ? 1 : 0,
            factionless: config.factionlessOnly ? 1 : 0,
            limit: 50
        });

        const url = `https://ffscouter.com/api/v1/get-targets?${params.toString()}`;

        showToast(`Finding ${targetType} target...`, 'info');

        GM_xmlhttpRequest({
            method: 'GET',
            url: url,
            onload: async function(response) {
                try {
                    const data = JSON.parse(response.responseText);

                    if (data.error) {
                        if (source === 'pda' && (data.error.includes('key') || data.error.includes('API') || data.error.includes('auth'))) {
                            showToast('API key required - not using Torn PDA?', 'error');
                            setTimeout(() => promptApiKey(), 1000);
                        } else {
                            showToast(`Error: ${data.error}`, 'error');
                        }
                        return;
                    }

                    if (!data.targets || data.targets.length === 0) {
                        showToast('No targets found with current filters', 'error');
                        return;
                    }

                    const targetCount = data.targets.length;

                    if (targetCount < 10) {
                        showToast(`Warning: Only ${targetCount} target${targetCount === 1 ? '' : 's'} available. Consider adjusting filters.`, 'warning');
                        await new Promise(r => setTimeout(r, 1500));
                    }

                    const verifyStatus = config.verifyStatus;
                    if (verifyStatus) {
                        showToast('Verifying target status...', 'info');
                    }

                    const result = await findValidTarget(data.targets, key, verifyStatus);

                    if (!result.target) {
                        showToast(`No available targets found (checked ${result.checked})`, 'error');
                        return;
                    }

                    if (result.verifyFailed) {
                        showToast('Status check failed, using unverified target', 'warning');
                        await new Promise(r => setTimeout(r, 1000));
                    }

                    const target = result.target;
                    const attackUrl = `https://www.torn.com/loader.php?sid=attack&user2ID=${target.player_id}`;

                    let message = `${target.name} [${target.player_id}] • Lvl ${target.level} • FF ${target.fair_fight.toFixed(2)}`;
                    if (verifyStatus && result.checked > 1) {
                        message += ` (${result.checked} checked)`;
                    }
                    showToast(message, 'success');

                    if (config.openInNewTab) {
                        window.open(attackUrl, '_blank');
                    } else {
                        window.location.href = attackUrl;
                    }
                } catch (e) {
                    showToast('Failed to parse response', 'error');
                    console.error('FFS Error:', e);
                }
            },
            onerror: function(error) {
                showToast('Request failed - check connection', 'error');
                console.error('FFS Error:', error);
            }
        });
    }

    // Reposition mode
    let isRepositioning = false;
    let originalPosition = null;

    function enterRepositionMode() {
        if (isRepositioning) return;
        isRepositioning = true;

        const container = document.querySelector('.ffs-fab-container');
        const floatingMenu = document.querySelector('.ffs-menu');
        if (floatingMenu) floatingMenu.classList.remove('active');

        const config = getConfig();
        originalPosition = { ...config.buttonPosition };

        container.classList.add('repositioning');

        // Create instruction bar
        const bar = document.createElement('div');
        bar.className = 'ffs-reposition-bar';
        bar.innerHTML = `
            <div class="ffs-reposition-text"><span>Drag</span> the button to move it</div>
            <div class="ffs-reposition-btns">
                <button class="ffs-reposition-btn reset">Reset</button>
                <button class="ffs-reposition-btn cancel">Cancel</button>
                <button class="ffs-reposition-btn confirm">Save</button>
            </div>
        `;
        document.body.appendChild(bar);

        // Dragging state
        let isDragging = false;
        let startX, startY;
        let startLeft, startTop;

        const getContainerPosition = () => {
            const rect = container.getBoundingClientRect();
            return {
                left: rect.left,
                top: rect.top
            };
        };

        const onDragStart = (e) => {
            e.preventDefault();
            isDragging = true;
            container.classList.add('dragging');

            const pos = getContainerPosition();
            startLeft = pos.left;
            startTop = pos.top;

            if (e.type === 'touchstart') {
                startX = e.touches[0].clientX;
                startY = e.touches[0].clientY;
            } else {
                startX = e.clientX;
                startY = e.clientY;
            }
        };

        const onDragMove = (e) => {
            if (!isDragging) return;
            e.preventDefault();

            let clientX, clientY;
            if (e.type === 'touchmove') {
                clientX = e.touches[0].clientX;
                clientY = e.touches[0].clientY;
            } else {
                clientX = e.clientX;
                clientY = e.clientY;
            }

            const deltaX = clientX - startX;
            const deltaY = clientY - startY;

            let newLeft = startLeft + deltaX;
            let newTop = startTop + deltaY;

            // Constrain to viewport
            const fabSize = isMobile ? 48 : 42;
            const padding = 8;
            newLeft = Math.max(padding, Math.min(window.innerWidth - fabSize - padding, newLeft));
            newTop = Math.max(padding, Math.min(window.innerHeight - fabSize - padding, newTop));

            // Apply position
            container.style.left = newLeft + 'px';
            container.style.top = newTop + 'px';
            container.style.right = 'auto';
            container.style.transform = 'none';
        };

        const onDragEnd = () => {
            if (!isDragging) return;
            isDragging = false;
            container.classList.remove('dragging');
        };

        // Add drag listeners
        container.addEventListener('mousedown', onDragStart);
        document.addEventListener('mousemove', onDragMove);
        document.addEventListener('mouseup', onDragEnd);

        container.addEventListener('touchstart', onDragStart, { passive: false });
        document.addEventListener('touchmove', onDragMove, { passive: false });
        document.addEventListener('touchend', onDragEnd);

        const cleanup = () => {
            container.removeEventListener('mousedown', onDragStart);
            document.removeEventListener('mousemove', onDragMove);
            document.removeEventListener('mouseup', onDragEnd);
            container.removeEventListener('touchstart', onDragStart);
            document.removeEventListener('touchmove', onDragMove);
            document.removeEventListener('touchend', onDragEnd);
            document.removeEventListener('keydown', escHandler);
            bar.remove();
            container.classList.remove('repositioning', 'dragging');
            isRepositioning = false;
        };

        const savePosition = () => {
            const rect = container.getBoundingClientRect();
            const config = getConfig();

            // Calculate position from right and top percentage for responsiveness
            config.buttonPosition = {
                right: window.innerWidth - rect.right,
                top: (rect.top / window.innerHeight) * 100,
                isPercent: true
            };

            saveConfig(config);
            applyButtonPosition();
            cleanup();
            showToast('Button position saved!', 'success');
        };

        const cancelReposition = () => {
            applyButtonPosition(originalPosition);
            cleanup();
        };

        const resetPosition = () => {
            const config = getConfig();
            config.buttonPosition = { ...defaultConfig.buttonPosition };
            saveConfig(config);
            applyButtonPosition();
            cleanup();
            showToast('Button position reset!', 'info');
        };

        bar.querySelector('.confirm').addEventListener('click', savePosition);
        bar.querySelector('.cancel').addEventListener('click', cancelReposition);
        bar.querySelector('.reset').addEventListener('click', resetPosition);

        const escHandler = (e) => {
            if (e.key === 'Escape') {
                cancelReposition();
            }
        };
        document.addEventListener('keydown', escHandler);
    }

    function applyButtonPosition(customPosition = null) {
        const container = document.querySelector('.ffs-fab-container');
        if (!container) return;

        const config = getConfig();
        const pos = customPosition || config.buttonPosition;

        container.style.right = pos.right + 'px';
        container.style.left = 'auto';

        if (pos.isPercent) {
            container.style.top = pos.top + '%';
            container.style.transform = 'translateY(-50%)';
        } else {
            container.style.top = pos.top + 'px';
            container.style.transform = 'none';
        }
    }

    function updateMenuPosition() {
        const container = document.querySelector('.ffs-fab-container');
        const menu = document.querySelector('.ffs-menu');
        if (!container || !menu) return;

        const rect = container.getBoundingClientRect();
        const menuWidth = 180;
        const menuHeight = menu.offsetHeight || 250;

        // Decide whether to show menu on left or right of button
        let menuLeft;
        if (rect.left > menuWidth + 20) {
            // Show on left
            menuLeft = rect.left - menuWidth - 10;
        } else {
            // Show on right
            menuLeft = rect.right + 10;
        }

        // Vertical positioning
        let menuTop = rect.top + (rect.height / 2) - (menuHeight / 2);
        menuTop = Math.max(10, Math.min(window.innerHeight - menuHeight - 10, menuTop));

        menu.style.left = menuLeft + 'px';
        menu.style.top = menuTop + 'px';
        menu.style.right = 'auto';
        menu.style.transform = 'scale(1)';
    }

    // Button visibility
    function updateButtonVisibility() {
        const container = document.querySelector('.ffs-fab-container');
        const menu = document.querySelector('.ffs-menu');
        if (!container) return;

        const config = getConfig();
        if (config.buttonVisible) {
            container.classList.remove('hidden');
        } else {
            container.classList.add('hidden');
            if (menu) menu.classList.remove('active');
        }
    }

    // Inject toggle into Torn's settings menu
    function injectSettingsToggle() {
        const settingsMenu = document.querySelector('ul.settings-menu');
        if (!settingsMenu || document.getElementById('ffs-button-state')) return;

        const config = getConfig();

        const li = document.createElement('li');
        li.className = 'setting ffs-torn-toggle';
        li.innerHTML = `
            <label for="ffs-button-state" class="setting-container">
                <div class="icon-wrapper">
                    <svg viewBox="0 0 24 24" width="22" height="22"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>
                </div>
                <span class="setting-name">FF Scouter</span>
                <div class="choice-container">
                    <input id="ffs-button-state" class="checkbox-css dark-bg" type="checkbox" ${config.buttonVisible ? 'checked' : ''}>
                    <label class="marker-css" for="ffs-button-state"></label>
                </div>
            </label>
        `;

        // Insert before the Settings link
        const settingsLink = settingsMenu.querySelector('li.link a[href="/preferences.php"]');
        if (settingsLink && settingsLink.parentElement) {
            settingsMenu.insertBefore(li, settingsLink.parentElement);
        } else {
            // Fallback: insert before logout
            const logoutLink = settingsMenu.querySelector('li.link a[href^="/logout.php"]');
            if (logoutLink && logoutLink.parentElement) {
                settingsMenu.insertBefore(li, logoutLink.parentElement);
            } else {
                settingsMenu.appendChild(li);
            }
        }

        // Add event listener
        document.getElementById('ffs-button-state').addEventListener('change', (e) => {
            const cfg = getConfig();
            cfg.buttonVisible = e.target.checked;
            saveConfig(cfg);
            updateButtonVisibility();

            if (!e.target.checked) {
                showToast('FF Scouter button hidden. Re-enable from profile menu.', 'info', 4000);
            } else {
                showToast('FF Scouter button visible', 'success');
            }
        });
    }

    // Configuration popup
    function showConfigPopup() {
        const existing = document.querySelector('.ffs-overlay');
        if (existing) existing.remove();

        const floatingMenu = document.querySelector('.ffs-menu');
        if (floatingMenu) floatingMenu.classList.remove('active');

        const config = getConfig();
        const { source } = getApiKey();
        const isManual = source === 'manual';

        const overlay = document.createElement('div');
        overlay.className = 'ffs-overlay';
        overlay.innerHTML = `
            <div class="ffs-popup">
                <div class="ffs-header">
                    <div class="ffs-header-title">
                        <svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>
                        <h2>FF Scouter</h2>
                    </div>
                    <button class="ffs-close" id="ffs-close">✕</button>
                </div>

                <div class="ffs-content">
                    <div class="ffs-api-banner ${isManual ? 'manual' : 'auto'}" id="ffs-api-btn">
                        <svg viewBox="0 0 24 24"><path d="M12.65 10C11.83 7.67 9.61 6 7 6c-3.31 0-6 2.69-6 6s2.69 6 6 6c2.61 0 4.83-1.67 5.65-4H17v4h4v-4h2v-4H12.65zM7 14c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></svg>
                        <div class="ffs-api-banner-text">
                            <div class="ffs-api-banner-title">${isManual ? 'Manual API Key' : 'Automatic (Torn PDA)'}</div>
                            <div class="ffs-api-banner-sub">${isManual ? 'Click to change or use automatic' : 'Click to set manual key instead'}</div>
                        </div>
                        <span class="ffs-api-badge">${isManual ? 'Manual' : 'Auto'}</span>
                    </div>

                    <div class="ffs-target-card" id="ffs-easy-card">
                        <div class="ffs-card-header">
                            <div class="ffs-card-icon easy">⚡</div>
                            <div class="ffs-card-title">
                                <h3>Easy Targets</h3>
                                <span>${isMobile ? 'Via menu' : 'Press F1'}</span>
                            </div>
                        </div>
                        <div class="ffs-card-body">
                            <div class="ffs-input-row">
                                <span class="ffs-input-label">Fair Fight</span>
                                <div class="ffs-input-group">
                                    <input type="number" class="ffs-input ffs-easy-input" id="ffs-easy-minff" value="${config.easy.minFF}" step="0.1" min="1" max="3">
                                    <span class="ffs-input-sep">→</span>
                                    <input type="number" class="ffs-input ffs-easy-input" id="ffs-easy-maxff" value="${config.easy.maxFF}" step="0.1" min="1" max="3">
                                </div>
                            </div>
                            <div class="ffs-input-row">
                                <span class="ffs-input-label">Level</span>
                                <div class="ffs-input-group">
                                    <input type="number" class="ffs-input ffs-easy-input" id="ffs-easy-minlvl" value="${config.easy.minLevel}" min="1" max="100">
                                    <span class="ffs-input-sep">→</span>
                                    <input type="number" class="ffs-input ffs-easy-input" id="ffs-easy-maxlvl" value="${config.easy.maxLevel}" min="1" max="100">
                                </div>
                            </div>
                        </div>
                        <div class="ffs-card-count loading" id="ffs-easy-count">
                            <div class="ffs-count-spinner"></div>
                            <span>Checking available targets...</span>
                        </div>
                    </div>

                    <div class="ffs-target-card" id="ffs-good-card">
                        <div class="ffs-card-header">
                            <div class="ffs-card-icon good">🔥</div>
                            <div class="ffs-card-title">
                                <h3>Good Targets</h3>
                                <span>${isMobile ? 'Tap button' : 'Press F2'}</span>
                            </div>
                        </div>
                        <div class="ffs-card-body">
                            <div class="ffs-input-row">
                                <span class="ffs-input-label">Fair Fight</span>
                                <div class="ffs-input-group">
                                    <input type="number" class="ffs-input ffs-good-input" id="ffs-good-minff" value="${config.good.minFF}" step="0.1" min="1" max="3">
                                    <span class="ffs-input-sep">→</span>
                                    <input type="number" class="ffs-input ffs-good-input" id="ffs-good-maxff" value="${config.good.maxFF}" step="0.1" min="1" max="3">
                                </div>
                            </div>
                            <div class="ffs-input-row">
                                <span class="ffs-input-label">Level</span>
                                <div class="ffs-input-group">
                                    <input type="number" class="ffs-input ffs-good-input" id="ffs-good-minlvl" value="${config.good.minLevel}" min="1" max="100">
                                    <span class="ffs-input-sep">→</span>
                                    <input type="number" class="ffs-input ffs-good-input" id="ffs-good-maxlvl" value="${config.good.maxLevel}" min="1" max="100">
                                </div>
                            </div>
                        </div>
                        <div class="ffs-card-count loading" id="ffs-good-count">
                            <div class="ffs-count-spinner"></div>
                            <span>Checking available targets...</span>
                        </div>
                    </div>

                    <div class="ffs-options">
                        <div class="ffs-options-header">Filters</div>
                        <label class="ffs-option">
                            <div class="ffs-toggle">
                                <input type="checkbox" id="ffs-inactive" class="ffs-filter-toggle" ${config.inactiveOnly ? 'checked' : ''}>
                                <span class="ffs-toggle-slider"></span>
                            </div>
                            <div class="ffs-option-text">
                                <div class="ffs-option-title">Inactive Only</div>
                                <div class="ffs-option-desc">Target players inactive 14+ days</div>
                            </div>
                        </label>
                        <label class="ffs-option">
                            <div class="ffs-toggle">
                                <input type="checkbox" id="ffs-factionless" class="ffs-filter-toggle" ${config.factionlessOnly ? 'checked' : ''}>
                                <span class="ffs-toggle-slider"></span>
                            </div>
                            <div class="ffs-option-text">
                                <div class="ffs-option-title">Factionless Only</div>
                                <div class="ffs-option-desc">Target players without a faction</div>
                            </div>
                        </label>
                        <label class="ffs-option">
                            <div class="ffs-toggle">
                                <input type="checkbox" id="ffs-verify" ${config.verifyStatus ? 'checked' : ''}>
                                <span class="ffs-toggle-slider"></span>
                            </div>
                            <div class="ffs-option-text">
                                <div class="ffs-option-title">Verify Status</div>
                                <div class="ffs-option-desc">Check target is okay <span class="ffs-option-warn">(slower)</span></div>
                            </div>
                        </label>
                    </div>

                    <div class="ffs-options">
                        <div class="ffs-options-header">Behavior</div>
                        <label class="ffs-option">
                            <div class="ffs-toggle">
                                <input type="checkbox" id="ffs-newtab" ${config.openInNewTab ? 'checked' : ''}>
                                <span class="ffs-toggle-slider"></span>
                            </div>
                            <div class="ffs-option-text">
                                <div class="ffs-option-title">Open in New Tab</div>
                                <div class="ffs-option-desc">Open attack page in a new browser tab</div>
                            </div>
                        </label>
                        <div class="ffs-option" id="ffs-move-btn" style="cursor: pointer;">
                            <div style="width: 40px; height: 22px; display: flex; align-items: center; justify-content: center;">
                                <span style="font-size: 18px;">📍</span>
                            </div>
                            <div class="ffs-option-text">
                                <div class="ffs-option-title">Move Button</div>
                                <div class="ffs-option-desc">Drag the floating button to a new position</div>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="ffs-footer">
                    <button class="ffs-btn ffs-btn-secondary" id="ffs-cancel">Cancel</button>
                    <button class="ffs-btn ffs-btn-primary" id="ffs-save">Save Settings</button>
                </div>

                <div class="ffs-kbd-hints">
                    <div class="ffs-kbd-hint"><span class="ffs-kbd">F1</span> Easy</div>
                    <div class="ffs-kbd-hint"><span class="ffs-kbd">F2</span> Good</div>
                    <div class="ffs-kbd-hint"><span class="ffs-kbd">F3</span> API Key</div>
                    <div class="ffs-kbd-hint"><span class="ffs-kbd">F4</span> Settings</div>
                </div>
            </div>
        `;

        document.body.appendChild(overlay);

        // Target count update functions
        let easyDebounce = null;
        let goodDebounce = null;

        function updateCountDisplay(elementId, result) {
            const el = document.getElementById(elementId);
            if (!el) return;

            if (!result.success) {
                el.className = 'ffs-card-count error';
                el.innerHTML = `<span class="ffs-count-num">!</span> <span>${result.error}</span>`;
                return;
            }

            const count = result.count;
            let statusClass = 'good';
            let statusText = 'targets available';

            if (count === 0) {
                statusClass = 'error';
                statusText = 'No targets found';
            } else if (count < 10) {
                statusClass = 'warning';
                statusText = count === 1 ? 'target available (very low!)' : 'targets available (low!)';
            } else if (count == 50) {
                statusText = 'targets available (max)';
            }

            el.className = `ffs-card-count ${statusClass}`;
            el.innerHTML = `<span class="ffs-count-num">${count}</span> <span>${statusText}</span>`;
        }

        function setCountLoading(elementId) {
            const el = document.getElementById(elementId);
            if (!el) return;
            el.className = 'ffs-card-count loading';
            el.innerHTML = '<div class="ffs-count-spinner"></div> <span>Checking...</span>';
        }

        function getFormSettings(type) {
            const prefix = type === 'easy' ? 'ffs-easy' : 'ffs-good';
            return {
                minFF: parseFloat(document.getElementById(`${prefix}-minff`).value) || 1,
                maxFF: parseFloat(document.getElementById(`${prefix}-maxff`).value) || 3,
                minLevel: parseInt(document.getElementById(`${prefix}-minlvl`).value) || 1,
                maxLevel: parseInt(document.getElementById(`${prefix}-maxlvl`).value) || 100
            };
        }

        function getFormFilters() {
            return {
                inactiveOnly: document.getElementById('ffs-inactive').checked,
                factionlessOnly: document.getElementById('ffs-factionless').checked
            };
        }

        async function refreshEasyCount() {
            setCountLoading('ffs-easy-count');
            const settings = getFormSettings('easy');
            const filters = getFormFilters();
            const result = await fetchTargetCount(settings, filters.inactiveOnly, filters.factionlessOnly);
            updateCountDisplay('ffs-easy-count', result);
        }

        async function refreshGoodCount() {
            setCountLoading('ffs-good-count');
            const settings = getFormSettings('good');
            const filters = getFormFilters();
            const result = await fetchTargetCount(settings, filters.inactiveOnly, filters.factionlessOnly);
            updateCountDisplay('ffs-good-count', result);
        }

        async function refreshBothCounts() {
            await Promise.all([refreshEasyCount(), refreshGoodCount()]);
        }

        // Debounced refresh for easy inputs
        function debouncedRefreshEasy() {
            clearTimeout(easyDebounce);
            easyDebounce = setTimeout(refreshEasyCount, 300);
        }

        // Debounced refresh for good inputs
        function debouncedRefreshGood() {
            clearTimeout(goodDebounce);
            goodDebounce = setTimeout(refreshGoodCount, 300);
        }

        // Add blur listeners to easy inputs
        document.querySelectorAll('.ffs-easy-input').forEach(input => {
            input.addEventListener('blur', debouncedRefreshEasy);
            input.addEventListener('keydown', (e) => {
                if (e.key === 'Enter') {
                    e.target.blur();
                }
            });
        });

        // Add blur listeners to good inputs
        document.querySelectorAll('.ffs-good-input').forEach(input => {
            input.addEventListener('blur', debouncedRefreshGood);
            input.addEventListener('keydown', (e) => {
                if (e.key === 'Enter') {
                    e.target.blur();
                }
            });
        });

        // Add change listeners to filter toggles
        document.querySelectorAll('.ffs-filter-toggle').forEach(toggle => {
            toggle.addEventListener('change', refreshBothCounts);
        });

        // Initial count fetch
        refreshBothCounts();

        const closePopup = () => {
            clearTimeout(easyDebounce);
            clearTimeout(goodDebounce);
            overlay.remove();
        };

        overlay.addEventListener('click', (e) => {
            if (e.target === overlay) closePopup();
        });

        document.getElementById('ffs-close').addEventListener('click', closePopup);
        document.getElementById('ffs-cancel').addEventListener('click', closePopup);
        document.getElementById('ffs-api-btn').addEventListener('click', () => {
            closePopup();
            promptApiKey();
        });

        document.getElementById('ffs-move-btn').addEventListener('click', () => {
            closePopup();
            setTimeout(() => enterRepositionMode(), 100);
        });

        document.getElementById('ffs-save').addEventListener('click', () => {
            const currentConfig = getConfig();

            const newConfig = {
                apiKey: currentConfig.apiKey,
                easy: {
                    minFF: parseFloat(document.getElementById('ffs-easy-minff').value) || 1.50,
                    maxFF: parseFloat(document.getElementById('ffs-easy-maxff').value) || 2.00,
                    minLevel: parseInt(document.getElementById('ffs-easy-minlvl').value) || 1,
                    maxLevel: parseInt(document.getElementById('ffs-easy-maxlvl').value) || 100
                },
                good: {
                    minFF: parseFloat(document.getElementById('ffs-good-minff').value) || 2.50,
                    maxFF: parseFloat(document.getElementById('ffs-good-maxff').value) || 3.00,
                    minLevel: parseInt(document.getElementById('ffs-good-minlvl').value) || 1,
                    maxLevel: parseInt(document.getElementById('ffs-good-maxlvl').value) || 100
                },
                inactiveOnly: document.getElementById('ffs-inactive').checked,
                factionlessOnly: document.getElementById('ffs-factionless').checked,
                verifyStatus: document.getElementById('ffs-verify').checked,
                openInNewTab: document.getElementById('ffs-newtab').checked,
                hasUsedTap: currentConfig.hasUsedTap,
                hasUsedHold: currentConfig.hasUsedHold,
                buttonPosition: currentConfig.buttonPosition,
                buttonVisible: currentConfig.buttonVisible
            };

            if (newConfig.easy.minFF > newConfig.easy.maxFF) {
                showToast('Easy: Min FF cannot exceed Max', 'error');
                return;
            }
            if (newConfig.good.minFF > newConfig.good.maxFF) {
                showToast('Good: Min FF cannot exceed Max', 'error');
                return;
            }
            if (newConfig.easy.minLevel > newConfig.easy.maxLevel) {
                showToast('Easy: Min Level cannot exceed Max', 'error');
                return;
            }
            if (newConfig.good.minLevel > newConfig.good.maxLevel) {
                showToast('Good: Min Level cannot exceed Max', 'error');
                return;
            }

            saveConfig(newConfig);
            showToast('Settings saved!', 'success');
            closePopup();
        });

        const escHandler = (e) => {
            if (e.key === 'Escape') {
                closePopup();
                document.removeEventListener('keydown', escHandler);
            }
        };
        document.addEventListener('keydown', escHandler);
    }

    // Create floating button
    function createFloatingButton() {
        const container = document.createElement('div');
        container.className = 'ffs-fab-container';

        const config = getConfig();
        const showInitialHint = !config.hasUsedTap || !config.hasUsedHold;

        container.innerHTML = `
            <div class="ffs-fab" title="Tap: Good Target • Hold: Menu">
                <svg class="ffs-fab-progress" viewBox="0 0 52 52">
                    <circle cx="26" cy="26" r="24"/>
                </svg>
                <svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></svg>
                <div class="ffs-fab-hint ${showInitialHint ? 'show animate' : ''}" id="ffs-hint">
                    <div class="ffs-hint-row">
                        <span class="ffs-hint-action">Tap</span>
                        <span class="ffs-hint-result good">🔥 Good Target</span>
                    </div>
                    <div class="ffs-hint-row">
                        <span class="ffs-hint-action">Hold</span>
                        <span class="ffs-hint-result menu">☰ More Options</span>
                    </div>
                </div>
            </div>
        `;

        const floatingMenu = document.createElement('div');
        floatingMenu.className = 'ffs-menu';
        floatingMenu.innerHTML = `
            <div class="ffs-menu-header">FF Scouter</div>
            <div class="ffs-menu-item easy" data-action="easy">
                <span class="ffs-menu-icon">⚡</span>
                <span class="ffs-menu-text">Easy Target</span>
                <span class="ffs-menu-kbd">F1</span>
            </div>
            <div class="ffs-menu-item good" data-action="good">
                <span class="ffs-menu-icon">🔥</span>
                <span class="ffs-menu-text">Good Target</span>
                <span class="ffs-menu-kbd">F2</span>
            </div>
            <div class="ffs-menu-item" data-action="apikey">
                <span class="ffs-menu-icon">🔑</span>
                <span class="ffs-menu-text">API Key</span>
                <span class="ffs-menu-kbd">F3</span>
            </div>
            <div class="ffs-menu-item" data-action="settings">
                <span class="ffs-menu-icon">⚙️</span>
                <span class="ffs-menu-text">Settings</span>
                <span class="ffs-menu-kbd">F4</span>
            </div>
            <div class="ffs-menu-item move" data-action="move">
                <span class="ffs-menu-icon">📍</span>
                <span class="ffs-menu-text">Move Button</span>
                <span class="ffs-menu-kbd"></span>
            </div>
        `;

        document.body.appendChild(container);
        document.body.appendChild(floatingMenu);

        // Apply saved position and visibility
        applyButtonPosition();
        updateButtonVisibility();

        const fab = container.querySelector('.ffs-fab');
        const hint = container.querySelector('#ffs-hint');
        let hintTimeout = null;

        function shouldShowHints() {
            const cfg = getConfig();
            return !cfg.hasUsedTap || !cfg.hasUsedHold;
        }

        const hideHint = () => {
            hint.classList.remove('show', 'animate');
        };

        const showHint = (animate = false) => {
            if (shouldShowHints()) {
                hint.classList.add('show');
                if (animate) hint.classList.add('animate');
            }
        };

        if (showInitialHint) {
            hintTimeout = setTimeout(() => {
                hideHint();
            }, isMobile ? 8000 : 6000);
        }

        if (!isMobile) {
            fab.addEventListener('mouseenter', () => {
                if (shouldShowHints()) {
                    clearTimeout(hintTimeout);
                    showHint(false);
                }
            });
            fab.addEventListener('mouseleave', () => {
                if (!fab.classList.contains('pressing')) {
                    hideHint();
                }
            });
        }

        let pressTimer = null;
        let isLongPress = false;
        const LONG_PRESS_DURATION = 500;

        const startPress = (e) => {
            if (isRepositioning) return;
            e.preventDefault();
            clearTimeout(hintTimeout);
            hideHint();
            isLongPress = false;
            fab.classList.add('pressing');

            pressTimer = setTimeout(() => {
                isLongPress = true;
                fab.classList.remove('pressing');
                updateMenuPosition();
                floatingMenu.classList.add('active');

                const cfg = getConfig();
                if (!cfg.hasUsedHold) {
                    cfg.hasUsedHold = true;
                    saveConfig(cfg);
                }
            }, LONG_PRESS_DURATION);
        };

        const endPress = (e) => {
            if (isRepositioning) return;
            e.preventDefault();
            fab.classList.remove('pressing');

            if (pressTimer) {
                clearTimeout(pressTimer);
                pressTimer = null;
            }

            if (!isLongPress) {
                const cfg = getConfig();
                if (!cfg.hasUsedTap) {
                    cfg.hasUsedTap = true;
                    saveConfig(cfg);
                }
                fetchTarget('good');
            }
        };

        const cancelPress = () => {
            if (isRepositioning) return;
            fab.classList.remove('pressing');
            if (pressTimer) {
                clearTimeout(pressTimer);
                pressTimer = null;
            }
        };

        fab.addEventListener('mousedown', startPress);
        fab.addEventListener('mouseup', endPress);
        fab.addEventListener('mouseleave', cancelPress);

        fab.addEventListener('touchstart', startPress, { passive: false });
        fab.addEventListener('touchend', endPress, { passive: false });
        fab.addEventListener('touchcancel', cancelPress);

        fab.addEventListener('contextmenu', (e) => e.preventDefault());

        floatingMenu.addEventListener('click', (e) => {
            const item = e.target.closest('.ffs-menu-item');
            if (!item) return;

            const action = item.dataset.action;
            floatingMenu.classList.remove('active');

            switch (action) {
                case 'easy': fetchTarget('easy'); break;
                case 'good': fetchTarget('good'); break;
                case 'apikey': promptApiKey(); break;
                case 'settings': showConfigPopup(); break;
                case 'move': enterRepositionMode(); break;
            }
        });

        document.addEventListener('click', (e) => {
            if (!floatingMenu.contains(e.target) && !fab.contains(e.target)) {
                floatingMenu.classList.remove('active');
            }
        });
    }

    // Keyboard shortcuts
    document.addEventListener('keydown', (e) => {
        if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.isContentEditable) {
            return;
        }

        if (isRepositioning) return;

        switch (e.key) {
            case 'F1':
                e.preventDefault();
                fetchTarget('easy');
                break;
            case 'F2':
                e.preventDefault();
                fetchTarget('good');
                break;
            case 'F3':
                e.preventDefault();
                promptApiKey();
                break;
            case 'F4':
                e.preventDefault();
                showConfigPopup();
                break;
        }
    });

    // Watch for settings menu to appear
    const observer = new MutationObserver(() => {
        injectSettingsToggle();
    });
    observer.observe(document.body, { childList: true, subtree: true });

    // Initialize
    createFloatingButton();
    injectSettingsToggle();
    console.log('FF Scouter loaded');
})();