DuoHacker

Best free-to-use Duolingo farming tool with new safe mode!

// ==UserScript==
// @name         DuoHacker
// @name:zh-CN   DuoHacker — 新安全模式 Duolingo 农场工具
// @name:ja      DuoHacker — 新しい安全モード Duolingo ファーミングツール
// @name:es      DuoHacker — Nueva Modo Seguro Herramienta para farmear en Duolingo
// @name:ru      DuoHacker — Новый безопасный режим для фарминга Duolingo
// @name:pt-BR   DuoHacker — Novo Modo Seguro Ferramenta para farmar no Duolingo
// @name:de      DuoHacker — Neuer Sicherer Modus Duolingo Farming-Tool
// @name:it      DuoHacker — Nuova Modalità Sicura Strumento di farming Duolingo
// @name:ko      DuoHacker — 새로운 안전 모드 Duolingo 팜 도구
// @name:hi      DuoHacker — नया सुरक्षित मोड Duolingo फार्मिंग टूल
// @name:ar      DuoHacker — الوضع الآمن الجديد أداة زراعة Duolingo
// @name:tr      DuoHacker — Yeni Güvenli Mod Duolingo Farming Aracı
// @name:pl      DuoHacker — Nowy Tryb Bezpieczny Narzędzie do farmienia Duolingo
// @description  Best free-to-use Duolingo farming tool with new safe mode!
// @description:zh-CN  具有新安全模式的最佳免费 Duolingo 农场工具!
// @description:ja     新しい安全モードを搭載した最高の無料 Duolingo ファーミングツール!
// @description:es     ¡La mejor herramienta gratuita para farmear en Duolingo con nuevo modo seguro!
// @description:ru     Лучший бесплатный инструмент для фарминга Duolingo с новым безопасным режимом!
// @description:pt-BR  A melhor ferramenta gratuita para farmar no Duolingo com novo modo seguro!
// @description:de     Bestes kostenloses Duolingo Farming-Tool mit neuem Sicherem Modus!
// @description:it     Migliore strumento di farming Duolingo gratuito con nuova modalità sicura!
// @description:ko     새로운 안전 모드가 탑재된 최고의 무료 Duolingo 팜 도구!
// @description:hi     नए सुरक्षित मोड के साथ सर्वश्रेष्ठ मुफ्त Duolingo फार्मिंग टूल!
// @description:ar     أفضل أداة زراعة Duolingo مجانية مع الوضع الآمن الجديد!
// @description:tr     Yeni güvenli modlu en iyi ücretsiz Duolingo farming aracı!
// @description:pl     Najlepsze darmowe narzędzie do farmienia Duolingo z nowym trybem bezpiecznym!
// @namespace    https://irylisvps.vercel.app
// @version      2.0.2
// @author       DuoHacker Community
// @match        https://*.duolingo.com/*
// @icon         https://github.com/pillowslua/images/blob/main/logoo.png?raw=true
// @grant        none
// @license      MIT
// ==/UserScript==

const VERSION = "2.0.2";
const SAFE_DELAY = 2000;
const FAST_DELAY = 300;
const STORAGE_KEY = 'duohacker_accounts';

var jwt, defaultHeaders, userInfo, sub;
let isRunning = false;
let currentMode = 'safe';
let currentTheme = localStorage.getItem('duofarmer_theme') || 'dark';
let hasJoined = localStorage.getItem('duofarmer_joined') === 'true';
let totalEarned = { xp: 0, gems: 0, streak: 0 };
let farmingStats = { sessions: 0, errors: 0, startTime: null };
let farmingInterval = null;
let savedAccounts = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');

const initInterface = () => {
  const containerHTML = `
  <div id="_backdrop"></div>
  <div id="_container" class="theme-${currentTheme}">
    <div id="_header">
      <div class="_header_top">
        <div class="_brand">
          <div class="_logo_container">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120" class="_logo">
              <defs>
                <linearGradient id="logoGrad" x1="0%" y1="0%" x2="100%" y2="100%">
                  <stop offset="0%" style="stop-color:#1E88E5;stop-opacity:1" />
                  <stop offset="100%" style="stop-color:#0D47A1;stop-opacity:1" />
                </linearGradient>
              </defs>
              <circle cx="60" cy="60" r="50" fill="url(#logoGrad)"/>
              <path d="M60 30 Q75 45 60 70 Q45 45 60 30" fill="white" opacity="0.9"/>
              <circle cx="45" cy="50" r="4" fill="white"/>
              <circle cx="75" cy="50" r="4" fill="white"/>
              <path d="M45 75 Q60 85 75 75" stroke="white" stroke-width="3" fill="none" stroke-linecap="round"/>
            </svg>
          </div>
          <div class="_brand_text">
            <h1>DuoHacker</h1>
            <span class="_version_badge">v2.1</span>
          </div>
        </div>
        <div class="_header_controls">
          <button id="_accounts_btn" class="_control_btn _accounts">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/>
              <circle cx="9" cy="7" r="4"/>
              <path d="M23 21v-2a4 4 0 0 0-3-3.87"/>
              <path d="M16 3.13a4 4 0 0 1 0 7.75"/>
            </svg>
            <span class="_badge">${savedAccounts.length}</span>
          </button>
          <button id="_settings_btn" class="_control_btn _settings">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <circle cx="12" cy="12" r="3"/>
              <path d="M12 1v6m0 6v6m4.22-13.22l4.24 4.24M1.54 1.54l4.24 4.24M20.46 20.46l-4.24-4.24M1.54 20.46l4.24-4.24"/>
            </svg>
          </button>
          <button id="_theme_toggle" class="_control_btn">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <circle cx="12" cy="12" r="5"/>
              <line x1="12" y1="1" x2="12" y2="3"/>
              <line x1="12" y1="21" x2="12" y2="23"/>
              <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/>
              <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/>
              <line x1="1" y1="12" x2="3" y2="12"/>
              <line x1="21" y1="12" x2="23" y2="12"/>
              <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/>
              <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/>
            </svg>
          </button>
          <button id="_minimize_btn" class="_control_btn">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <line x1="5" y1="12" x2="19" y2="12"/>
            </svg>
          </button>
          <button id="_close_btn" class="_control_btn _close">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <line x1="18" y1="6" x2="6" y2="18"/>
              <line x1="6" y1="6" x2="18" y2="18"/>
            </svg>
          </button>
        </div>
      </div>
    </div>

    <div id="_main_content" style="display:none">

      <div class="_profile_card">
        <div class="_profile_header">
          <div class="_avatar">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
              <circle cx="12" cy="7" r="4"/>
            </svg>
          </div>
          <div class="_profile_info">
            <h2 id="_username">Loading...</h2>
            <p id="_user_details">Fetching data...</p>
          </div>
          <button id="_save_account_btn" class="_icon_btn _success" title="Save Current Account">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/>
              <polyline points="17 21 17 13 7 13 7 21"/>
              <polyline points="7 3 7 8 15 8"/>
            </svg>
          </button>
          <button id="_refresh_profile" class="_icon_btn" title="Refresh Profile">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <polyline points="23 4 23 10 17 10"/>
              <path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/>
            </svg>
          </button>
        </div>
        <div class="_stats_row">
          <div class="_stat_item">
            <div class="_stat_icon">⚡</div>
            <div class="_stat_info">
              <span class="_stat_value" id="_current_xp">0</span>
              <span class="_stat_label">Total XP</span>
            </div>
          </div>
          <div class="_stat_item">
            <div class="_stat_icon">🔥</div>
            <div class="_stat_info">
              <span class="_stat_value" id="_current_streak">0</span>
              <span class="_stat_label">Streak</span>
            </div>
          </div>
          <div class="_stat_item">
            <div class="_stat_icon">💎</div>
            <div class="_stat_info">
              <span class="_stat_value" id="_current_gems">0</span>
              <span class="_stat_label">Gems</span>
            </div>
          </div>
        </div>
      </div>

      <div class="_mode_section">
        <h3>Select Farming Mode</h3>
        <div class="_mode_cards">
          <div class="_mode_card ${currentMode === 'safe' ? '_active' : ''}" data-mode="safe">
            <div class="_mode_icon">🛡️</div>
            <h4>Safe Mode</h4>
            <p>Slow but undetectable farming</p>
            <div class="_mode_specs">
              <span class="_spec">2s delay</span>
              <span class="_spec">100% safe</span>
            </div>
          </div>
          <div class="_mode_card ${currentMode === 'fast' ? '_active' : ''}" data-mode="fast">
            <div class="_mode_icon">⚡</div>
            <h4>Fast Mode</h4>
            <p>Quick farming with moderate risk</p>
            <div class="_mode_specs">
              <span class="_spec">0.3s delay</span>
              <span class="_spec">Use carefully</span>
            </div>
          </div>
        </div>
      </div>

      <div class="_options_section">
        <h3>Farming Options</h3>
        <div class="_option_grid">
          <button class="_option_btn" data-type="xp">
            <div class="_option_icon">⚡</div>
            <span>Farm XP</span>
          </button>
          <button class="_option_btn" data-type="gems">
            <div class="_option_icon">💎</div>
            <span>Farm Gems</span>
          </button>
          <button class="_option_btn" data-type="streak_repair">
            <div class="_option_icon">🔧</div>
            <span>Repair Streak</span>
          </button>
          <button class="_option_btn" data-type="streak_farm">
            <div class="_option_icon">🔥</div>
            <span>Farm Streak</span>
          </button>
        </div>
      </div>

      <div class="_control_panel">
        <button id="_start_farming" class="_start_btn">
          <span class="_btn_text">Start Farming</span>
        </button>
        <button id="_stop_farming" class="_stop_btn" style="display:none">
          <span class="_btn_text">Stop Farming</span>
        </button>
      </div>

      <div class="_live_stats">
        <h3>Live Statistics</h3>
        <div class="_stats_grid">
          <div class="_live_stat">
            <div class="_live_icon">⚡</div>
            <div class="_live_data">
              <span id="_earned_xp">0</span>
              <small>XP Earned</small>
            </div>
          </div>
          <div class="_live_stat">
            <div class="_live_icon">💎</div>
            <div class="_live_data">
              <span id="_earned_gems">0</span>
              <small>Gems Earned</small>
            </div>
          </div>
          <div class="_live_stat">
            <div class="_live_icon">🔥</div>
            <div class="_live_data">
              <span id="_earned_streak">0</span>
              <small>Streak Gained</small>
            </div>
          </div>
          <div class="_live_stat">
            <div class="_live_icon">⏱️</div>
            <div class="_live_data">
              <span id="_farming_time">00:00</span>
              <small>Time Elapsed</small>
            </div>
          </div>
        </div>
      </div>

      <div class="_console_section">
        <div class="_console_header">
          <h3>Activity Log</h3>
          <button id="_clear_console" class="_clear_btn">Clear</button>
        </div>
        <div id="_console_output" class="_console">
          <div class="_log_entry _info">
            <span class="_log_time">${new Date().toLocaleTimeString()}</span>
            <span class="_log_msg">DuoHacker v2.1 initialized</span>
          </div>
        </div>
      </div>

    </div>

    <div id="_join_section" class="_join_section">
      <div class="_join_content">
        <div class="_join_icon">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <path d="M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2.5-1-3.5a2.5 2.5 0 0 0-1.5 3.5z"/>
            <path d="M15.5 14.5A2.5 2.5 0 0 1 13 12c0-1.38.5-2.5 1-3.5a2.5 2.5 0 0 1 1.5 3.5z"/>
            <path d="M9 16c-1.5 1.5-2 3.5-2 5.5h10c0-2-.5-4-2-5.5"/>
            <path d="M9 16c0-1 1-2 1-3h4c0 1 1 2 1 3"/>
          </svg>
        </div>
        <h2>Join Our Community</h2>
        <p>Get access to updates, support, and exclusive features</p>
        <button id="_join_btn" class="_join_btn">
          <span>Free Pro Version</span>
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <path d="M18 8L22 12L18 16"/>
            <path d="M2 12H22"/>
          </svg>
        </button>
      </div>
    </div>

    <div class="_footer">
      <span>© 2025 DuoHacker by tw1sk</span>
      <div class="_footer_links">
        <button id="_website_btn" class="_footer_link">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <circle cx="12" cy="12" r="10"/>
            <path d="M2 12h20"/>
            <path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/>
          </svg>
          Website
        </button>
        <button id="_discord_btn" class="_footer_link">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <path d="M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2.5-1-3.5a2.5 2.5 0 0 0-1.5 3.5z"/>
            <path d="M15.5 14.5A2.5 2.5 0 0 1 13 12c0-1.38.5-2.5 1-3.5a2.5 2.5 0 0 1 1.5 3.5z"/>
            <path d="M9 16c-1.5 1.5-2 3.5-2 5.5h10c0-2-.5-4-2-5.5"/>
            <path d="M9 16c0-1 1-2 1-3h4c0 1 1 2 1 3"/>
          </svg>
          Discord
        </button>
      </div>
      <span class="_footer_version">v2.1.0</span>
    </div>
  </div>

  <div id="_accounts_modal" class="_modal" style="display:none">
    <div class="_modal_overlay"></div>
    <div class="_modal_container _wide">
      <div class="_modal_header">
        <h2>
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="width:24px;height:24px;display:inline-block;vertical-align:middle;margin-right:8px">
            <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/>
            <circle cx="9" cy="7" r="4"/>
            <path d="M23 21v-2a4 4 0 0 0-3-3.87"/>
            <path d="M16 3.13a4 4 0 0 1 0 7.75"/>
          </svg>
          Account Manager
        </h2>
        <button id="_close_accounts" class="_close_modal_btn">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <line x1="18" y1="6" x2="6" y2="18"/>
            <line x1="6" y1="6" x2="18" y2="18"/>
          </svg>
        </button>
      </div>
      <div class="_modal_content">
        <div class="_accounts_grid" id="_accounts_list">
          ${savedAccounts.length === 0 ? '<div class="_empty_state"><p>No saved accounts yet. Save your current account to get started!</p></div>' : ''}
        </div>
      </div>
    </div>
  </div>

  <div id="_settings_modal" class="_modal" style="display:none">
    <div class="_modal_overlay"></div>
    <div class="_modal_container">
      <div class="_modal_header">
        <h2>Settings</h2>
        <button id="_close_settings" class="_close_modal_btn">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <line x1="18" y1="6" x2="6" y2="18"/>
            <line x1="6" y1="6" x2="18" y2="18"/>
          </svg>
        </button>
      </div>
      <div class="_modal_content">
        <div class="_settings_section">
          <h3>Quick Actions</h3>
          <div class="_setting_item">
            <button id="_get_jwt_btn" class="_setting_btn _primary">
              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                <rect x="9" y="9" width="13" height="13" rx="2" ry="2"/>
                <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
              </svg>
              Copy JWT Token
            </button>
          </div>
          <div class="_setting_item">
            <button id="_logout_btn" class="_setting_btn _danger">
              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/>
                <polyline points="16 17 21 12 16 7"/>
                <line x1="21" y1="12" x2="9" y2="12"/>
              </svg>
              Log Out
            </button>
          </div>
        </div>
        <div class="_settings_section">
          <h3>Manual Login</h3>
          <div class="_setting_item">
            <div class="_jwt_input_group">
              <input type="text" id="_jwt_input" placeholder="Paste JWT Token here">
              <button id="_login_jwt_btn" class="_setting_btn _success">
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                  <path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/>
                  <polyline points="10 17 15 12 10 7"/>
                  <line x1="15" y1="12" x2="3" y2="12"/>
                </svg>
                Login
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

  <div id="_save_account_modal" class="_modal" style="display:none">
    <div class="_modal_overlay"></div>
    <div class="_modal_container">
      <div class="_modal_header">
        <h2>Save Account</h2>
        <button id="_close_save_account" class="_close_modal_btn">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <line x1="18" y1="6" x2="6" y2="18"/>
            <line x1="6" y1="6" x2="18" y2="18"/>
          </svg>
        </button>
      </div>
      <div class="_modal_content">
        <div class="_settings_section">
          <div class="_setting_item">
            <label class="_input_label">Account Nickname</label>
            <input type="text" id="_account_nickname" class="_text_input" placeholder="e.g., Main Account, Alt #1, Work Account">
          </div>
          <div class="_setting_item">
            <div class="_account_preview">
              <div class="_preview_avatar">
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                  <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
                  <circle cx="12" cy="7" r="4"/>
                </svg>
              </div>
              <div class="_preview_info">
                <strong id="_preview_username">Loading...</strong>
                <span id="_preview_details">...</span>
              </div>
            </div>
          </div>
          <div class="_setting_item">
            <button id="_confirm_save_account" class="_setting_btn _success">
              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                <polyline points="20 6 9 17 4 12"/>
              </svg>
              Save Account
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>

  <div id="_fab">
    <div class="_fab_ring"></div>
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
      <circle cx="12" cy="12" r="10"/>
      <path d="M12 6v6l4 2"/>
    </svg>
  </div>
`;

  const style = document.createElement("style");
  style.innerHTML = `
    :root {
      --primary-color: #1E88E5;
      --primary-dark: #0D47A1;
      --primary-light: #64B5F6;
      --success-color: #43A047;
      --error-color: #E53935;
      --warning-color: #FB8C00;
      --transition: all 0.2s ease;
    }

    .theme-dark {
      --bg-primary: #121212;
      --bg-secondary: #1E1E1E;
      --bg-card: rgba(30, 30, 30, 0.95);
      --bg-modal: #1E1E1E;
      --text-primary: #FFFFFF;
      --text-secondary: #B0BEC5;
      --text-muted: #78909C;
      --border-color: rgba(255, 255, 255, 0.12);
      --hover-bg: rgba(30, 136, 229, 0.1);
    }

    .theme-light {
      --bg-primary: #FFFFFF;
      --bg-secondary: #F5F5F5;
      --bg-card: rgba(255, 255, 255, 0.95);
      --bg-modal: #FFFFFF;
      --text-primary: #212121;
      --text-secondary: #757575;
      --text-muted: #9E9E9E;
      --border-color: rgba(0, 0, 0, 0.12);
      --hover-bg: rgba(30, 136, 229, 0.05);
    }

    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
    }

    #_container {
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      width: min(90vw, 900px);
      max-height: 90vh;
      background: var(--bg-primary);
      border-radius: 16px;
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
      border: 1px solid var(--border-color);
      overflow: hidden;
      z-index: 10000;
      display: flex;
      flex-direction: column;
      animation: containerAppear 0.3s ease-out;
    }

    @keyframes containerAppear {
      0% {
        opacity: 0;
        transform: translate(-50%, -50%) scale(0.95);
      }
      100% {
        opacity: 1;
        transform: translate(-50%, -50%) scale(1);
      }
    }

    #_backdrop {
      position: fixed;
      top: 0;
      left: 0;
      width: 100vw;
      height: 100vh;
      background: rgba(0, 0, 0, 0.5);
      backdrop-filter: blur(5px);
      z-index: 9999;
      animation: fadeIn 0.2s ease-out;
    }

    @keyframes fadeIn {
      from { opacity: 0; }
      to { opacity: 1; }
    }

    #_header {
      background: var(--bg-secondary);
      padding: 16px 20px;
      border-bottom: 1px solid var(--border-color);
    }

    ._header_top {
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    ._brand {
      display: flex;
      align-items: center;
      gap: 12px;
    }

    ._logo_container {
      width: 40px;
      height: 40px;
    }

    ._logo {
      width: 100%;
      height: 100%;
    }

    ._brand_text {
      display: flex;
      align-items: center;
      gap: 8px;
    }

    ._brand_text h1 {
      font-size: 20px;
      font-weight: 700;
      color: var(--primary-color);
    }

    ._version_badge {
      background: var(--primary-color);
      color: white;
      padding: 2px 8px;
      border-radius: 10px;
      font-size: 11px;
      font-weight: 600;
    }

    ._header_controls {
      display: flex;
      gap: 6px;
    }

    ._control_btn {
      position: relative;
      width: 36px;
      height: 36px;
      border: none;
      background: var(--bg-card);
      border: 1px solid var(--border-color);
      border-radius: 8px;
      color: var(--text-secondary);
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
      transition: var(--transition);
    }

    ._control_btn:hover {
      background: var(--hover-bg);
      color: var(--primary-color);
    }

    ._control_btn._close:hover {
      background: rgba(229, 57, 53, 0.1);
      color: var(--error-color);
    }

    ._control_btn._accounts {
      background: var(--primary-color);
      color: white;
    }

    ._control_btn._accounts:hover {
      background: var(--primary-dark);
    }

    ._control_btn._settings {
      background: var(--primary-color);
      color: white;
    }

    ._control_btn._settings:hover {
      background: var(--primary-dark);
    }

    ._badge {
      position: absolute;
      top: -4px;
      right: -4px;
      background: var(--error-color);
      color: white;
      font-size: 10px;
      font-weight: 700;
      padding: 2px 5px;
      border-radius: 8px;
      min-width: 16px;
      text-align: center;
    }

    #_main_content {
      flex: 1;
      overflow-y: auto;
      padding: 20px;
      display: flex;
      flex-direction: column;
      gap: 20px;
    }

    ._profile_card {
      background: var(--bg-card);
      border: 1px solid var(--border-color);
      border-radius: 12px;
      padding: 20px;
      transition: var(--transition);
    }

    ._profile_card:hover {
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    }

    ._profile_header {
      display: flex;
      align-items: center;
      gap: 12px;
      margin-bottom: 16px;
    }

    ._avatar {
      width: 50px;
      height: 50px;
      background: var(--primary-color);
      border-radius: 12px;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
    }

    ._avatar svg {
      width: 28px;
      height: 28px;
    }

    ._profile_info {
      flex: 1;
    }

    ._profile_info h2 {
      font-size: 18px;
      font-weight: 600;
      color: var(--text-primary);
      margin-bottom: 4px;
    }

    ._profile_info p {
      color: var(--text-secondary);
      font-size: 14px;
    }

    ._icon_btn {
      width: 32px;
      height: 32px;
      border: none;
      background: var(--bg-card);
      border: 1px solid var(--border-color);
      border-radius: 8px;
      color: var(--text-secondary);
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
      transition: var(--transition);
    }

    ._icon_btn:hover {
      background: var(--hover-bg);
      color: var(--primary-color);
    }

    ._icon_btn._success {
      background: var(--success-color);
      color: white;
      border-color: var(--success-color);
    }

    ._icon_btn._success:hover {
      background: #2E7D32;
    }

    ._icon_btn svg {
      width: 16px;
      height: 16px;
    }

    ._stats_row {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 12px;
    }

    ._stat_item {
      display: flex;
      align-items: center;
      gap: 10px;
      padding: 12px;
      background: var(--bg-secondary);
      border-radius: 8px;
    }

    ._stat_icon {
      font-size: 20px;
    }

    ._stat_info {
      display: flex;
      flex-direction: column;
    }

    ._stat_value {
      font-size: 16px;
      font-weight: 600;
      color: var(--text-primary);
    }

    ._stat_label {
      font-size: 11px;
      color: var(--text-secondary);
    }

    ._mode_section h3 {
      font-size: 16px;
      font-weight: 600;
      color: var(--text-primary);
      margin-bottom: 12px;
    }

    ._mode_cards {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 12px;
    }

    ._mode_card {
      background: var(--bg-card);
      border: 2px solid var(--border-color);
      border-radius: 12px;
      padding: 16px;
      cursor: pointer;
      transition: var(--transition);
      text-align: center;
    }

    ._mode_card:hover {
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    }

    ._mode_card._active {
      border-color: var(--primary-color);
      background: var(--hover-bg);
    }

    ._mode_icon {
      font-size: 36px;
      margin-bottom: 8px;
    }

    ._mode_card h4 {
      font-size: 16px;
      font-weight: 600;
      color: var(--text-primary);
      margin-bottom: 6px;
    }

    ._mode_card p {
      color: var(--text-secondary);
      font-size: 13px;
      margin-bottom: 10px;
    }

    ._mode_specs {
      display: flex;
      justify-content: center;
      gap: 6px;
    }

    ._spec {
      background: var(--bg-secondary);
      padding: 3px 6px;
      border-radius: 4px;
      font-size: 11px;
      color: var(--text-muted);
    }

    ._options_section h3 {
      font-size: 16px;
      font-weight: 600;
      color: var(--text-primary);
      margin-bottom: 12px;
    }

    ._option_grid {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 10px;
    }

    ._option_btn {
      background: var(--bg-card);
      border: 1px solid var(--border-color);
      border-radius: 8px;
      padding: 14px;
      cursor: pointer;
      transition: var(--transition);
      display: flex;
      align-items: center;
      gap: 10px;
    }

    ._option_btn:hover {
      background: var(--hover-bg);
      border-color: var(--primary-color);
    }

    ._option_btn._selected {
      background: var(--primary-color);
      color: white;
      border-color: var(--primary-color);
    }

    ._option_icon {
      font-size: 20px;
    }

    ._option_btn span {
      font-weight: 500;
      color: var(--text-primary);
    }

    ._option_btn._selected span {
      color: white;
    }

    ._control_panel {
      display: flex;
      justify-content: center;
      gap: 12px;
    }

    ._start_btn, ._stop_btn {
      padding: 12px 32px;
      border: none;
      border-radius: 8px;
      font-size: 16px;
      font-weight: 600;
      cursor: pointer;
      transition: var(--transition);
    }

    ._start_btn {
      background: var(--success-color);
      color: white;
    }

    ._stop_btn {
      background: var(--error-color);
      color: white;
    }

    ._start_btn:hover {
      background: #2E7D32;
    }

    ._stop_btn:hover {
      background: #C62828;
    }

    ._live_stats h3 {
      font-size: 16px;
      font-weight: 600;
      color: var(--text-primary);
      margin-bottom: 12px;
    }

    ._stats_grid {
      display: grid;
      grid-template-columns: repeat(2, 1fr);
      gap: 10px;
    }

    ._live_stat {
      background: var(--bg-card);
      border: 1px solid var(--border-color);
      border-radius: 8px;
      padding: 12px;
      display: flex;
      align-items: center;
      gap: 10px;
    }

    ._live_icon {
      font-size: 20px;
    }

    ._live_data {
      display: flex;
      flex-direction: column;
    }

    ._live_data span {
      font-size: 16px;
      font-weight: 600;
      color: var(--text-primary);
    }

    ._live_data small {
      font-size: 11px;
      color: var(--text-secondary);
    }

    ._console_section {
      background: var(--bg-card);
      border: 1px solid var(--border-color);
      border-radius: 8px;
    }

    ._console_header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 12px 16px;
      border-bottom: 1px solid var(--border-color);
    }

    ._console_header h3 {
      font-size: 14px;
      font-weight: 600;
      color: var(--text-primary);
    }

    ._clear_btn {
      background: var(--bg-secondary);
      border: 1px solid var(--border-color);
      border-radius: 6px;
      padding: 4px 8px;
      color: var(--text-secondary);
      font-size: 11px;
      cursor: pointer;
      transition: var(--transition);
    }

    ._clear_btn:hover {
      background: rgba(229, 57, 53, 0.1);
      color: var(--error-color);
    }

    ._console {
      height: 120px;
      overflow-y: auto;
      padding: 12px 16px;
      font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
      font-size: 12px;
    }

    ._log_entry {
      display: flex;
      gap: 8px;
      margin-bottom: 6px;
    }

    ._log_time {
      color: var(--text-muted);
      flex-shrink: 0;
    }

    ._log_msg {
      color: var(--text-secondary);
    }

    ._log_entry._success ._log_msg {
      color: var(--success-color);
    }

    ._log_entry._error ._log_msg {
      color: var(--error-color);
    }

    ._log_entry._info ._log_msg {
      color: var(--primary-color);
    }

    ._join_section {
      flex: 1;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 30px;
    }

    ._join_content {
      text-align: center;
      max-width: 350px;
    }

    ._join_icon {
      width: 60px;
      height: 60px;
      background: var(--primary-color);
      border-radius: 16px;
      display: flex;
      align-items: center;
      justify-content: center;
      margin: 0 auto 20px;
      color: white;
    }

    ._join_icon svg {
      width: 30px;
      height: 30px;
    }

    ._join_content h2 {
      font-size: 20px;
      font-weight: 600;
      color: var(--text-primary);
      margin-bottom: 10px;
    }

    ._join_content p {
      color: var(--text-secondary);
      margin-bottom: 20px;
    }

    ._join_btn {
      background: var(--primary-color);
      color: white;
      border: none;
      padding: 10px 20px;
      border-radius: 8px;
      font-size: 14px;
      font-weight: 600;
      cursor: pointer;
      display: inline-flex;
      align-items: center;
      gap: 6px;
      transition: var(--transition);
    }

    ._join_btn:hover {
      background: var(--primary-dark);
    }

    ._footer {
      padding: 12px 20px;
      background: var(--bg-secondary);
      border-top: 1px solid var(--border-color);
      display: flex;
      justify-content: space-between;
      align-items: center;
      font-size: 11px;
      color: var(--text-muted);
    }

    ._footer_links {
      display: flex;
      gap: 10px;
    }

    ._footer_link {
      display: flex;
      align-items: center;
      gap: 4px;
      background: var(--bg-card);
      border: 1px solid var(--border-color);
      border-radius: 6px;
      padding: 4px 8px;
      color: var(--text-secondary);
      font-size: 11px;
      cursor: pointer;
      transition: var(--transition);
    }

    ._footer_link:hover {
      background: var(--hover-bg);
      color: var(--primary-color);
    }

    ._footer_link svg {
      width: 12px;
      height: 12px;
    }

    ._footer_version {
      background: var(--bg-card);
      padding: 2px 6px;
      border-radius: 4px;
    }

    #_fab {
      position: fixed;
      bottom: 20px;
      right: 20px;
      width: 48px;
      height: 48px;
      background: var(--primary-color);
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      cursor: pointer;
      box-shadow: 0 4px 12px rgba(30, 136, 229, 0.3);
      transition: var(--transition);
      z-index: 9998;
    }

    #_fab:hover {
      transform: scale(1.05);
      box-shadow: 0 6px 16px rgba(30, 136, 229, 0.4);
    }

    ._fab_ring {
      position: absolute;
      width: 100%;
      height: 100%;
      border: 2px solid var(--primary-color);
      border-radius: 50%;
      animation: ringPulse 2s infinite;
    }

    @keyframes ringPulse {
      0% {
        transform: scale(1);
        opacity: 1;
      }
      100% {
        transform: scale(1.3);
        opacity: 0;
      }
    }

    #_fab svg {
      width: 20px;
      height: 20px;
      z-index: 1;
    }

    ._modal {
      position: fixed;
      top: 0;
      left: 0;
      width: 100vw;
      height: 100vh;
      z-index: 10001;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    ._modal_overlay {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: rgba(0, 0, 0, 0.6);
      backdrop-filter: blur(5px);
    }

    ._modal_container {
      position: relative;
      width: 90%;
      max-width: 500px;
      max-height: 85vh;
      background: var(--bg-modal);
      border: 1px solid var(--border-color);
      border-radius: 12px;
      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
      overflow: hidden;
      animation: modalSlideIn 0.3s ease-out;
      display: flex;
      flex-direction: column;
    }

    ._modal_container._wide {
      max-width: 800px;
    }

    @keyframes modalSlideIn {
      from {
        opacity: 0;
        transform: scale(0.95) translateY(20px);
      }
      to {
        opacity: 1;
        transform: scale(1) translateY(0);
      }
    }

    ._modal_header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 16px 20px;
      background: var(--bg-secondary);
      border-bottom: 1px solid var(--border-color);
    }

    ._modal_header h2 {
      font-size: 18px;
      font-weight: 600;
      color: var(--text-primary);
    }

    ._close_modal_btn {
      width: 32px;
      height: 32px;
      border: none;
      background: var(--bg-card);
      color: var(--text-secondary);
      border-radius: 6px;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
      transition: var(--transition);
    }

    ._close_modal_btn:hover {
      background: rgba(229, 57, 53, 0.1);
      color: var(--error-color);
    }

    ._modal_content {
      padding: 20px;
      overflow-y: auto;
      flex: 1;
    }

    ._settings_section {
      margin-bottom: 20px;
    }

    ._settings_section:last-child {
      margin-bottom: 0;
    }

    ._settings_section h3 {
      font-size: 16px;
      font-weight: 600;
      color: var(--text-primary);
      margin-bottom: 16px;
    }

    ._setting_item {
      margin-bottom: 12px;
    }

    ._setting_item:last-child {
      margin-bottom: 0;
    }

    ._setting_btn {
      width: 100%;
      display: flex;
      align-items: center;
      gap: 10px;
      padding: 12px 16px;
      background: var(--bg-card);
      border: 1px solid var(--border-color);
      border-radius: 8px;
      color: var(--text-primary);
      font-size: 14px;
      font-weight: 500;
      cursor: pointer;
      transition: var(--transition);
    }

    ._setting_btn:hover {
      background: var(--hover-bg);
    }

    ._setting_btn._primary {
      background: var(--primary-color);
      color: white;
      border-color: var(--primary-color);
    }

    ._setting_btn._primary:hover {
      background: var(--primary-dark);
    }

    ._setting_btn._success {
      background: var(--success-color);
      color: white;
      border-color: var(--success-color);
    }

    ._setting_btn._success:hover {
      background: #2E7D32;
    }

    ._setting_btn._danger {
      background: var(--error-color);
      color: white;
      border-color: var(--error-color);
    }

    ._setting_btn._danger:hover {
      background: #C62828;
    }

    ._setting_btn svg {
      width: 18px;
      height: 18px;
    }

    ._jwt_input_group {
      display: flex;
      gap: 10px;
    }

    #_jwt_input {
      flex: 1;
      padding: 12px 16px;
      background: var(--bg-card);
      border: 1px solid var(--border-color);
      border-radius: 8px;
      color: var(--text-primary);
      font-size: 14px;
      font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
      transition: var(--transition);
    }

    #_jwt_input:focus {
      outline: none;
      border-color: var(--primary-color);
    }

    ._input_label {
      display: block;
      font-size: 13px;
      font-weight: 500;
      color: var(--text-primary);
      margin-bottom: 6px;
    }

    ._text_input {
      width: 100%;
      padding: 12px 16px;
      background: var(--bg-card);
      border: 1px solid var(--border-color);
      border-radius: 8px;
      color: var(--text-primary);
      font-size: 14px;
      transition: var(--transition);
    }

    ._text_input:focus {
      outline: none;
      border-color: var(--primary-color);
    }

    ._text_input::placeholder {
      color: var(--text-muted);
    }

    ._account_preview {
      display: flex;
      align-items: center;
      gap: 12px;
      padding: 16px;
      background: var(--bg-card);
      border: 1px solid var(--border-color);
      border-radius: 8px;
    }

    ._preview_avatar {
      width: 40px;
      height: 40px;
      background: var(--primary-color);
      border-radius: 8px;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      flex-shrink: 0;
    }

    ._preview_avatar svg {
      width: 20px;
      height: 20px;
    }

    ._preview_info {
      display: flex;
      flex-direction: column;
      gap: 2px;
    }

    ._preview_info strong {
      font-size: 14px;
      color: var(--text-primary);
    }

    ._preview_info span {
      font-size: 12px;
      color: var(--text-secondary);
    }

    ._accounts_grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
      gap: 12px;
    }

    ._empty_state {
      grid-column: 1 / -1;
      text-align: center;
      padding: 40px 20px;
      color: var(--text-secondary);
    }

    ._empty_state p {
      font-size: 14px;
    }

    ._account_card {
      background: var(--bg-card);
      border: 1px solid var(--border-color);
      border-radius: 8px;
      padding: 16px;
      transition: var(--transition);
      position: relative;
      cursor: pointer;
    }

    ._account_card:hover {
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
      border-color: var(--primary-color);
    }

    ._account_card._active {
      border-color: var(--success-color);
      background: var(--hover-bg);
    }

    ._account_header {
      display: flex;
      align-items: center;
      gap: 10px;
      margin-bottom: 12px;
    }

    ._account_avatar {
      width: 40px;
      height: 40px;
      background: var(--primary-color);
      border-radius: 8px;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      flex-shrink: 0;
    }

    ._account_avatar svg {
      width: 20px;
      height: 20px;
    }

    ._account_info {
      flex: 1;
      min-width: 0;
    }

    ._account_nickname {
      font-size: 14px;
      font-weight: 600;
      color: var(--text-primary);
      margin-bottom: 2px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    ._account_username {
      font-size: 12px;
      color: var(--text-secondary);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    ._account_stats {
      display: flex;
      justify-content: space-between;
      gap: 8px;
      margin-bottom: 12px;
    }

    ._account_stat {
      display: flex;
      align-items: center;
      gap: 4px;
      font-size: 12px;
      color: var(--text-secondary);
    }

    ._account_actions {
      display: flex;
      gap: 6px;
    }

    ._account_action_btn {
      flex: 1;
      padding: 8px;
      border: none;
      border-radius: 6px;
      font-size: 12px;
      font-weight: 500;
      cursor: pointer;
      transition: var(--transition);
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 4px;
    }

    ._account_action_btn._login {
      background: var(--success-color);
      color: white;
    }

    ._account_action_btn._login:hover {
      background: #2E7D32;
    }

    ._account_action_btn._delete {
      background: var(--error-color);
      color: white;
    }

    ._account_action_btn._delete:hover {
      background: #C62828;
    }

    ._account_action_btn svg {
      width: 14px;
      height: 14px;
    }

    ._active_badge {
      position: absolute;
      top: 8px;
      right: 8px;
      background: var(--success-color);
      color: white;
      font-size: 10px;
      font-weight: 700;
      padding: 2px 6px;
      border-radius: 4px;
    }

    ::-webkit-scrollbar {
      width: 6px;
    }

    ::-webkit-scrollbar-track {
      background: var(--bg-secondary);
      border-radius: 3px;
    }

    ::-webkit-scrollbar-thumb {
      background: var(--border-color);
      border-radius: 3px;
    }

    ::-webkit-scrollbar-thumb:hover {
      background: var(--text-muted);
    }

    @media (max-width: 768px) {
      #_container {
        width: 95vw;
        max-height: 95vh;
      }

      ._stats_row, ._mode_cards, ._option_grid, ._stats_grid {
        grid-template-columns: 1fr;
      }

      ._control_panel {
        flex-direction: column;
      }

      ._start_btn, ._stop_btn {
        width: 100%;
      }

      ._footer {
        flex-direction: column;
        gap: 8px;
      }

      ._footer_links {
        width: 100%;
        justify-content: center;
      }

      ._jwt_input_group {
        flex-direction: column;
      }

      ._accounts_grid {
        grid-template-columns: 1fr;
      }

      ._modal_container._wide {
        max-width: 95%;
      }
    }
  `;

  document.head.appendChild(style);
// === FIX MODAL VISIBILITY & CONTRAST ===
style.innerHTML += `
  /* Reduce dark overlay opacity */
  ._modal_overlay {
    background: rgba(0, 0, 0, 0.3) !important;
    backdrop-filter: blur(3px) !important;
  }

  /* Make modal box less transparent & text brighter */
  ._modal_container {
    background: rgba(30, 30, 30, 0.98) !important;
    color: #fff !important;
  }

  /* Improve input visibility */
  ._text_input, #_jwt_input {
    background: #2c2c2c !important;
    color: #fff !important;
    border: 1px solid #444 !important;
  }

  /* Buttons inside settings/login modals */
  ._setting_btn {
    background: #1e88e5 !important;
    color: #fff !important;
    border-color: #1565c0 !important;
  }

  ._setting_btn:hover {
    background: #1565c0 !important;
  }

  /* Make account card text readable */
  ._account_card {
    background: rgba(40, 40, 40, 0.95) !important;
    color: #fff !important;
  }
`;
// === END FIX ===


  const container = document.createElement("div");
  container.innerHTML = containerHTML;
  document.body.appendChild(container);
};

const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

const logToConsole = (message, type = 'info') => {
  const console = document.getElementById('_console_output');
  if (!console) return;

  const timestamp = new Date().toLocaleTimeString();
  const entry = document.createElement('div');
  entry.className = `_log_entry _${type}`;
  entry.innerHTML = `
    <span class="_log_time">${timestamp}</span>
    <span class="_log_msg">${message}</span>
  `;

  console.appendChild(entry);
  console.scrollTop = console.scrollHeight;

  while (console.children.length > 50) {
    console.removeChild(console.firstChild);
  }
};

const updateEarnedStats = () => {
  const elements = {
    xp: document.getElementById('_earned_xp'),
    gems: document.getElementById('_earned_gems'),
    streak: document.getElementById('_earned_streak')
  };

  if (elements.xp) elements.xp.textContent = totalEarned.xp.toLocaleString();
  if (elements.gems) elements.gems.textContent = totalEarned.gems.toLocaleString();
  if (elements.streak) elements.streak.textContent = totalEarned.streak;
};

const updateFarmingTime = () => {
  if (!farmingStats.startTime) return;

  const elapsed = Date.now() - farmingStats.startTime;
  const minutes = Math.floor(elapsed / 60000);
  const seconds = Math.floor((elapsed % 60000) / 1000);

  const timeElement = document.getElementById('_farming_time');
  if (timeElement) {
    timeElement.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
  }
};

const setInterfaceVisible = (visible) => {
  const container = document.getElementById("_container");
  const backdrop = document.getElementById("_backdrop");

  if (container && backdrop) {
    container.style.display = visible ? "flex" : "none";
    backdrop.style.display = visible ? "block" : "none";
  }
};

const isInterfaceVisible = () => {
  const container = document.getElementById("_container");
  return container && container.style.display !== "none";
};

const toggleInterface = () => {
  setInterfaceVisible(!isInterfaceVisible());
};

const applyTheme = (theme) => {
  currentTheme = theme;
  localStorage.setItem('duofarmer_theme', theme);

  const container = document.getElementById("_container");
  if (container) {
    container.className = container.className.replace(/theme-\w+/, `theme-${theme}`);
  }
};

const saveAccount = (nickname) => {
  if (!jwt || !userInfo) {
    logToConsole('Cannot save account: not logged in', 'error');
    return false;
  }

  const account = {
    id: Date.now().toString(),
    nickname: nickname || userInfo.username,
    username: userInfo.username,
    jwt: jwt,
    fromLanguage: userInfo.fromLanguage,
    learningLanguage: userInfo.learningLanguage,
    streak: userInfo.streak,
    gems: userInfo.gems,
    totalXp: userInfo.totalXp,
    savedAt: new Date().toISOString()
  };

  const existingIndex = savedAccounts.findIndex(acc => acc.username === account.username);
  if (existingIndex !== -1) {
    savedAccounts[existingIndex] = account;
    logToConsole(`Updated account: ${nickname}`, 'success');
  } else {
    savedAccounts.push(account);
    logToConsole(`Saved new account: ${nickname}`, 'success');
  }

  localStorage.setItem(STORAGE_KEY, JSON.stringify(savedAccounts));
  updateAccountsBadge();
  return true;
};

const deleteAccount = (accountId) => {
  savedAccounts = savedAccounts.filter(acc => acc.id !== accountId);
  localStorage.setItem(STORAGE_KEY, JSON.stringify(savedAccounts));
  updateAccountsBadge();
  renderAccountsList();
  logToConsole('Account deleted', 'info');
};

const loginWithAccount = (account) => {
  document.cookie = `jwt_token=${account.jwt}; path=/; domain=.duolingo.com`;
  logToConsole(`Logging in as ${account.username}...`, 'info');
  setTimeout(() => {
    window.location.reload();
  }, 1000);
};

const updateAccountsBadge = () => {
  const badge = document.querySelector('._control_btn._accounts ._badge');
  if (badge) {
    badge.textContent = savedAccounts.length;
  }
};

const renderAccountsList = () => {
  const accountsList = document.getElementById('_accounts_list');
  if (!accountsList) return;

  if (savedAccounts.length === 0) {
    accountsList.innerHTML = '<div class="_empty_state"><p>No saved accounts yet. Save your current account to get started!</p></div>';
    return;
  }

  const currentUsername = userInfo?.username;

  accountsList.innerHTML = savedAccounts.map(account => {
    const isActive = account.username === currentUsername;
    return `
      <div class="_account_card ${isActive ? '_active' : ''}" data-id="${account.id}">
        ${isActive ? '<div class="_active_badge">ACTIVE</div>' : ''}
        <div class="_account_header">
          <div class="_account_avatar">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
              <circle cx="12" cy="7" r="4"/>
            </svg>
          </div>
          <div class="_account_info">
            <div class="_account_nickname">${account.nickname}</div>
            <div class="_account_username">@${account.username}</div>
          </div>
        </div>
        <div class="_account_stats">
          <div class="_account_stat">⚡ ${account.totalXp?.toLocaleString() || 0}</div>
          <div class="_account_stat">🔥 ${account.streak || 0}</div>
          <div class="_account_stat">💎 ${account.gems || 0}</div>
        </div>
        <div class="_account_actions">
          ${!isActive ? `<button class="_account_action_btn _login" data-action="login">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/>
              <polyline points="10 17 15 12 10 7"/>
              <line x1="15" y1="12" x2="3" y2="12"/>
            </svg>
            Login
          </button>` : '<div style="flex:1"></div>'}
          <button class="_account_action_btn _delete" data-action="delete">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <polyline points="3 6 5 6 21 6"/>
              <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
            </svg>
          </button>
        </div>
      </div>
    `;
  }).join('');

  accountsList.querySelectorAll('._account_card').forEach(card => {
    const accountId = card.dataset.id;
    const account = savedAccounts.find(acc => acc.id === accountId);

    card.querySelector('[data-action="login"]')?.addEventListener('click', (e) => {
      e.stopPropagation();
      if (confirm(`Switch to account: ${account.nickname}?`)) {
        loginWithAccount(account);
      }
    });

    card.querySelector('[data-action="delete"]')?.addEventListener('click', (e) => {
      e.stopPropagation();
      if (confirm(`Delete account: ${account.nickname}?`)) {
        deleteAccount(accountId);
      }
    });
  });
};

const addEventListeners = () => {
  document.getElementById('_fab')?.addEventListener('click', toggleInterface);

  document.getElementById('_minimize_btn')?.addEventListener('click', () => {
    setInterfaceVisible(false);
  });

  document.getElementById('_close_btn')?.addEventListener('click', () => {
    if (isRunning) {
      if (confirm('Farming is active. Are you sure you want to close?')) {
        stopFarming();
        setInterfaceVisible(false);
      }
    } else {
      setInterfaceVisible(false);
    }
  });

  document.getElementById('_theme_toggle')?.addEventListener('click', () => {
    applyTheme(currentTheme === 'dark' ? 'light' : 'dark');
  });

  document.getElementById('_accounts_btn')?.addEventListener('click', () => {
    renderAccountsList();
    document.getElementById('_accounts_modal').style.display = 'flex';
  });

  document.getElementById('_close_accounts')?.addEventListener('click', () => {
    document.getElementById('_accounts_modal').style.display = 'none';
  });

  document.getElementById('_accounts_modal')?.addEventListener('click', (e) => {
    if (e.target.classList.contains('_modal_overlay')) {
      document.getElementById('_accounts_modal').style.display = 'none';
    }
  });

  document.getElementById('_settings_btn')?.addEventListener('click', () => {
    document.getElementById('_settings_modal').style.display = 'flex';
  });

  document.getElementById('_close_settings')?.addEventListener('click', () => {
    document.getElementById('_settings_modal').style.display = 'none';
  });

  document.getElementById('_settings_modal')?.addEventListener('click', (e) => {
    if (e.target.classList.contains('_modal_overlay')) {
      document.getElementById('_settings_modal').style.display = 'none';
    }
  });

  document.getElementById('_save_account_btn')?.addEventListener('click', () => {
    if (!userInfo) {
      logToConsole('Please wait for user data to load', 'error');
      return;
    }
    document.getElementById('_preview_username').textContent = userInfo.username;
    document.getElementById('_preview_details').textContent = `${userInfo.fromLanguage} → ${userInfo.learningLanguage}`;
    document.getElementById('_account_nickname').value = userInfo.username;
    document.getElementById('_save_account_modal').style.display = 'flex';
  });

  document.getElementById('_close_save_account')?.addEventListener('click', () => {
    document.getElementById('_save_account_modal').style.display = 'none';
  });

  document.getElementById('_save_account_modal')?.addEventListener('click', (e) => {
    if (e.target.classList.contains('_modal_overlay')) {
      document.getElementById('_save_account_modal').style.display = 'none';
    }
  });

  document.getElementById('_confirm_save_account')?.addEventListener('click', () => {
    const nickname = document.getElementById('_account_nickname').value.trim();
    if (!nickname) {
      alert('Please enter a nickname for this account');
      return;
    }
    if (saveAccount(nickname)) {
      document.getElementById('_save_account_modal').style.display = 'none';
      alert(`Account saved as: ${nickname}`);
    }
  });

  document.getElementById('_get_jwt_btn')?.addEventListener('click', () => {
    const token = getJwtToken();
    if (token) {
      navigator.clipboard.writeText(token);
      logToConsole('JWT Token copied to clipboard', 'success');
      alert('JWT Token copied to clipboard!');
    } else {
      logToConsole('JWT Token not found', 'error');
      alert('JWT Token not found! Please make sure you are logged in to Duolingo.');
    }
  });

  document.getElementById('_logout_btn')?.addEventListener('click', () => {
    if (confirm('Are you sure you want to log out?')) {
      window.location.href = 'https://www.duolingo.com/logout';
    }
  });

  document.getElementById('_login_jwt_btn')?.addEventListener('click', () => {
    const jwtInput = document.getElementById('_jwt_input');
    const token = jwtInput.value.trim();

    if (token) {
      document.cookie = `jwt_token=${token}; path=/; domain=.duolingo.com`;
      logToConsole('JWT Token updated, refreshing page...', 'success');
      setTimeout(() => {
        window.location.reload();
      }, 1000);
    } else {
      logToConsole('Please enter a valid JWT Token', 'error');
      alert('Please enter a valid JWT Token');
    }
  });

  document.getElementById('_website_btn')?.addEventListener('click', () => {
    window.open('https://irylisvps.vercel.app/', '_blank');
  });

  document.getElementById('_discord_btn')?.addEventListener('click', () => {
    window.open('https://discord.gg/Gvmd7deFtS', '_blank');
  });

  document.getElementById('_join_btn')?.addEventListener('click', () => {
    window.open('https://discord.gg/Gvmd7deFtS', '_blank');
    localStorage.setItem('duofarmer_joined', 'true');
    hasJoined = true;
    document.getElementById('_join_section').style.display = 'none';
    document.getElementById('_main_content').style.display = 'flex';
    initializeFarming();
  });

  document.querySelectorAll('._mode_card').forEach(card => {
    card.addEventListener('click', () => {
      document.querySelectorAll('._mode_card').forEach(c => c.classList.remove('_active'));
      card.classList.add('_active');
      currentMode = card.dataset.mode;
      logToConsole(`Switched to ${currentMode} mode`, 'info');
    });
  });

  document.querySelectorAll('._option_btn').forEach(btn => {
    btn.addEventListener('click', () => {
      document.querySelectorAll('._option_btn').forEach(b => b.classList.remove('_selected'));
      btn.classList.add('_selected');
    });
  });

  document.getElementById('_start_farming')?.addEventListener('click', startFarming);
  document.getElementById('_stop_farming')?.addEventListener('click', stopFarming);

  document.getElementById('_refresh_profile')?.addEventListener('click', async () => {
    const btn = document.getElementById('_refresh_profile');
    btn.style.animation = 'spin 1s linear';
    await refreshUserData();
    btn.style.animation = '';
  });

  document.getElementById('_clear_console')?.addEventListener('click', () => {
    const console = document.getElementById('_console_output');
    if (console) {
      console.innerHTML = '';
      logToConsole('Console cleared', 'info');
    }
  });
};

const startFarming = async () => {
  if (isRunning) return;

  const selectedOption = document.querySelector('._option_btn._selected');
  if (!selectedOption) {
    logToConsole('Please select a farming option', 'error');
    return;
  }

  const type = selectedOption.dataset.type;
  const delayMs = currentMode === 'safe' ? SAFE_DELAY : FAST_DELAY;

  isRunning = true;
  farmingStats.startTime = Date.now();

  document.getElementById('_start_farming').style.display = 'none';
  document.getElementById('_stop_farming').style.display = 'block';

  logToConsole(`Started ${type} farming in ${currentMode} mode`, 'success');

  const timer = setInterval(updateFarmingTime, 1000);

  try {
    switch (type) {
      case 'xp':
        await farmXP(delayMs);
        break;
      case 'gems':
        await farmGems(delayMs);
        break;
      case 'streak_repair':
        await repairStreak();
        break;
      case 'streak_farm':
        await farmStreak();
        break;
    }
  } catch (error) {
    logToConsole(`Farming error: ${error.message}`, 'error');
  } finally {
    clearInterval(timer);
  }
};

const stopFarming = () => {
  if (!isRunning) return;

  isRunning = false;
  if (farmingInterval) {
    clearInterval(farmingInterval);
    farmingInterval = null;
  }

  document.getElementById('_start_farming').style.display = 'block';
  document.getElementById('_stop_farming').style.display = 'none';

  logToConsole('Farming stopped', 'info');
};

const farmXP = async (delayMs) => {
  while (isRunning) {
    try {
      const response = await farmXpOnce();
      if (response.ok) {
        const data = await response.json();
        const earned = data?.awardedXp || 0;
        totalEarned.xp += earned;
        updateEarnedStats();
        logToConsole(`Earned ${earned} XP`, 'success');
      }
      await delay(delayMs);
    } catch (error) {
      logToConsole(`XP farming error: ${error.message}`, 'error');
      await delay(delayMs * 2);
    }
  }
};

const farmGems = async (delayMs) => {
  while (isRunning) {
    try {
      const response = await farmGemOnce();
      if (response.ok) {
        totalEarned.gems += 30;
        updateEarnedStats();
        logToConsole('Earned 30 gems', 'success');
      }
      await delay(delayMs);
    } catch (error) {
      logToConsole(`Gem farming error: ${error.message}`, 'error');
      await delay(delayMs * 2);
    }
  }
};

const repairStreak = async () => {
  logToConsole('Starting streak repair...', 'info');

  try {
    if (!userInfo.streakData?.currentStreak) {
      logToConsole('No streak to repair!', 'error');
      return;
    }

    const startStreakDate = userInfo.streakData.currentStreak.startDate;
    const endStreakDate = userInfo.streakData.currentStreak.endDate;
    const startStreakTimestamp = Math.floor(new Date(startStreakDate).getTime() / 1000);
    const endStreakTimestamp = Math.floor(new Date(endStreakDate).getTime() / 1000);
    const expectedStreak = Math.floor((endStreakTimestamp - startStreakTimestamp) / (60 * 60 * 24)) + 1;

    if (expectedStreak > userInfo.streak) {
      logToConsole(`Found ${expectedStreak - userInfo.streak} frozen days. Repairing...`, 'warning');

      let currentTimestamp = Math.floor(Date.now() / 1000);
      for (let i = 0; i < expectedStreak && isRunning; i++) {
        await farmSessionOnce(currentTimestamp, currentTimestamp + 60);
        currentTimestamp -= 86400;
        logToConsole(`Repaired day ${i + 1}/${expectedStreak}`, 'info');
        await delay(currentMode === 'safe' ? SAFE_DELAY : FAST_DELAY);
      }

      const updatedUser = await getUserInfo(sub);
      if (updatedUser.streak >= expectedStreak) {
        logToConsole(`Streak repair completed! New streak: ${updatedUser.streak}`, 'success');
        userInfo = updatedUser;
        totalEarned.streak += (updatedUser.streak - userInfo.streak);
        updateUserInfo();
        updateEarnedStats();
      }
    } else {
      logToConsole('No frozen streak detected', 'info');
    }
  } catch (error) {
    logToConsole(`Streak repair failed: ${error.message}`, 'error');
  } finally {
    stopFarming();
  }
};

const farmStreak = async () => {
  logToConsole('Starting streak farming...', 'info');

  const hasStreak = !!userInfo.streakData?.currentStreak;
  const startStreakDate = hasStreak ? userInfo.streakData.currentStreak.startDate : new Date();
  const startFarmStreakTimestamp = Math.floor(new Date(startStreakDate).getTime() / 1000);
  let currentTimestamp = hasStreak ? startFarmStreakTimestamp - 86400 : startFarmStreakTimestamp;

  while (isRunning) {
    try {
      await farmSessionOnce(currentTimestamp, currentTimestamp + 60);
      currentTimestamp -= 86400;
      totalEarned.streak++;
      userInfo.streak++;
      updateUserInfo();
      updateEarnedStats();
      logToConsole(`Streak increased to ${userInfo.streak}`, 'success');
      await delay(currentMode === 'safe' ? SAFE_DELAY : FAST_DELAY);
    } catch (error) {
      logToConsole(`Streak farming error: ${error.message}`, 'error');
      await delay((currentMode === 'safe' ? SAFE_DELAY : FAST_DELAY) * 2);
    }
  }
};

const getJwtToken = () => {
  let match = document.cookie.match(new RegExp('(^| )jwt_token=([^;]+)'));
  if (match) {
    return match[2];
  }
  return null;
};

const decodeJwtToken = (token) => {
  const base64Url = token.split(".")[1];
  const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
  const jsonPayload = decodeURIComponent(
    atob(base64)
      .split("")
      .map(c => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2))
      .join("")
  );
  return JSON.parse(jsonPayload);
};

const formatHeaders = (jwt) => ({
  "Content-Type": "application/json",
  Authorization: "Bearer " + jwt,
  "User-Agent": navigator.userAgent,
});

const getUserInfo = async (sub) => {
  const userInfoUrl = `https://www.duolingo.com/2017-06-30/users/${sub}?fields=id,username,fromLanguage,learningLanguage,streak,totalXp,level,numFollowers,numFollowing,gems,creationDate,streakData`;
  const response = await fetch(userInfoUrl, {
    method: "GET",
    headers: defaultHeaders,
  });
  return await response.json();
};

const sendRequestWithDefaultHeaders = async ({ url, payload, headers = {}, method = "GET" }) => {
  const mergedHeaders = { ...defaultHeaders, ...headers };
  return await fetch(url, {
    method,
    headers: mergedHeaders,
    body: payload ? JSON.stringify(payload) : undefined,
  });
};

const farmXpOnce = async () => {
  const startTime = Math.floor(Date.now() / 1000);
  const fromLanguage = userInfo.fromLanguage;
  const completeUrl = `https://stories.duolingo.com/api2/stories/en-${fromLanguage}-the-passport/complete`;

  const payload = {
    awardXp: true,
    isFeaturedStoryInPracticeHub: false,
    completedBonusChallenge: true,
    mode: "READ",
    isV2Redo: false,
    isV2Story: false,
    isLegendaryMode: true,
    masterVersion: false,
    maxScore: 0,
    numHintsUsed: 0,
    score: 0,
    startTime: startTime,
    fromLanguage: fromLanguage,
    learningLanguage: "en",
    hasXpBoost: false,
    happyHourBonusXp: 449,
  };

  return await sendRequestWithDefaultHeaders({
    url: completeUrl,
    payload: payload,
    method: "POST",
  });
};

const farmGemOnce = async () => {
  const idReward = "SKILL_COMPLETION_BALANCED-dd2495f4_d44e_3fc3_8ac8_94e2191506f0-2-GEMS";
  const patchUrl = `https://www.duolingo.com/2017-06-30/users/${sub}/rewards/${idReward}`;

  const patchData = {
    consumed: true,
    learningLanguage: userInfo.learningLanguage,
    fromLanguage: userInfo.fromLanguage,
  };

  return await sendRequestWithDefaultHeaders({
    url: patchUrl,
    payload: patchData,
    method: "PATCH",
  });
};

const farmSessionOnce = async (startTime, endTime) => {
  const sessionPayload = {
    challengeTypes: [
      "assist", "characterIntro", "characterMatch", "characterPuzzle", "characterSelect",
      "characterTrace", "characterWrite", "completeReverseTranslation", "definition",
      "dialogue", "extendedMatch", "extendedListenMatch", "form", "freeResponse",
      "gapFill", "judge", "listen", "listenComplete", "listenMatch", "match", "name",
      "listenComprehension", "listenIsolation", "listenSpeak", "listenTap",
      "orderTapComplete", "partialListen", "partialReverseTranslate", "patternTapComplete",
      "radioBinary", "radioImageSelect", "radioListenMatch", "radioListenRecognize",
      "radioSelect", "readComprehension", "reverseAssist", "sameDifferent", "select",
      "selectPronunciation", "selectTranscription", "svgPuzzle", "syllableTap",
      "syllableListenTap", "speak", "tapCloze", "tapClozeTable", "tapComplete",
      "tapCompleteTable", "tapDescribe", "translate", "transliterate",
      "transliterationAssist", "typeCloze", "typeClozeTable", "typeComplete",
      "typeCompleteTable", "writeComprehension",
    ],
    fromLanguage: userInfo.fromLanguage,
    isFinalLevel: false,
    isV2: true,
    juicy: true,
    learningLanguage: userInfo.learningLanguage,
    smartTipsVersion: 2,
    type: "GLOBAL_PRACTICE",
  };

  const sessionRes = await sendRequestWithDefaultHeaders({
    url: "https://www.duolingo.com/2017-06-30/sessions",
    payload: sessionPayload,
    method: "POST",
  });

  const sessionData = await sessionRes.json();

  const updateSessionPayload = {
    ...sessionData,
    heartsLeft: 0,
    startTime: startTime,
    enableBonusPoints: false,
    endTime: endTime,
    failed: false,
    maxInLessonStreak: 9,
    shouldLearnThings: true,
  };

  const updateRes = await sendRequestWithDefaultHeaders({
    url: `https://www.duolingo.com/2017-06-30/sessions/${sessionData.id}`,
    payload: updateSessionPayload,
    method: "PUT",
  });

  return await updateRes.json();
};

const updateUserInfo = () => {
  if (!userInfo) return;

  const elements = {
    username: document.getElementById('_username'),
    user_details: document.getElementById('_user_details'),
    currentStreak: document.getElementById('_current_streak'),
    currentGems: document.getElementById('_current_gems'),
    currentXp: document.getElementById('_current_xp')
  };

  if (elements.username) elements.username.textContent = userInfo.username;
  if (elements.user_details) {
    elements.user_details.textContent = `${userInfo.fromLanguage} → ${userInfo.learningLanguage}`;
  }
  if (elements.currentStreak) elements.currentStreak.textContent = userInfo.streak?.toLocaleString() || '0';
  if (elements.currentGems) elements.currentGems.textContent = userInfo.gems?.toLocaleString() || '0';
  if (elements.currentXp) elements.currentXp.textContent = userInfo.totalXp?.toLocaleString() || '0';
};

const refreshUserData = async () => {
  if (!sub || !defaultHeaders) return;

  try {
    logToConsole('Refreshing user data...', 'info');
    userInfo = await getUserInfo(sub);
    updateUserInfo();
    logToConsole('User data refreshed', 'success');
  } catch (error) {
    logToConsole(`Failed to refresh: ${error.message}`, 'error');
  }
};

const initializeFarming = async () => {
  try {
    jwt = getJwtToken();
    if (!jwt) {
      logToConsole('Please login to Duolingo and reload', 'error');
      return false;
    }

    defaultHeaders = formatHeaders(jwt);
    const decodedJwt = decodeJwtToken(jwt);
    sub = decodedJwt.sub;

    logToConsole('Loading user data...', 'info');
    userInfo = await getUserInfo(sub);

    if (userInfo && userInfo.username) {
      updateUserInfo();
      logToConsole(`Welcome ${userInfo.username}!`, 'success');
      return true;
    } else {
      logToConsole('Failed to load user data', 'error');
      return false;
    }
  } catch (error) {
    logToConsole(`Init error: ${error.message}`, 'error');
    return false;
  }
};

(async () => {
  try {
    initInterface();
    setInterfaceVisible(false);
    applyTheme(currentTheme);
    addEventListeners();
    updateAccountsBadge();

    if (hasJoined) {
      document.getElementById('_join_section').style.display = 'none';
      document.getElementById('_main_content').style.display = 'flex';
      await initializeFarming();
    }

    logToConsole('DuoHacker v2.1 ready - Enhanced Multi-Account Edition', 'success');
  } catch (error) {
    console.error('Init failed:', error);
  }
})();