Stake Dice Bot

Advanced Dice Bot for Stake.us and Stake.com with a resizable UI, intelligent triggers, notifications, and enhanced strategy options.

// ==UserScript==
// @name         Stake Dice Bot
// @namespace    http://tampermonkey.net/
// @version      7.7.0
// @description  Advanced Dice Bot for Stake.us and Stake.com with a resizable UI, intelligent triggers, notifications, and enhanced strategy options.
// @author       shdw_lol
// @license      MIT
// @match        *://stake.com/casino/games/dice*
// @match        *://stake.com/*/casino/games/dice*
// @match        *://stake.us/*/casino/games/dice*
// @match        *://stake.us/casino/games/dice*
// @grant        GM_addStyle
// @grant        unsafeWindow
// @run-at       document-idle
// ==/UserScript==

// --- DISCLAIMER ---
// This script interacts with the Stake API to perform actions like changing your game seed.
// To do this, it needs to use your account's session token. This token is retrieved from your browser's
// storage (cookies or local storage) and is ONLY sent back to Stake's official servers.
// It is never sent to any third-party server or stored outside of your browser.
// The password feature uses SHA-256 hashing and stores the result in your browser's local storage.
// It is never transmitted over the network.

(function() {
    'use strict';

    // --- CONFIGURATION & STATE ---

    const state = {
        running: false,
        isLocked: false,
        baseBet: 0.01,
        currentBet: 0.01,
        betCount: 0,
        totalProfit: 0,
        winStreak: 0,
        lossStreak: 0,
        lastBetWasWin: null,
        onWinAction: 'reset',
        onWinIncrease: 0,
        onLossAction: 'increase',
        onLossIncrease: 100,
        strategyFlags: {}, // For stateful conditions like 'firstStreakOf'
        persistentTriggerStates: {}, // For tracking profit/time based one-time actions
        lastWinTimestamp: 0,
        outcomeHistory: '', // String of 'W' and 'L'
        originalAutoStrategy: null,
        originalBetDelay: null, // To store the bet delay from config when the bot starts
    };

    const semiAutoState = {
        currentBet: 0.01,
        isStarted: false,
    };

    let advancedStrategies = {};
    let isPickingElement = false;
    let logEntries = [];
    let isBotInitialized = false;
    let storedUsername = '';
    let storedPasswordHash = '';
    let pendingAction = null;

    const logFilters = {
        system: true,
        manual: true,
        auto: true,
        strategy: true,
    };

    // --- CONFIG & SELECTORS ---
    let CONFIG = {
        authToken: '',
        seedChangeEndpoint: '/_api/graphql',
        betButton: '[data-testid="bet-button"]',
        amountInput: '[data-testid="input-game-amount"]',
        payoutInput: '[data-testid="payout"]',
        winChanceInput: '[data-testid="chance"]',
        baseWinChance: 49.5,
        betDelay: '100', // Can be a single number or a range like "100-250"
        maxBetAmount: 0,
        gameFrame: '[data-testid="game-frame"]',
        pastBetsContainer: '.past-bets',
        winClass: 'variant-success',
        lossClass: 'variant-neutral',
        autoTab: '[data-testid="auto-tab"]',
        manualTab: '[data-testid="manual-tab"]',
        reverseRollButton: '[data-testid="reverse-roll"]',
        uiScale: 100, // UI Scale percentage
    };

    const CONFIG_FRIENDLY_NAMES = {
        authToken: "Auth Token",
        seedChangeEndpoint: "API Endpoint",
        betButton: "Bet Button",
        amountInput: "Amount Input",
        payoutInput: "Payout Input",
        winChanceInput: "Win Chance Input",
        baseWinChance: "Base Win Chance (%)",
        betDelay: "Bet Delay Range (ms)",
        maxBetAmount: "Max Bet Amount (0=off)",
        gameFrame: "Game Frame",
        pastBetsContainer: "Past Bets List",
        winClass: "Win Bet Class",
        lossClass: "Loss Bet Class",
        autoTab: "Auto Tab Button",
        manualTab: "Manual Tab Button",
        reverseRollButton: "Flip Over/Under Button",
        uiScale: "UI Scale (%)",
    };

    // --- UI (HTML & CSS) ---

    const botHtml = `
        <div id="bot-notification-container"></div>
        <div id="dice-bot-window" class="bot-window">
            <div class="resizer resizer-t"></div>
            <div class="resizer resizer-r"></div>
            <div class="resizer resizer-b"></div>
            <div class="resizer resizer-l"></div>
            <div class="resizer resizer-tl"></div>
            <div class="resizer resizer-tr"></div>
            <div class="resizer resizer-br"></div>
            <div class="resizer resizer-bl"></div>
            <div id="bot-header" class="bot-header">
                <span>Stake Dice Bot <span id="bot-status-indicator"></span> <span id="profit-loss-display"></span></span>
                <div class="window-controls">
                    <button id="minimize-btn" class="window-btn" title="Minimize">—</button>
                    <button id="close-btn" class="window-btn" title="Close">×</button>
                </div>
            </div>
            <div id="bot-main-content" class="bot-content">
                <div class="bot-tabs">
                    <button class="bot-tab-btn active" data-tab="semi-auto">Manual</button>
                    <button class="bot-tab-btn" data-tab="main">Auto</button>
                    <button class="bot-tab-btn" data-tab="advanced">Advanced</button>
                    <button class="bot-tab-btn" data-tab="log">Log</button>
                    <button class="bot-tab-btn" data-tab="config">Config</button>
                    <button class="bot-tab-btn" data-tab="admin">Admin</button>
                </div>
                <div id="tab-semi-auto" class="bot-tab-content active">
                    <div class="bot-input-group"><label>Base Amount</label><input type="number" id="semi-auto-base-bet" class="bot-input" value="0.01" step="0.01"></div>
                    <div class="bot-input-group"><label>Strategy</label><select id="semi-auto-strategy" class="bot-input"><option value="none" selected>None (Manual Betting)</option></select></div>
                    <p id="semi-auto-desc" class="strategy-desc">Select a custom strategy or use manual betting.</p>
                    <button id="semi-auto-step-btn" class="bot-btn bot-btn-primary" title="Run a single bet (D)">Run Step (D)</button>
                    <button id="semi-auto-reset-btn" class="bot-btn bot-btn-danger" title="Reset bet amount to base (R)">Reset to Base (R)</button>
                    <button id="manual-change-seed-btn" class="bot-btn bot-btn-secondary" title="Test the API seed change feature">Change Seed (API)</button>
                </div>
                <div id="tab-main" class="bot-tab-content">
                    <div class="bot-input-group"><label>Base Amount</label><input type="number" id="base-bet" class="bot-input" value="0.01" step="0.01"></div>
                    <div class="bot-input-group"><label>Strategy</label><select id="auto-strategy-select" class="bot-input"><option value="none">None (Use On Win/Loss %)</option></select></div>
                    <div id="on-win-loss-container">
                        <div class="bot-input-group on-action"><label>On Win</label><select id="on-win-action" class="bot-input"><option value="reset">Reset to Base</option><option value="increase">Increase by %</option></select><input type="number" id="on-win-increase" class="bot-input" value="0" min="0"></div>
                        <div class="bot-input-group on-action"><label>On Loss</label><select id="on-loss-action" class="bot-input"><option value="increase">Increase by %</option><option value="reset">Reset to Base</option></select><input type="number" id="on-loss-increase" class="bot-input" value="100" min="0"></div>
                    </div>
                    <button id="start-stop-btn" class="bot-btn bot-btn-primary" title="Starts or stops the bot (S)">Start Auto (S)</button>
                </div>
                <div id="tab-advanced" class="bot-tab-content">
                    <div class="bot-input-group">
                        <label>Your Saved Strategies</label>
                        <select id="advanced-strategy-list" class="bot-input"></select>
                    </div>
                    <div class="btn-grid">
                        <button id="create-strategy-btn" class="bot-btn bot-btn-secondary">Create New</button>
                        <button id="edit-strategy-btn" class="bot-btn bot-btn-secondary">Edit Selected</button>
                        <button id="import-strategy-btn" class="bot-btn bot-btn-secondary">Import</button>
                        <button id="export-strategy-btn" class="bot-btn bot-btn-secondary">Export Selected</button>
                    </div>
                    <button id="delete-strategy-btn" class="bot-btn bot-btn-danger">Delete Selected</button>
                </div>
                <div id="tab-log" class="bot-tab-content">
                    <div id="log-filters">
                        <label><input type="checkbox" data-filter="system" checked> System</label>
                        <label><input type="checkbox" data-filter="manual" checked> Manual</label>
                        <label><input type="checkbox" data-filter="auto" checked> Auto</label>
                        <label><input type="checkbox" data-filter="strategy" checked> Strategy</label>
                    </div>
                    <div id="log-container"></div>
                    <div class="btn-grid">
                        <button id="reset-stats-btn" class="bot-btn bot-btn-danger">Reset Stats</button>
                        <button id="save-log-btn" class="bot-btn bot-btn-secondary">Save Log to File</button>
                    </div>
                </div>
                <div id="tab-config" class="bot-tab-content">
                    <p class="strategy-desc">Configure API settings and UI element selectors. The bot tries to find the Auth Token automatically.</p>
                    <div id="config-container"></div>
                    <button id="save-config-btn" class="bot-btn bot-btn-primary">Save Config</button>
                    <button id="reset-config-btn" class="bot-btn bot-btn-danger">Reset to Defaults</button>
                </div>
                <div id="tab-admin" class="bot-tab-content">
                    <p class="strategy-desc">Set a password to lock bot settings. When locked, only the Manual and Admin tabs are usable.</p>
                    <div class="bot-input-group">
                        <label>Username</label>
                        <input type="text" id="admin-username" class="bot-input" autocomplete="username">
                    </div>
                    <div class="bot-input-group">
                        <label>New Password (leave blank to keep current)</label>
                        <input type="password" id="admin-password" class="bot-input" autocomplete="new-password">
                    </div>
                    <button id="save-credentials-btn" class="bot-btn bot-btn-secondary">Save Credentials</button>
                    <hr>
                    <button id="lock-unlock-btn" class="bot-btn bot-btn-primary">Lock</button>
                    <p id="admin-status" class="strategy-desc" style="margin-top: 15px; text-align: center;"></p>
                </div>
            </div>
        </div>

        <div id="dice-bot-minimized-bar" style="display: none;">
            <span>Stake Dice Bot</span>
            <div class="window-controls">
                <button id="maximize-btn" class="window-btn" title="Maximize">□</button>
                <button id="close-minimized-btn" class="window-btn" title="Close">×</button>
            </div>
        </div>

        <div id="strategy-modal" style="display: none;">
            <div id="strategy-modal-content">
                <h3 id="strategy-modal-title">Create Strategy</h3>
                <div class="bot-input-group"><label>Strategy Name</label><input type="text" id="strategy-name" class="bot-input"></div>
                <div id="strategy-rules-container"></div>
                <button id="add-rule-btn" class="bot-btn bot-btn-secondary">Add Condition Block</button>
                <hr>
                <p id="strategy-modal-warning" style="color: var(--accent-red); text-align: center; display: none;"></p>
                <button id="save-strategy-btn" class="bot-btn bot-btn-primary">Save Strategy</button>
                <button id="cancel-strategy-btn" class="bot-btn bot-btn-danger">Cancel</button>
            </div>
        </div>
        <div id="password-prompt-modal" style="display: none;">
            <div id="password-prompt-content">
                <h3>Password Required</h3>
                <p id="password-prompt-message">Please enter the password to unlock this feature.</p>
                <div class="bot-input-group">
                    <label>Password</label>
                    <input type="password" id="prompt-password-input" class="bot-input" autocomplete="current-password">
                </div>
                <p id="password-prompt-error" style="color: var(--accent-red); display: none;"></p>
                <button id="password-prompt-submit" class="bot-btn bot-btn-primary">Submit</button>
                <button id="password-prompt-cancel" class="bot-btn bot-btn-secondary">Cancel</button>
            </div>
        </div>
        <div id="element-picker-overlay"></div>
        <div id="element-picker-tooltip">Click an element to select it. Press ESC to cancel.</div>
    `;

    const botCss = `
        :root { --bg-primary: #0F212E; --bg-secondary: #213743; --accent-green: #00b373; --accent-red: #e53e3e; --accent-yellow: #FFC107; }
        .bot-window { position: fixed; top: 100px; right: 20px; width: 380px; min-width: 350px; max-width: 800px; height: 550px; min-height: 400px; max-height: 90vh; background-color: var(--bg-primary); border-radius: 8px; z-index: 9999; color: #fff; font-family: 'Inter', sans-serif; box-shadow: 0 5px 15px rgba(0,0,0,0.5); display: none; flex-direction: column; overflow: hidden; }
        .bot-header { padding: 10px 15px; cursor: move; background-color: var(--bg-secondary); font-weight: 600; user-select: none; display: flex; justify-content: space-between; align-items: center; flex-shrink: 0; }
        #bot-status-indicator { font-weight: normal; font-size: 12px; opacity: 0.8; margin-left: 8px; }
        #profit-loss-display { font-weight: 600; font-size: 12px; margin-left: 10px; }
        #profit-loss-display.profit { color: var(--accent-green); }
        #profit-loss-display.loss { color: var(--accent-red); }
        .window-controls { display: flex; gap: 8px; align-items: center; }
        .window-btn { background: none; border: none; color: #b1bad3; font-size: 20px; cursor: pointer; line-height: 1; padding: 0 5px; font-family: sans-serif; display: flex; align-items: center; justify-content: center; }
        .window-btn:hover { color: #fff; }
        #maximize-btn { font-size: 16px; }
        .bot-content { padding: 15px; flex-grow: 1; display: flex; flex-direction: column; min-height: 0; }
        .bot-tabs { display: flex; margin-bottom: 15px; background-color: var(--bg-primary); border-radius: 20px; padding: 4px; border: 1px solid var(--bg-secondary); flex-shrink: 0; }
        .bot-tab-btn { flex: 1; padding: 8px; cursor: pointer; background: transparent; border: none; color: #b1bad3; border-radius: 20px; font-weight: 500; transition: all 0.2s ease-in-out; font-size: 13px; white-space: nowrap; }
        .bot-tab-btn.active { background-color: var(--bg-secondary); color: #fff; }
        .bot-tabs.locked .bot-tab-btn:not([data-tab="semi-auto"]):not([data-tab="admin"]) { pointer-events: none; opacity: 0.5; }
        .bot-tab-content { display: none; }
        .bot-tab-content.active { display: flex; flex-grow: 1; flex-direction: column; }
        #tab-config { overflow-y: auto; }
        .bot-input-group { margin-bottom: 12px; display: flex; flex-direction: column; }
        .bot-input-group label { margin-bottom: 5px; font-size: 14px; color: #b1bad3; }
        .bot-input { width: 100%; padding: 8px; background-color: var(--bg-primary); border: 1px solid var(--bg-secondary); border-radius: 4px; color: #fff; box-sizing: border-box; }
        .bot-input:disabled { background-color: #2a414f; opacity: 0.7; }
        .bot-input-group.on-action { display: grid; grid-template-columns: 1fr 1fr; grid-gap: 10px; align-items: flex-end; }
        .bot-input-group.on-action label { grid-column: 1 / -1; }
        #on-win-loss-container.disabled { opacity: 0.5; pointer-events: none; }
        .bot-btn { width: 100%; padding: 12px; border: none; border-radius: 4px; cursor: pointer; font-size: 16px; font-weight: 600; margin-top: 10px; }
        .bot-btn:disabled { background-color: #4A5568; cursor: not-allowed; opacity: 0.7; }
        .bot-btn-primary { background-color: var(--accent-green); color: #fff; }
        .bot-btn-danger { background-color: var(--accent-red); color: #fff; }
        .bot-btn-secondary { background-color: var(--bg-secondary); color: #fff; }
        .strategy-desc { font-size: 12px; color: #b1bad3; background-color: var(--bg-secondary); padding: 8px; border-radius: 4px; margin: 5px 0 15px 0; }
        #config-container { background-color: var(--bg-primary); border-radius: 4px; padding: 8px; font-size: 12px; line-height: 1.5; }
        #log-container { flex-grow: 1; overflow-y: auto; padding-right: 5px; background-color: var(--bg-primary); border: 1px solid var(--bg-secondary); border-radius: 4px; padding: 8px; font-size: 12px; line-height: 1.5; }
        #log-container p { margin: 0 0 5px 0; padding: 2px 4px; border-radius: 3px; }
        #log-container p.log-manual { color: var(--accent-green); }
        #log-container p.log-auto { color: var(--accent-red); }
        #log-container p.log-strategy { color: var(--accent-yellow); }
        #log-container p b { font-weight: 900; }
        #log-filters { display: flex; gap: 15px; margin-bottom: 10px; background-color: var(--bg-secondary); padding: 8px; border-radius: 4px; }
        #log-filters label { display: flex; align-items: center; gap: 5px; font-size: 12px; cursor: pointer; }
        #dice-bot-minimized-bar { position: fixed; top: 100px; right: 20px; background-color: var(--bg-secondary); border-radius: 8px; z-index: 9999; color: #fff; font-family: 'Inter', sans-serif; box-shadow: 0 5px 15px rgba(0,0,0,0.5); display: none; justify-content: space-between; align-items: center; padding: 8px 12px; cursor: move; }
        .config-group { display: flex; align-items: center; gap: 5px; margin-bottom: 8px; }
        .config-group label { font-size: 12px; color: #b1bad3; flex-basis: 140px; flex-shrink: 0; display: flex; align-items: center; }
        .config-group .input-wrapper { display: flex; align-items: center; flex-grow: 1; position: relative; }
        .config-group input { flex-grow: 1; font-size: 11px; }
        .config-group input[type=text] { padding-right: 30px; }
        .config-group input.invalid-range { border-color: var(--accent-red) !important; }
        .config-range-wrapper { display: flex; align-items: center; gap: 5px; width: 100%; }
        .config-range-wrapper input { flex-grow: 1; text-align: center; }
        .config-range-wrapper span { color: #b1bad3; font-size: 11px; }
        .config-pick-btn, .config-toggle-vis-btn { padding: 6px 8px; font-size: 10px; flex-shrink: 0; background-color: #4A5568; color: white; border: none; border-radius: 4px; cursor: pointer; }
        .config-toggle-vis-btn { position: absolute; right: 1px; top: 1px; bottom: 1px; background-color: var(--bg-secondary); padding: 0 8px; }
        .config-toggle-vis-btn svg { width: 16px; height: 16px; pointer-events: none; }
        .config-tooltip-trigger { display: inline-block; margin-left: 8px; background-color: var(--accent-yellow); color: var(--bg-primary); border-radius: 50%; width: 16px; height: 16px; text-align: center; line-height: 16px; font-weight: bold; cursor: help; position: relative; font-size: 12px; }
        .config-tooltip-trigger .tooltip-text { visibility: hidden; width: 220px; background-color: var(--bg-secondary); color: #fff; text-align: center; border-radius: 6px; padding: 8px; position: absolute; z-index: 1; bottom: 125%; left: 50%; margin-left: -110px; opacity: 0; transition: opacity 0.3s; font-weight: normal; font-size: 11px; }
        .config-tooltip-trigger:hover .tooltip-text { visibility: visible; opacity: 1; }
        #element-picker-overlay { position: fixed; background-color: rgba(0, 179, 115, 0.3); border: 2px solid var(--accent-green); z-index: 10000; pointer-events: none; display: none; transition: all 0.1s linear; }
        #element-picker-tooltip { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); background-color: black; color: white; padding: 10px 20px; border-radius: 5px; z-index: 10001; display: none; }
        #strategy-modal, #password-prompt-modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 10002; display: flex; align-items: center; justify-content: center; }
        #strategy-modal-content, #password-prompt-content { background: var(--bg-primary); padding: 20px; border-radius: 8px; border: 1px solid var(--bg-secondary); width: 90%; max-width: 500px; max-height: 90vh; overflow-y: auto; display: flex; flex-direction: column; }
        #password-prompt-content { max-width: 380px; text-align: center; }
        #strategy-rules-container { margin-top: 15px; overflow-y: auto; flex-grow: 1; }
        .strategy-rule { background: var(--bg-secondary); padding: 10px; border-radius: 4px; margin-bottom: 10px; }
        .strategy-rule-header { display: flex; justify-content: space-between; align-items: center; cursor: pointer; }
        .strategy-rule-summary { display: flex; gap: 5px; align-items: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .strategy-rule-summary span { font-size: 13px; }
        .strategy-rule-summary .summary-action { color: var(--accent-yellow); }
        .strategy-rule-controls { display: flex; align-items: center; }
        .strategy-rule-editor { display: none; margin-top: 15px; padding-top: 15px; border-top: 1px solid var(--bg-primary); }
        .strategy-rule.expanded .strategy-rule-editor { display: block; }
        .strategy-rule.expanded .strategy-rule-summary { display: none; }
        .rule-toggle-group { display: flex; justify-content: center; flex-wrap: wrap; gap: 10px; margin-bottom: 10px; }
        .rule-toggle-group label { background: var(--bg-primary); padding: 5px 10px; border-radius: 4px; cursor: pointer; font-size: 12px; }
        .rule-toggle-group input { display: none; }
        .rule-toggle-group input:checked + label { background: var(--accent-green); color: white; }
        .rule-sentence { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-bottom: 10px; }
        .rule-sentence span { font-size: 14px; }
        .rule-sentence .bot-input { width: auto; flex-grow: 1; min-width: 80px; }
        .rule-sentence .bot-input[type=number] { max-width: 100px; }
        .remove-btn, .move-btn { color: #fff; cursor: pointer; font-weight: bold; background: none; border: none; font-size: 18px; padding: 0 5px; }
        .remove-btn { color: var(--accent-red); }
        .btn-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
        hr { border: none; border-top: 1px solid var(--bg-secondary); margin: 15px 0; }
        .resizer { position: absolute; z-index: 10; }
        .resizer-r { cursor: e-resize; height: 100%; width: 5px; right: 0; top: 0; }
        .resizer-l { cursor: w-resize; height: 100%; width: 5px; left: 0; top: 0; }
        .resizer-b { cursor: s-resize; height: 5px; width: 100%; right: 0; bottom: 0; }
        .resizer-t { cursor: n-resize; height: 5px; width: 100%; left: 0; top: 0; }
        .resizer-br { cursor: se-resize; height: 15px; width: 15px; right: 0; bottom: 0; }
        .resizer-bl { cursor: sw-resize; height: 15px; width: 15px; left: 0; bottom: 0; }
        .resizer-tr { cursor: ne-resize; height: 15px; width: 15px; right: 0; top: 0; }
        .resizer-tl { cursor: nw-resize; height: 15px; width: 15px; left: 0; top: 0; }
        .resizer-br::after { content: ''; position: absolute; bottom: 0; right: 0; width: 0; height: 0; border-style: solid; border-width: 0 0 12px 12px; border-color: transparent transparent rgba(177, 186, 211, 0.2) transparent; pointer-events: none; }
        #bot-notification-container { position: fixed; top: 20px; right: 20px; z-index: 10005; display: flex; flex-direction: column; gap: 10px; }
        .bot-notification { background-color: var(--bg-secondary); color: white; padding: 15px; border-radius: 8px; box-shadow: 0 3px 10px rgba(0,0,0,0.3); width: 300px; opacity: 0; transform: translateX(100%); animation: slideIn 0.5s forwards; }
        .bot-notification.fade-out { animation: slideOut 0.5s forwards; }
        .bot-notification-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
        .bot-notification-header span { font-weight: bold; }
        .bot-notification-header .close-btn { background: none; border: none; color: #b1bad3; font-size: 20px; cursor: pointer; line-height: 1; }
        @keyframes slideIn { from { opacity: 0; transform: translateX(100%); } to { opacity: 1; transform: translateX(0); } }
        @keyframes slideOut { from { opacity: 1; transform: translateX(0); } to { opacity: 0; transform: translateX(100%); } }
    `;

    // --- CORE LOGIC ---

    function init() {
        if (isBotInitialized) return;
        isBotInitialized = true;

        loadConfig();
        loadStrategies();

        document.body.insertAdjacentHTML('beforeend', botHtml);
        GM_addStyle(botCss);
        document.getElementById('dice-bot-window').style.display = 'flex';

        applyUiScale(); // Apply loaded scale on startup
        loadSecurityConfig();
        populateConfigTab();
        populateStrategyDropdowns();
        setupEventListeners();
        makeDraggable(document.getElementById('dice-bot-window'), document.getElementById('bot-header'));
        makeDraggable(document.getElementById('dice-bot-minimized-bar'), document.getElementById('dice-bot-minimized-bar'));
        makeResizable(document.getElementById('dice-bot-window'));


        log("Bot UI Initialized. Waiting for game interface...", "system");
        waitForGameAndEnable();
        updateSemiAutoDescription();
        updateProfitDisplay();

        if (storedPasswordHash) {
            lockUI();
        } else {
            updateAdminStatus("No password set. Bot is unlocked.", "info");
        }
    }

    function setupEventListeners() {
        // Window Controls
        document.getElementById('minimize-btn').addEventListener('click', minimizeBot);
        document.getElementById('close-btn').addEventListener('click', closeBot);
        document.getElementById('maximize-btn').addEventListener('click', maximizeBot);
        document.getElementById('close-minimized-btn').addEventListener('click', closeBot);

        // Tab switching
        const tabButtons = document.querySelectorAll('.bot-tab-btn');
        const tabContents = document.querySelectorAll('.bot-tab-content');
        tabButtons.forEach(btn => {
            btn.addEventListener('click', (e) => {
                if (state.isLocked && e.currentTarget.dataset.tab !== 'semi-auto' && e.currentTarget.dataset.tab !== 'admin') {
                    promptForPassword(unlockUI);
                    return;
                }
                const tabName = e.currentTarget.dataset.tab;

                tabButtons.forEach(b => b.classList.remove('active'));
                e.currentTarget.classList.add('active');

                tabContents.forEach(content => {
                    if (content.id === `tab-${tabName}`) {
                        content.classList.add('active');
                    } else {
                        content.classList.remove('active');
                    }
                });
            });
        });


        // Main controls
        document.getElementById('start-stop-btn').addEventListener('click', toggleBot);
        document.getElementById('semi-auto-step-btn').addEventListener('click', runSemiAutoStep);
        document.getElementById('semi-auto-reset-btn').addEventListener('click', resetSemiAutoProgression);
        document.getElementById('manual-change-seed-btn').addEventListener('click', handleManualSeedChange);
        document.getElementById('semi-auto-strategy').addEventListener('change', updateSemiAutoDescription);

        // Config tab
        document.getElementById('save-config-btn').addEventListener('click', saveConfig);
        document.getElementById('reset-config-btn').addEventListener('click', resetConfigToDefault);

        // Log Tab
        document.getElementById('save-log-btn').addEventListener('click', saveLogToFile);
        document.getElementById('reset-stats-btn').addEventListener('click', resetState);

        // Advanced Strategy tab
        document.getElementById('create-strategy-btn').addEventListener('click', () => openStrategyModal());
        document.getElementById('edit-strategy-btn').addEventListener('click', editSelectedStrategy);
        document.getElementById('delete-strategy-btn').addEventListener('click', deleteSelectedStrategy);
        document.getElementById('import-strategy-btn').addEventListener('click', importStrategy);
        document.getElementById('export-strategy-btn').addEventListener('click', exportSelectedStrategy);
        document.getElementById('save-strategy-btn').addEventListener('click', saveStrategy);
        document.getElementById('cancel-strategy-btn').addEventListener('click', () => document.getElementById('strategy-modal').style.display = 'none');
        document.getElementById('add-rule-btn').addEventListener('click', () => addRuleToModal());

        // Admin tab
        document.getElementById('save-credentials-btn').addEventListener('click', saveCredentials);
        document.getElementById('lock-unlock-btn').addEventListener('click', handleLockUnlock);

        // Password Prompt
        document.getElementById('password-prompt-submit').addEventListener('click', handleSubmitPassword);
        document.getElementById('password-prompt-cancel').addEventListener('click', () => document.getElementById('password-prompt-modal').style.display = 'none');

        // Log Filters
        document.getElementById('log-filters').addEventListener('change', (e) => {
            if (e.target.matches('input[type="checkbox"]')) {
                logFilters[e.target.dataset.filter] = e.target.checked;
                applyLogFilters();
            }
        });

        // Other listeners
        document.getElementById('auto-strategy-select').addEventListener('change', (e) => {
            document.getElementById('on-win-loss-container').classList.toggle('disabled', e.target.value !== 'none');
        });
        document.addEventListener('keydown', handleKeydown);
    }

    function toggleBot() {
        if (state.running) { // Stopping
            state.running = false;
            const btn = document.getElementById('start-stop-btn');
            btn.textContent = 'Start Auto (S)';
            btn.classList.remove('bot-btn-danger');
            btn.classList.add('bot-btn-primary');
            updateStatus('Stopped');
            log("Auto betting stopped.", "auto");
            updateInputDisabledState();

            if (state.originalAutoStrategy) {
                const autoSelect = document.getElementById('auto-strategy-select');
                const semiAutoSelect = document.getElementById('semi-auto-strategy');
                autoSelect.value = state.originalAutoStrategy;
                semiAutoSelect.value = state.originalAutoStrategy;
                state.originalAutoStrategy = null;
                log("Strategy selection reverted to original.", "system");
            }

            if (state.originalBetDelay) {
                CONFIG.betDelay = state.originalBetDelay;
                state.originalBetDelay = null;
                updateBetDelayConfigUI();
                log(`Bet delay reverted to config default: ${CONFIG.betDelay}ms`, "system");
            }

        } else { // Starting
            state.running = true;
            state.originalAutoStrategy = document.getElementById('auto-strategy-select').value;
            state.originalBetDelay = CONFIG.betDelay; // Save current delay
            const btn = document.getElementById('start-stop-btn');
            btn.textContent = 'Stop Auto (S)';
            btn.classList.remove('bot-btn-primary');
            btn.classList.add('bot-btn-danger');
            updateStatus('Auto Running...');
            updateInputDisabledState();
            startBot();
        }
    }

    // --- WINDOW CONTROLS ---
    function minimizeBot() {
        document.getElementById('dice-bot-window').style.display = 'none';
        document.getElementById('dice-bot-minimized-bar').style.display = 'flex';
    }

    function maximizeBot() {
        document.getElementById('dice-bot-window').style.display = 'flex';
        document.getElementById('dice-bot-minimized-bar').style.display = 'none';
    }

    function closeBot() {
        document.getElementById('dice-bot-window').style.display = 'none';
        document.getElementById('dice-bot-minimized-bar').style.display = 'none';
        log("Bot window closed. Refresh the page to reopen.", "system");
    }


    // --- SECURITY & ADMIN ---

    async function hashPassword(password) {
        const encoder = new TextEncoder();
        const data = encoder.encode(password);
        const hashBuffer = await crypto.subtle.digest('SHA-256', data);
        const hashArray = Array.from(new Uint8Array(hashBuffer));
        return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
    }

    function loadSecurityConfig() {
        storedUsername = localStorage.getItem('stakeDiceBotUser') || '';
        storedPasswordHash = localStorage.getItem('stakeDiceBotPassHash') || '';
        document.getElementById('admin-username').value = storedUsername;
    }

    async function saveCredentials() {
        const usernameInput = document.getElementById('admin-username');
        const passwordInput = document.getElementById('admin-password');
        const newUsername = usernameInput.value.trim();
        const newPassword = passwordInput.value;

        const performSave = async () => {
            let changesMade = false;
            if (newUsername !== storedUsername) {
                storedUsername = newUsername;
                localStorage.setItem('stakeDiceBotUser', storedUsername);
                log("Username updated.", "system");
                changesMade = true;
            }

            if (newPassword) {
                storedPasswordHash = await hashPassword(newPassword);
                localStorage.setItem('stakeDiceBotPassHash', storedPasswordHash);
                passwordInput.value = '';
                log("Password updated.", "system");
                updateAdminStatus("Password updated. You can now lock the bot.", "info");
                changesMade = true;
            }

            if (changesMade) {
                showNotification('Credentials saved!');
            }
        };

        if (newPassword && storedPasswordHash) {
            promptForPassword(performSave, "Enter your CURRENT password to save changes.");
        } else {
            await performSave();
        }
    }


    function handleLockUnlock() {
        if (state.isLocked) {
            promptForPassword(unlockUI);
        } else {
            if (!storedPasswordHash) {
                showNotification("Please set a password before locking.");
                return;
            }
            lockUI();
        }
    }

    function lockUI() {
        state.isLocked = true;
        document.querySelector('.bot-tab-btn[data-tab="semi-auto"]').click();
        document.querySelector('.bot-tabs').classList.add('locked');
        const lockBtn = document.getElementById('lock-unlock-btn');
        lockBtn.textContent = "Unlock";
        lockBtn.classList.remove('bot-btn-primary');
        lockBtn.classList.add('bot-btn-danger');
        updateAdminStatus(`Locked by ${storedUsername || 'Admin'}. UI is restricted.`, "locked");
        log("Bot settings locked.", "system");
    }

    function unlockUI() {
        state.isLocked = false;
        document.querySelector('.bot-tabs').classList.remove('locked');
        const lockBtn = document.getElementById('lock-unlock-btn');
        lockBtn.textContent = "Lock";
        lockBtn.classList.remove('bot-btn-danger');
        lockBtn.classList.add('bot-btn-primary');
        updateAdminStatus("Bot is unlocked. Settings are editable.", "unlocked");
        log("Bot settings unlocked.", "system");
    }

    function promptForPassword(onSuccess, message = "Please enter the password to unlock this feature.") {
        const modal = document.getElementById('password-prompt-modal');
        if (modal.style.display === 'flex') return;

        pendingAction = onSuccess;
        const messageEl = document.getElementById('password-prompt-message');
        const errorEl = document.getElementById('password-prompt-error');

        if (messageEl) messageEl.textContent = message;
        document.getElementById('prompt-password-input').value = "";
        errorEl.style.display = 'none';
        modal.style.display = 'flex';
        document.getElementById('prompt-password-input').focus();
    }

    async function handleSubmitPassword() {
        const password = document.getElementById('prompt-password-input').value;
        const hash = await hashPassword(password);
        if (hash === storedPasswordHash) {
            document.getElementById('password-prompt-modal').style.display = 'none';
            if (typeof pendingAction === 'function') {
                pendingAction();
            }
            pendingAction = null;
        } else {
            const errorEl = document.getElementById('password-prompt-error');
            errorEl.textContent = "Incorrect password. Please try again.";
            errorEl.style.display = 'block';
        }
    }

    function updateAdminStatus(text, status) {
        const statusEl = document.getElementById('admin-status');
        if (!statusEl) return;
        statusEl.textContent = text;
        if (status === 'locked') {
            statusEl.style.color = 'var(--accent-red)';
        } else if (status === 'unlocked') {
            statusEl.style.color = 'var(--accent-green)';
        } else {
            statusEl.style.color = '#b1bad3';
        }
    }


    // --- API & NETWORK LOGIC ---

    function getAuthToken() {
        const cookieToken = document.cookie.split('; ').find(row => row.startsWith('session='))?.split('=')[1];
        if (cookieToken) {
            console.log("Auto-detected auth token from cookie.");
            return cookieToken;
        }
        for (let i = 0; i < localStorage.length; i++) {
            const key = localStorage.key(i);
            const value = localStorage.getItem(key);
            if (typeof value === 'string' && value.split('.').length === 3 && value.startsWith('ey')) {
                console.log(`Auto-detected auth token in localStorage key: "${key}"`);
                return value;
            }
        }
        console.warn("Could not auto-detect auth token.");
        return '';
    }

    function generateRandomSeed() {
        const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        const length = Math.floor(Math.random() * 64) + 1;
        let seed = '';
        for (let i = 0; i < length; i++) {
            seed += chars.charAt(Math.floor(Math.random() * chars.length));
        }
        return seed;
    }

    async function changeSeedProgrammatically() {
        updateStatus("Changing Seed...");
        log("Attempting to change seed via API...", "strategy");
        const token = CONFIG.authToken;
        if (!token) {
            updateStatus("Error: Auth Token not found!");
            // showNotification("Seed change failed: Authentication Token is missing.", "error"); // Removed
            log("Seed change failed: Auth Token missing.", "error");
            return false;
        }

        const newClientSeed = generateRandomSeed();

        const graphqlQuery = {
            query: `
                mutation changeClientSeed($seed: String!) {
                    changeClientSeed(seed: $seed) {
                        id
                        seed
                        __typename
                    }
                }
            `,
            variables: {
                seed: newClientSeed
            },
            operationName: "changeClientSeed"
        };

        try {
            const response = await fetch(CONFIG.seedChangeEndpoint, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'x-access-token': token,
                },
                body: JSON.stringify(graphqlQuery),
            });

            const contentType = response.headers.get("content-type");
            if (!contentType || !contentType.includes("application/json")) {
                const responseText = await response.text();
                if (responseText.includes("Cloudflare") || responseText.toLowerCase().includes("<!doctype html")) {
                    throw new Error("API request was blocked, likely by Cloudflare. The response was HTML, not JSON.");
                }
                throw new Error(`API returned a non-JSON response. Status: ${response.status}`);
            }

            const responseData = await response.json();

            if (!response.ok || responseData.errors || (responseData.data && !responseData.data.changeClientSeed)) {
                let errorMessage = 'Unknown API error';
                if (responseData.errors) {
                    errorMessage = responseData.errors.map(e => e.message).join(', ');
                } else if (responseData.message) {
                    errorMessage = responseData.message;
                }

                throw new Error(`API Error: ${errorMessage}`);
            }

            console.log("Successfully changed seed via API:", responseData);
            updateStatus("Seed Changed!");
            log(`Seed changed successfully. New seed: ${newClientSeed}`, "strategy");
            return true;
        } catch (error) {
            console.error("Failed to change seed programmatically:", error);
            updateStatus("Error: Seed change failed.");
            // showNotification(`Seed change failed: ${error.message}.`); // Removed
            log(`Seed change failed: ${error.message}`, "error");
            return false;
        }
    }

    // --- CONFIGURATION MANAGEMENT ---

    function populateConfigTab() {
        const container = document.getElementById('config-container');
        container.innerHTML = '';
        for (const key in CONFIG) {
            const friendlyName = CONFIG_FRIENDLY_NAMES[key] || key;
            const group = document.createElement('div');
            group.className = 'config-group';

            let inputWrapperHtml = '';
            let labelHtml = `<label for="config-${key}">${friendlyName}</label>`;

            if (key === 'betDelay') {
                labelHtml = `<label>${friendlyName}
                    <span class="config-tooltip-trigger" style="display: none;">?
                        <span class="tooltip-text">A low delay (< 20ms) can cause the bot to miss bet results. Use with caution.</span>
                    </span>
                </label>`;

                const parts = String(CONFIG.betDelay).split('-').map(p => p.trim());
                const min = parts[0] || '';
                const max = parts[1] || '';

                inputWrapperHtml = `
                    <div class="input-wrapper config-range-wrapper">
                        <input type="number" id="config-betDelay-min" class="bot-input" value="${min}" placeholder="Min">
                        <span>to</span>
                        <input type="number" id="config-betDelay-max" class="bot-input" value="${max}" placeholder="Max">
                    </div>
                `;
                group.innerHTML = `${labelHtml}${inputWrapperHtml}`;
                container.appendChild(group);

            } else if (key === 'uiScale') {
                group.innerHTML = `
                    <label for="config-uiScale">${friendlyName}</label>
                    <div class="input-wrapper" style="display: flex; align-items: center; gap: 10px;">
                        <input type="range" id="config-uiScale" class="bot-input" min="50" max="150" value="${CONFIG[key]}" style="flex-grow: 1; padding: 0;">
                        <span id="config-uiScale-value" style="flex-basis: 40px; text-align: right;">${CONFIG[key]}%</span>
                    </div>
                `;
                container.appendChild(group);

            } else {
                const isSelector = !["authToken", "seedChangeEndpoint", "baseWinChance", "maxBetAmount"].includes(key);
                if (key === 'authToken') {
                    inputWrapperHtml = `
                        <div class="input-wrapper">
                            <input type="password" id="config-${key}" class="bot-input" value="${CONFIG[key]}" placeholder="Auto-detected or paste here">
                            <button class="config-toggle-vis-btn" data-target="config-${key}">
                                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>
                            </button>
                        </div>
                    `;
                } else {
                    inputWrapperHtml = `
                        <div class="input-wrapper">
                            <input type="text" id="config-${key}" class="bot-input" value="${CONFIG[key]}">
                            ${isSelector ? `<button class="config-pick-btn" data-key="${key}">Pick</button>` : ''}
                        </div>
                    `;
                }
                group.innerHTML = `${labelHtml}${inputWrapperHtml}`;
                container.appendChild(group);
            }
        }

        container.querySelectorAll('.config-pick-btn').forEach(btn => btn.addEventListener('click', (e) => initSelectorPicker(e.target.dataset.key)));
        container.querySelectorAll('.config-toggle-vis-btn').forEach(btn => {
            btn.addEventListener('click', (e) => {
                const targetInput = document.getElementById(e.currentTarget.dataset.target);
                if (targetInput) {
                    const isPassword = targetInput.type === 'password';
                    targetInput.type = isPassword ? 'text' : 'password';
                    e.currentTarget.innerHTML = isPassword ?
                        `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path><line x1="1" y1="1" x2="23" y2="23"></line></svg>` :
                        `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path><circle cx="12" cy="12" r="3"></circle></svg>`;
                }
            });
        });

        const minDelayInput = document.getElementById('config-betDelay-min');
        const maxDelayInput = document.getElementById('config-betDelay-max');

        if (minDelayInput && maxDelayInput) {
            const groupEl = minDelayInput.closest('.config-group');
            const tooltipTrigger = groupEl ? groupEl.querySelector('.config-tooltip-trigger') : null;

            const validateDelay = () => {
                const minVal = minDelayInput.value.trim();
                const maxVal = maxDelayInput.value.trim();
                const min = parseInt(minVal, 10);
                const max = parseInt(maxVal, 10);

                let isValid = true;
                let showWarning = false;

                if (minVal && isNaN(min)) isValid = false;
                if (maxVal && isNaN(max)) isValid = false;
                if (minVal && maxVal && min > max) isValid = false;
                if (!minVal && maxVal) isValid = false;

                if (minVal && min < 20) {
                    showWarning = true;
                }

                minDelayInput.classList.toggle('invalid-range', !isValid);
                maxDelayInput.classList.toggle('invalid-range', !isValid);
                if (tooltipTrigger) {
                    tooltipTrigger.style.display = showWarning ? 'inline-flex' : 'none';
                }
            };

            minDelayInput.addEventListener('input', validateDelay);
            maxDelayInput.addEventListener('input', validateDelay);
            validateDelay();
        }

        const uiScaleSlider = document.getElementById('config-uiScale');
        if (uiScaleSlider) {
            const uiScaleValue = document.getElementById('config-uiScale-value');
            uiScaleSlider.addEventListener('input', () => {
                const scale = uiScaleSlider.value;
                uiScaleValue.textContent = `${scale}%`;
                applyUiScale(scale);
            });
        }
    }

    function initSelectorPicker(configKey) {
        if (isPickingElement) return;
        isPickingElement = true;
        const overlay = document.getElementById('element-picker-overlay');
        const tooltip = document.getElementById('element-picker-tooltip');
        overlay.style.display = 'block';
        tooltip.style.display = 'block';

        const mouseMoveHandler = (e) => {
            const target = e.target;
            if (target.id === 'dice-bot-window' || target.closest('#dice-bot-window')) {
                overlay.style.display = 'none';
                return;
            }
            overlay.style.display = 'block';
            const rect = target.getBoundingClientRect();
            Object.assign(overlay.style, {
                width: `${rect.width}px`,
                height: `${rect.height}px`,
                top: `${rect.top}px`,
                left: `${rect.left}px`
            });
        };

        const clickHandler = (e) => {
            e.preventDefault();
            e.stopPropagation();
            const target = e.target;
            if (target.id === 'dice-bot-window' || target.closest('#dice-bot-window')) return;
            document.getElementById(`config-${configKey}`).value = generateSelector(target);
            cleanup();
        };

        const escHandler = (e) => e.key === "Escape" && cleanup();
        const cleanup = () => {
            document.removeEventListener('mousemove', mouseMoveHandler);
            document.removeEventListener('click', clickHandler, true);
            document.removeEventListener('keydown', escHandler, true);
            overlay.style.display = 'none';
            tooltip.style.display = 'none';
            isPickingElement = false;
        };

        document.addEventListener('mousemove', mouseMoveHandler);
        document.addEventListener('click', clickHandler, true);
        document.addEventListener('keydown', escHandler, true);
    }

    function generateSelector(el) {
        if (el.getAttribute('data-testid')) return `[data-testid="${el.getAttribute('data-testid')}"]`;
        if (el.getAttribute('data-test')) return `[data-test="${el.getAttribute('data-test')}"]`;
        if (el.id) return `#${el.id}`;
        if (el.className) {
            const classNames = typeof el.className === 'string' ? el.className.split(' ').filter(c => c && !c.includes('svelte-')) : [];
            if (classNames.length > 0) return `.${classNames.join('.')}`;
        }
        return el.tagName.toLowerCase();
    }

    function saveConfig() {
        const newConfig = { ...CONFIG
        };
        for (const key in CONFIG) {
            if (key === 'betDelay') {
                const min = document.getElementById('config-betDelay-min').value.trim();
                const max = document.getElementById('config-betDelay-max').value.trim();
                if (min && max) {
                    newConfig[key] = `${min}-${max}`;
                } else if (min) {
                    newConfig[key] = min;
                } else {
                    newConfig[key] = '100';
                }
            } else {
                const el = document.getElementById(`config-${key}`);
                if (el) {
                    if (key === 'uiScale') {
                        newConfig[key] = parseInt(el.value, 10);
                    } else if (typeof CONFIG[key] === 'boolean') {
                        newConfig[key] = el.value === 'true';
                    } else {
                        newConfig[key] = el.value;
                    }
                }
            }
        }
        localStorage.setItem('stakeDiceBotConfig', JSON.stringify(newConfig));
        CONFIG = newConfig;
        showNotification('Configuration saved!');
        log("Configuration saved.", "system");
    }

    function loadConfig() {
        const hostname = window.location.hostname;
        CONFIG.seedChangeEndpoint = '/_api/graphql';
        log(`API endpoint configured for ${hostname}.`, "system");

        const saved = localStorage.getItem('stakeDiceBotConfig');
        if (saved) {
            try {
                let customConfig = JSON.parse(saved);
                const selectorKeys = ['betButton', 'amountInput', 'payoutInput', 'winChanceInput', 'gameFrame', 'pastBetsContainer', 'autoTab', 'manualTab', 'reverseRollButton'];

                // Pre-validate any selector strings to prevent runtime errors.
                for (const key of selectorKeys) {
                    if (customConfig[key] && typeof customConfig[key] === 'string') {
                        try {
                            // Dummy query to validate the selector syntax.
                            document.querySelector(customConfig[key]);
                        } catch (e) {
                            log(`Skipping invalid selector for '${key}' from saved config.`, "system");
                            // Revert this key to the default to prevent errors.
                            delete customConfig[key];
                        }
                    }
                }
                CONFIG = { ...CONFIG, ...customConfig };
                console.log("Loaded custom config from storage.");
            } catch (e) {
                console.error("Failed to parse custom config from localStorage.", e);
            }
        }
        if (!CONFIG.authToken) {
            CONFIG.authToken = getAuthToken();
        }
    }

    function resetConfigToDefault() {
        if (confirm("Are you sure you want to reset all configuration to defaults?")) {
            localStorage.removeItem('stakeDiceBotConfig');
            CONFIG = {
                authToken: '',
                seedChangeEndpoint: '/_api/graphql',
                betButton: '[data-testid="bet-button"]',
                amountInput: '[data-testid="input-game-amount"]',
                payoutInput: '[data-testid="payout"]',
                winChanceInput: '[data-testid="chance"]',
                baseWinChance: 49.5,
                betDelay: '100',
                maxBetAmount: 0,
                gameFrame: '[data-testid="game-frame"]',
                pastBetsContainer: '.past-bets',
                winClass: 'variant-success',
                lossClass: 'variant-neutral',
                autoTab: '[data-testid="auto-tab"]',
                manualTab: '[data-testid="manual-tab"]',
                reverseRollButton: '[data-testid="reverse-roll"]',
                uiScale: 100,
            };
            loadConfig();
            populateConfigTab();
            applyUiScale();
            showNotification("Configuration has been reset to default.");
            log("Configuration reset to defaults.", "system");
        }
    }

    // --- ADVANCED STRATEGY LOGIC ---

    function openStrategyModal(strategyName = '') {
        const modal = document.getElementById('strategy-modal');
        const nameInput = document.getElementById('strategy-name');
        const rulesContainer = document.getElementById('strategy-rules-container');
        document.getElementById('strategy-modal-title').textContent = strategyName ? 'Edit Strategy' : 'Create Strategy';
        nameInput.value = strategyName;
        nameInput.dataset.originalName = strategyName;
        rulesContainer.innerHTML = '';

        if (strategyName && advancedStrategies[strategyName]) {
            advancedStrategies[strategyName].forEach(rule => addRuleToModal(rule));
        } else {
            addRuleToModal();
        }
        modal.style.display = 'flex';
        validateStrategyRules();
    }

    function addRuleToModal(rule = {}) {
        const rulesContainer = document.getElementById('strategy-rules-container');
        const ruleDiv = document.createElement('div');
        ruleDiv.className = 'strategy-rule';
        const ruleId = `rule-${Date.now()}-${Math.random()}`;
        ruleDiv.id = ruleId;

        const defaults = {
            conditionType: 'bets',
            playConditionTerm: 'every',
            playConditionValue: 1,
            playConditionBetType: 'lose',
            netGainCondition: 'greater',
            netGainValue: 0,
            action: 'increaseByPercentage',
            actionValue: 100,
            timeSinceWinCondition: 'greater',
            timeSinceWinValue: 10,
            patternMatch: 'LWL',
        };
        const currentRule = { ...defaults,
            ...rule
        };

        ruleDiv.innerHTML = `
            <div class="strategy-rule-header">
                <div class="strategy-rule-summary"></div>
                <div class="strategy-rule-controls">
                    <button class="move-btn" data-direction="up" title="Move Up">↑</button>
                    <button class="move-btn" data-direction="down" title="Move Down">↓</button>
                    <button class="remove-btn" title="Remove Rule">&times;</button>
                </div>
            </div>
            <div class="strategy-rule-editor">
                <div class="rule-toggle-group">
                    <input type="radio" id="${ruleId}-type-bets" name="${ruleId}-type" value="bets" ${currentRule.conditionType === 'bets' ? 'checked' : ''}>
                    <label for="${ruleId}-type-bets">Play</label>
                    <input type="radio" id="${ruleId}-type-profit" name="${ruleId}-type" value="profit" ${currentRule.conditionType === 'profit' ? 'checked' : ''}>
                    <label for="${ruleId}-type-profit">Net Gain</label>
                    <input type="radio" id="${ruleId}-type-time" name="${ruleId}-type" value="time" ${currentRule.conditionType === 'time' ? 'checked' : ''}>
                    <label for="${ruleId}-type-time">Time</label>
                    <input type="radio" id="${ruleId}-type-pattern" name="${ruleId}-type" value="pattern" ${currentRule.conditionType === 'pattern' ? 'checked' : ''}>
                    <label for="${ruleId}-type-pattern">Pattern</label>
                </div>

                <div class="play-condition-sentence rule-sentence">
                    <span>On</span>
                    <select class="bot-input play-term">
                        <option value="every">Every</option>
                        <option value="everyStreakOf">Every streak of</option>
                        <option value="firstStreakOf">First streak of</option>
                        <option value="streakGreaterThan">Streak greater than</option>
                        <option value="streakLowerThan">Streak lower than</option>
                    </select>
                    <input type="number" class="bot-input play-value" value="${currentRule.playConditionValue}">
                    <select class="bot-input play-bet-type">
                        <option value="win">Wins</option>
                        <option value="lose">Losses</option>
                        <option value="bet">Games</option>
                    </select>
                </div>
                <div class="net-gain-condition-sentence rule-sentence">
                    <span>If Net Gain is</span>
                    <select class="bot-input net-gain-condition">
                        <option value="greater">&gt;</option>
                        <option value="less">&lt;</option>
                        <option value="=">=</option>
                    </select>
                    <input type="number" step="any" class="bot-input net-gain-value" value="${currentRule.netGainValue}">
                </div>
                <div class="time-condition-sentence rule-sentence">
                    <span>If time since last win is</span>
                    <select class="bot-input time-condition">
                        <option value="greater">&gt;</option>
                        <option value="less">&lt;</option>
                    </select>
                    <input type="number" class="bot-input time-value" value="${currentRule.timeSinceWinValue}">
                    <span>seconds</span>
                </div>
                <div class="pattern-condition-sentence rule-sentence">
                    <span>If last bets match pattern</span>
                    <input type="text" class="bot-input pattern-value" placeholder="e.g. LWL" value="${currentRule.patternMatch}">
                </div>

                <div class="action-sentence rule-sentence">
                    <span>Do</span>
                    <select class="bot-input action-type">
                        <option value="increaseByPercentage">Increase Amount by %</option>
                        <option value="decreaseByPercentage">Decrease Amount by %</option>
                        <option value="setAmount">Set Amount</option>
                        <option value="resetAmount">Reset Amount</option>
                        <option value="setBaseBet">Set Base Bet</option>
                        <option value="increaseBaseBetByPercentage">Increase Base Bet by %</option>
                        <option value="decreaseBaseBetByPercentage">Decrease Base Bet by %</option>
                        <option value="increaseWinChanceBy">Increase Win Chance by %</option>
                        <option value="decreaseWinChanceBy">Decrease Win Chance by %</option>
                        <option value="setWinChance">Set Win Chance</option>
                        <option value="resetWinChance">Reset Win Chance</option>
                        <option value="setBetSpeed">Set Bet Speed</option>
                        <option value="switchOverUnder">Switch Over/Under</option>
                        <option value="changeSeed">Change Seed (API)</option>
                        <option value="switchStrategy">Switch Strategy</option>
                        <option value="stop">Stop Autoplay</option>
                        <option value="notify">Show Notification</option>
                    </select>
                    <input type="number" step="any" class="bot-input action-value" value="${currentRule.actionValue}">
                    <input type="text" class="bot-input action-value-text" style="display: none;" placeholder="Notification message...">
                    <select class="bot-input action-strategy-select" style="display: none;"></select>
                    <div class="config-range-wrapper action-value-range" style="display: none;">
                        <input type="number" class="bot-input action-value-range-min" placeholder="Min">
                        <span>to</span>
                        <input type="number" class="bot-input action-value-range-max" placeholder="Max">
                        <span>ms</span>
                    </div>
                </div>
            </div>
        `;
        rulesContainer.appendChild(ruleDiv);

        ruleDiv.querySelector('.play-term').value = currentRule.playConditionTerm;
        ruleDiv.querySelector('.play-bet-type').value = currentRule.playConditionBetType;
        ruleDiv.querySelector('.net-gain-condition').value = currentRule.netGainCondition;
        ruleDiv.querySelector('.time-condition').value = currentRule.timeSinceWinCondition;
        ruleDiv.querySelector('.action-type').value = currentRule.action;

        const actionStrategySelect = ruleDiv.querySelector('.action-strategy-select');
        for (const name in advancedStrategies) {
            actionStrategySelect.add(new Option(name, name));
        }
        if (currentRule.action === 'switchStrategy') {
            actionStrategySelect.value = currentRule.actionValue;
        }


        const summary = ruleDiv.querySelector('.strategy-rule-summary');
        const playSentence = ruleDiv.querySelector('.play-condition-sentence');
        const netGainSentence = ruleDiv.querySelector('.net-gain-condition-sentence');
        const timeSentence = ruleDiv.querySelector('.time-condition-sentence');
        const patternSentence = ruleDiv.querySelector('.pattern-condition-sentence');
        const actionValueInput = ruleDiv.querySelector('.action-value');
        const actionValueTextInput = ruleDiv.querySelector('.action-value-text');
        const actionValueRange = ruleDiv.querySelector('.action-value-range');
        const actionTypeSelect = ruleDiv.querySelector('.action-type');

        if (currentRule.action === 'notify') {
            actionValueTextInput.value = currentRule.actionValue;
        } else if (currentRule.action === 'setBetSpeed' && typeof currentRule.actionValue === 'string') {
            const [min, max] = currentRule.actionValue.split('-');
            ruleDiv.querySelector('.action-value-range-min').value = min || '';
            ruleDiv.querySelector('.action-value-range-max').value = max || '';
        }

        const updateVisibility = () => {
            const type = ruleDiv.querySelector(`input[name="${ruleId}-type"]:checked`).value;
            playSentence.style.display = type === 'bets' ? '' : 'none';
            netGainSentence.style.display = type === 'profit' ? '' : 'none';
            timeSentence.style.display = type === 'time' ? '' : 'none';
            patternSentence.style.display = type === 'pattern' ? '' : 'none';

            const actionType = actionTypeSelect.value;
            const noValueActions = ['resetAmount', 'resetWinChance', 'switchOverUnder', 'changeSeed', 'stop'];
            const isSwitchStrategy = actionType === 'switchStrategy';
            const isNotify = actionType === 'notify';
            const isSetSpeed = actionType === 'setBetSpeed';

            actionValueInput.style.display = noValueActions.includes(actionType) || isSwitchStrategy || isNotify || isSetSpeed ? 'none' : 'block';
            actionValueTextInput.style.display = isNotify ? 'block' : 'none';
            actionStrategySelect.style.display = isSwitchStrategy ? 'block' : 'none';
            actionValueRange.style.display = isSetSpeed ? 'flex' : 'none';


            validateStrategyRules();
            updateSummary();
        };

        const updateSummary = () => {
            const type = ruleDiv.querySelector(`input[name="${ruleId}-type"]:checked`).value;
            let conditionText = '';
            if (type === 'bets') {
                const term = ruleDiv.querySelector('.play-term option:checked').textContent;
                const value = ruleDiv.querySelector('.play-value').value;
                const betType = ruleDiv.querySelector('.play-bet-type option:checked').textContent;
                conditionText = `On ${term} ${value} ${betType}`;
            } else if (type === 'profit') {
                const op = ruleDiv.querySelector('.net-gain-condition option:checked').textContent;
                const value = ruleDiv.querySelector('.net-gain-value').value;
                conditionText = `If Net Gain ${op} ${value}`;
            } else if (type === 'time') {
                const op = ruleDiv.querySelector('.time-condition option:checked').textContent;
                const value = ruleDiv.querySelector('.time-value').value;
                conditionText = `If time since win ${op} ${value}s`;
            } else if (type === 'pattern') {
                const value = ruleDiv.querySelector('.pattern-value').value;
                conditionText = `If pattern is ${value}`;
            }

            const actionType = actionTypeSelect.value;
            const actionText = actionTypeSelect.options[actionTypeSelect.selectedIndex].textContent;
            let actionValueText = '';
            const noValueActions = ['resetAmount', 'resetWinChance', 'switchOverUnder', 'changeSeed', 'stop'];

            if (!noValueActions.includes(actionType)) {
                if (actionType === 'switchStrategy') {
                    actionValueText = ` to ${actionStrategySelect.value}`;
                } else if (actionType === 'notify') {
                    actionValueText = ` "${actionValueTextInput.value}"`;
                } else if (actionType === 'setBetSpeed') {
                    const min = ruleDiv.querySelector('.action-value-range-min').value;
                    const max = ruleDiv.querySelector('.action-value-range-max').value;
                    actionValueText = ` to ${min || '?'} - ${max || '?'}ms`;
                } else {
                    actionValueText = ` ${actionValueInput.value}`;
                }
            }

            summary.innerHTML = `<span>${conditionText} →</span><span class="summary-action">${actionText}${actionValueText}</span>`;
        };

        ruleDiv.querySelector('.strategy-rule-header').addEventListener('click', (e) => {
            if (!e.target.matches('.move-btn, .remove-btn')) {
                ruleDiv.classList.toggle('expanded');
                updateSummary();
            }
        });

        ruleDiv.querySelectorAll('input, select').forEach(el => el.addEventListener('change', updateVisibility));
        ruleDiv.querySelectorAll('input, select').forEach(el => el.addEventListener('input', updateSummary));


        ruleDiv.querySelector('.remove-btn').addEventListener('click', () => {
            ruleDiv.remove();
            validateStrategyRules();
        });

        ruleDiv.querySelectorAll('.move-btn').forEach(btn => {
            btn.addEventListener('click', (e) => {
                const direction = e.target.dataset.direction;
                const parent = ruleDiv.parentNode;
                if (direction === 'up' && ruleDiv.previousElementSibling) {
                    parent.insertBefore(ruleDiv, ruleDiv.previousElementSibling);
                } else if (direction === 'down' && ruleDiv.nextElementSibling) {
                    parent.insertBefore(ruleDiv.nextElementSibling, ruleDiv);
                }
            });
        });

        updateVisibility();
    }

    function validateStrategyRules() {
        const warningEl = document.getElementById('strategy-modal-warning');
        const saveBtn = document.getElementById('save-strategy-btn');
        // All validation logic for seed changes has been removed.
        warningEl.style.display = 'none';
        saveBtn.disabled = false;
    }


    function saveStrategy() {
        validateStrategyRules();
        if (document.getElementById('save-strategy-btn').disabled) {
            showNotification("Please fix the errors in your strategy before saving.", "error");
            return;
        }

        const nameInput = document.getElementById('strategy-name');
        const originalName = nameInput.dataset.originalName;
        const newName = nameInput.value.trim();
        if (!newName) {
            showNotification('Strategy name cannot be empty.', "error");
            return;
        }
        if (newName !== originalName && advancedStrategies[newName]) {
            showNotification('A strategy with this name already exists.', "error");
            return;
        }

        const rules = [];
        document.querySelectorAll('.strategy-rule').forEach(ruleDiv => {
            const action = ruleDiv.querySelector('.action-type').value;
            let actionValue;
            if (action === 'switchStrategy') {
                actionValue = ruleDiv.querySelector('.action-strategy-select').value;
            } else if (action === 'notify') {
                actionValue = ruleDiv.querySelector('.action-value-text').value;
            } else if (action === 'setBetSpeed') {
                const min = ruleDiv.querySelector('.action-value-range-min').value.trim();
                const max = ruleDiv.querySelector('.action-value-range-max').value.trim();
                if (min && max) {
                    actionValue = `${min}-${max}`;
                } else {
                    actionValue = min;
                }
            } else {
                actionValue = parseFloat(ruleDiv.querySelector('.action-value').value);
            }

            rules.push({
                conditionType: ruleDiv.querySelector('input[name*="-type"]:checked').value,
                playConditionTerm: ruleDiv.querySelector('.play-term').value,
                playConditionValue: parseFloat(ruleDiv.querySelector('.play-value').value),
                playConditionBetType: ruleDiv.querySelector('.play-bet-type').value,
                netGainCondition: ruleDiv.querySelector('.net-gain-condition').value,
                netGainValue: parseFloat(ruleDiv.querySelector('.net-gain-value').value),
                timeSinceWinCondition: ruleDiv.querySelector('.time-condition').value,
                timeSinceWinValue: parseFloat(ruleDiv.querySelector('.time-value').value),
                patternMatch: ruleDiv.querySelector('.pattern-value').value,
                action: action,
                actionValue: actionValue,
            });
        });

        if (originalName && originalName !== newName) {
            delete advancedStrategies[originalName];
        }
        advancedStrategies[newName] = rules;
        saveStrategies();
        document.getElementById('strategy-modal').style.display = 'none';
        log(`Strategy '${newName}' saved.`, "system");
    }

    function editSelectedStrategy() {
        const selectedName = document.getElementById('advanced-strategy-list').value;
        if (selectedName) {
            openStrategyModal(selectedName);
        } else {
            showNotification('Please select a strategy to edit.', "error");
        }
    }

    function deleteSelectedStrategy() {
        const selectedName = document.getElementById('advanced-strategy-list').value;
        if (selectedName && confirm(`Are you sure you want to delete the strategy "${selectedName}"?`)) {
            delete advancedStrategies[selectedName];
            saveStrategies();
            log(`Strategy '${selectedName}' deleted.`, "system");
        }
    }

    async function executeAdvancedStrategy(rules, targetState, baseBet) {
        let betAmountModified = false;
        let winChanceModified = false;
        const currentStrategyName = document.getElementById('auto-strategy-select').value;

        // Reset persistent trigger flags if their conditions are no longer met
        for (const ruleKey in state.persistentTriggerStates) {
            const [strategyName, ruleIndex] = ruleKey.split('-');
            if (strategyName !== currentStrategyName || !advancedStrategies[strategyName] || !advancedStrategies[strategyName][ruleIndex]) {
                delete state.persistentTriggerStates[ruleKey];
                continue;
            }
            const rule = advancedStrategies[strategyName][ruleIndex];
            const isConditionMet = checkCondition(rule);
            if (!isConditionMet) {
                delete state.persistentTriggerStates[ruleKey];
                log(`Persistent trigger for Rule #${parseInt(ruleIndex)+1} reset.`, "strategy");
            }
        }

        for (const [index, rule] of rules.entries()) {
            const conditionMet = checkCondition(rule);
            let conditionText = ''; // You can expand this to generate text for notifications if needed

            if (conditionMet) {
                log(`<b>Strategy Trigger:</b> Rule #${index + 1}`, "strategy");

                const action = rule.action;
                const isBetAction = ['increaseByPercentage', 'decreaseByPercentage', 'setAmount', 'resetAmount', 'setBaseBet', 'increaseBaseBetByPercentage', 'decreaseBaseBetByPercentage'].includes(action);
                const isWinChanceAction = ['increaseWinChanceBy', 'decreaseWinChanceBy', 'setWinChance', 'resetWinChance'].includes(action);
                const isOneTimeAction = ['changeSeed'];
                const isPersistentCondition = ['profit', 'time'].includes(rule.conditionType);

                if (isBetAction && betAmountModified) {
                    log(`&nbsp;&nbsp;↳ Action skipped: Bet amount already modified in this step.`, "strategy");
                    continue;
                }
                if (isWinChanceAction && winChanceModified) {
                    log(`&nbsp;&nbsp;↳ Action skipped: Win chance already modified in this step.`, "strategy");
                    continue;
                }

                if (isOneTimeAction.includes(action) && isPersistentCondition) {
                    const ruleKey = `${currentStrategyName}-${index}`;
                    if (state.persistentTriggerStates[ruleKey]) {
                        log(`&nbsp;&nbsp;↳ Action skipped: Persistent trigger already fired.`, "strategy");
                        continue;
                    }
                    state.persistentTriggerStates[ruleKey] = true;
                }


                switch (action) {
                    case 'increaseByPercentage':
                        targetState.currentBet *= (1 + rule.actionValue / 100);
                        log(`&nbsp;&nbsp;↳ Action: Increased bet by ${rule.actionValue}%. New bet: ${targetState.currentBet.toFixed(8)}`, "strategy");
                        break;
                    case 'decreaseByPercentage':
                        targetState.currentBet *= (1 - rule.actionValue / 100);
                        log(`&nbsp;&nbsp;↳ Action: Decreased bet by ${rule.actionValue}%. New bet: ${targetState.currentBet.toFixed(8)}`, "strategy");
                        break;
                    case 'resetAmount':
                        targetState.currentBet = baseBet;
                        log(`&nbsp;&nbsp;↳ Action: Reset bet to base. New bet: ${targetState.currentBet.toFixed(8)}`, "strategy");
                        break;
                    case 'setAmount':
                        targetState.currentBet = rule.actionValue;
                        log(`&nbsp;&nbsp;↳ Action: Set bet to ${rule.actionValue}. New bet: ${targetState.currentBet.toFixed(8)}`, "strategy");
                        break;
                    case 'setBaseBet':
                        if (targetState === state) { // Auto mode
                            state.baseBet = rule.actionValue;
                            document.getElementById('base-bet').value = rule.actionValue;
                        } else { // Semi-auto mode
                            document.getElementById('semi-auto-base-bet').value = rule.actionValue;
                        }
                        log(`&nbsp;&nbsp;↳ Action: Set base bet to ${rule.actionValue}.`, "strategy");
                        break;
                    case 'increaseBaseBetByPercentage':
                        if (targetState === state) { // Auto mode
                            state.baseBet *= (1 + rule.actionValue / 100);
                            document.getElementById('base-bet').value = state.baseBet.toFixed(8);
                        } else { // Semi-auto mode
                            const semiAutoBaseEl = document.getElementById('semi-auto-base-bet');
                            semiAutoBaseEl.value = (parseFloat(semiAutoBaseEl.value) * (1 + rule.actionValue / 100)).toFixed(8);
                        }
                        log(`&nbsp;&nbsp;↳ Action: Increased base bet by ${rule.actionValue}%.`, "strategy");
                        break;
                    case 'decreaseBaseBetByPercentage':
                        if (targetState === state) { // Auto mode
                            state.baseBet *= (1 - rule.actionValue / 100);
                            document.getElementById('base-bet').value = state.baseBet.toFixed(8);
                        } else { // Semi-auto mode
                            const semiAutoBaseEl = document.getElementById('semi-auto-base-bet');
                            semiAutoBaseEl.value = (parseFloat(semiAutoBaseEl.value) * (1 - rule.actionValue / 100)).toFixed(8);
                        }
                        log(`&nbsp;&nbsp;↳ Action: Decreased base bet by ${rule.actionValue}%.`, "strategy");
                        break;
                    case 'increaseWinChanceBy':
                        {
                            const input = document.querySelector(CONFIG.winChanceInput);
                            if (input) {
                                const currentVal = parseFloat(input.value) || 49.5;
                                const newVal = Math.min(98, currentVal + rule.actionValue);
                                setUIValue(CONFIG.winChanceInput, newVal);
                                log(`&nbsp;&nbsp;↳ Action: Increased win chance by ${rule.actionValue}%. New chance: ${newVal}%`, "strategy");
                            }
                            break;
                        }
                    case 'decreaseWinChanceBy':
                        {
                            const input = document.querySelector(CONFIG.winChanceInput);
                            if (input) {
                                const currentVal = parseFloat(input.value) || 49.5;
                                const newVal = Math.max(0.01, currentVal - rule.actionValue);
                                setUIValue(CONFIG.winChanceInput, newVal);
                                log(`&nbsp;&nbsp;↳ Action: Decreased win chance by ${rule.actionValue}%. New chance: ${newVal}%`, "strategy");
                            }
                            break;
                        }
                    case 'setWinChance':
                        setUIValue(CONFIG.winChanceInput, rule.actionValue);
                        log(`&nbsp;&nbsp;↳ Action: Set win chance to ${rule.actionValue}%.`, "strategy");
                        break;
                    case 'resetWinChance':
                        setUIValue(CONFIG.winChanceInput, CONFIG.baseWinChance);
                        log(`&nbsp;&nbsp;↳ Action: Reset win chance to base (${CONFIG.baseWinChance}%).`, "strategy");
                        break;
                    case 'setBetSpeed':
                        CONFIG.betDelay = rule.actionValue;
                        updateBetDelayConfigUI();
                        log(`&nbsp;&nbsp;↳ Action: Set bet speed to ${rule.actionValue}ms.`, "strategy");
                        break;
                    case 'stop':
                        if (state.running) toggleBot();
                        log(`&nbsp;&nbsp;↳ Action: Stopped autoplay.`, "strategy");
                        break;
                    case 'changeSeed':
                        const isRisky = ['profit', 'time'].includes(rule.conditionType);
                        await promptForSeedChange(conditionText, isRisky);
                        break;
                    case 'switchOverUnder':
                        document.querySelector(CONFIG.reverseRollButton)?.click();
                        log(`&nbsp;&nbsp;↳ Action: Switched Over/Under.`, "strategy");
                        break;
                    case 'switchStrategy':
                        {
                            const newStrategy = rule.actionValue;
                            const autoSelect = document.getElementById('auto-strategy-select');
                            const semiAutoSelect = document.getElementById('semi-auto-strategy');
                            if (autoSelect && semiAutoSelect && advancedStrategies[newStrategy]) {
                                autoSelect.value = newStrategy;
                                semiAutoSelect.value = newStrategy;
                                log(`&nbsp;&nbsp;↳ Action: Switched strategy to '${newStrategy}'.`, "strategy");
                            } else {
                                log(`&nbsp;&nbsp;↳ Action failed: Could not find strategy '${newStrategy}'.`, "error");
                            }
                            break;
                        }
                    case 'notify':
                        showNotification(rule.actionValue);
                        log(`&nbsp;&nbsp;↳ Action: Sent notification: "${rule.actionValue}"`, "strategy");
                        break;
                }

                if (isBetAction) betAmountModified = true;
                if (isWinChanceAction) winChanceModified = true;
            }
        }
    }

    function checkCondition(rule) {
        switch (rule.conditionType) {
            case 'bets':
                {
                    const value = rule.playConditionValue;
                    const betType = rule.playConditionBetType;
                    const isWin = betType === 'win';
                    const streak = isWin ? state.winStreak : state.lossStreak;

                    switch (rule.playConditionTerm) {
                        case 'every':
                            if (betType === 'bet' && state.betCount > 0 && state.betCount % value === 0) return true;
                            if (betType === 'win' && state.lastBetWasWin && streak > 0 && streak % value === 0) return true;
                            if (betType === 'lose' && !state.lastBetWasWin && streak > 0 && streak % value === 0) return true;
                            break;
                        case 'everyStreakOf':
                            if (betType !== 'bet' && streak > 0 && streak % value === 0) return true;
                            break;
                        case 'firstStreakOf':
                            const flag = `firstStreak-${rule.playConditionBetType}-${rule.playConditionValue}`;
                            if (betType !== 'bet' && streak === value && !state.strategyFlags[flag]) {
                                state.strategyFlags[flag] = true; // Mark as triggered for this session
                                return true;
                            } else if (betType !== 'bet' && streak < value) {
                                state.strategyFlags[flag] = false; // Reset if streak is broken
                            }
                            break;
                        case 'streakGreaterThan':
                            if (betType !== 'bet' && streak > value) return true;
                            break;
                        case 'streakLowerThan':
                            if (betType !== 'bet' && streak < value) return true;
                            break;
                    }
                    break;
                }
            case 'profit':
                if (rule.netGainCondition === 'greater' && state.totalProfit > rule.netGainValue) return true;
                if (rule.netGainCondition === 'less' && state.totalProfit < rule.netGainValue) return true;
                if (rule.netGainCondition === '=' && state.totalProfit.toFixed(8) == rule.netGainValue.toFixed(8)) return true;
                break;
            case 'time':
                {
                    const timeSinceWin = (Date.now() - state.lastWinTimestamp) / 1000;
                    if (rule.timeSinceWinCondition === 'greater' && timeSinceWin > rule.timeSinceWinValue) return true;
                    if (rule.timeSinceWinCondition === 'less' && timeSinceWin < rule.timeSinceWinValue) return true;
                    break;
                }
            case 'pattern':
                {
                    const pattern = rule.patternMatch.toUpperCase();
                    if (state.outcomeHistory.endsWith(pattern)) return true;
                    break;
                }
        }
        return false;
    }


    // --- HELPER & STATE FUNCTIONS ---

    function getBetDelay() {
        const delayValue = String(CONFIG.betDelay).trim();
        const parts = delayValue.split('-').map(p => parseInt(p.trim(), 10));

        if (parts.length === 2) {
            const [min, max] = parts;
            if (!isNaN(min) && !isNaN(max) && min <= max) {
                // Return a random integer between min and max (inclusive)
                return Math.floor(Math.random() * (max - min + 1)) + min;
            }
        } else if (parts.length === 1) {
            const delay = parts[0];
            if (!isNaN(delay)) {
                return delay;
            }
        }

        // Fallback for invalid input
        log(`Invalid betDelay value "${CONFIG.betDelay}", defaulting to 100ms.`, 'error');
        return 100;
    }

    function showNotification(message, type = 'info') {
        const container = document.getElementById('bot-notification-container');
        const notification = document.createElement('div');
        notification.className = 'bot-notification';
        notification.innerHTML = `
            <div class="bot-notification-header">
                <span>${type === 'error' ? 'Error' : 'Bot Notification'}</span>
                <button class="close-btn">&times;</button>
            </div>
            <p>${message}</p>
        `;
        if (type === 'error') {
            notification.style.backgroundColor = 'var(--accent-red)';
        }
        container.appendChild(notification);

        const close = () => {
            notification.classList.add('fade-out');
            setTimeout(() => notification.remove(), 500);
        };

        notification.querySelector('.close-btn').addEventListener('click', close);
        setTimeout(close, 10000); // Auto-dismiss after 10 seconds
    }

    /**
     * A more robust way to simulate a click event on an element.
     * @param {HTMLElement} element The element to click.
     */
    function simulateClick(element) {
        if (!element) return;
        const eventOptions = { bubbles: true, cancelable: true, view: unsafeWindow };
        element.dispatchEvent(new MouseEvent('mousedown', eventOptions));
        element.dispatchEvent(new MouseEvent('mouseup', eventOptions));
        element.dispatchEvent(new MouseEvent('click', eventOptions));
    }

    /**
     * Sets an input element's value in a way that is compatible with frameworks like React.
     * @param {string} selector The CSS selector for the input element.
     * @param {string|number} value The value to set.
     * @returns {boolean} True if the element was found and updated, false otherwise.
     */
    function setUIValue(selector, value) {
        const input = document.querySelector(selector);
        if (input) {
            // Focus the element to simulate user interaction
            input.focus();

            const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
            nativeInputValueSetter.call(input, value.toString());

            // Dispatch events that React (and other frameworks) might listen for
            input.dispatchEvent(new Event('input', { bubbles: true }));
            input.dispatchEvent(new Event('change', { bubbles: true }));

            // Blur the element to complete the "interaction"
            input.blur();
            return true;
        }
        log(`Error: Could not find UI element with selector: ${selector}`, 'error');
        return false;
    }


    function getStakeBetAmount() {
        const amountInput = document.querySelector(CONFIG.amountInput);
        if (amountInput) {
            const amount = parseFloat(amountInput.value);
            return isNaN(amount) ? 0 : amount;
        }
        return 0;
    }

    function updateStatus(text) {
        const el = document.getElementById('bot-status-indicator');
        if (el) el.textContent = `- ${text}`;
    }

    function updateProfitDisplay() {
        const el = document.getElementById('profit-loss-display');
        if (!el) return;

        const profit = state.totalProfit;
        el.textContent = `${profit >= 0 ? '+' : ''}${profit.toFixed(8)}`;
        el.classList.remove('profit', 'loss');
        if (profit > 0) {
            el.classList.add('profit');
        } else if (profit < 0) {
            el.classList.add('loss');
        }
    }

    function resetState() {
        state.betCount = 0;
        state.totalProfit = 0;
        state.winStreak = 0;
        state.lossStreak = 0;
        state.lastBetWasWin = null;
        state.strategyFlags = {};
        state.persistentTriggerStates = {};
        state.lastWinTimestamp = Date.now();
        state.outcomeHistory = '';
        updateProfitDisplay();
        log("State reset for new session.", "system");
    }

    function updateStateFromResult(result) {
        state.betCount++;
        state.totalProfit += result.profit;
        state.lastBetWasWin = result.win;
        if (result.win) {
            state.winStreak++;
            state.lossStreak = 0;
            state.lastWinTimestamp = Date.now();
            state.outcomeHistory += 'W';
        } else {
            state.lossStreak++;
            state.winStreak = 0;
            state.outcomeHistory += 'L';
        }
        if (state.outcomeHistory.length > 20) { // Keep history from growing too large
            state.outcomeHistory = state.outcomeHistory.slice(-20);
        }
        updateProfitDisplay();
    }

    function updateInputDisabledState() {
        const isRunning = state.running;
        document.querySelectorAll('#dice-bot-window .bot-input, #dice-bot-window .bot-btn, #dice-bot-window .config-pick-btn, #dice-bot-window select').forEach(el => {
            if (el.id === 'start-stop-btn') {
                el.disabled = false;
            } else {
                el.disabled = isRunning;
            }
        });
    }

    function updateSettings() {
        state.baseBet = parseFloat(document.getElementById('base-bet').value) || 0.01;
        state.currentBet = state.baseBet;
        state.onWinAction = document.getElementById('on-win-action').value;
        state.onWinIncrease = parseFloat(document.getElementById('on-win-increase').value) || 0;
        state.onLossAction = document.getElementById('on-loss-action').value;
        state.onLossIncrease = parseFloat(document.getElementById('on-loss-increase').value) || 100;

        const minDelay = document.getElementById('config-betDelay-min').value.trim();
        const maxDelay = document.getElementById('config-betDelay-max').value.trim();
        if (minDelay && maxDelay) {
            CONFIG.betDelay = `${minDelay}-${maxDelay}`;
        } else if (minDelay) {
            CONFIG.betDelay = minDelay;
        } else {
            CONFIG.betDelay = '100';
        }

        CONFIG.maxBetAmount = parseFloat(document.getElementById('config-maxBetAmount').value) || 0;
    }

    async function startBot() {
        updateSettings();
        resetState();

        while (state.running) {
            const autoStrategyName = document.getElementById('auto-strategy-select').value;
            const useAdvancedStrategy = autoStrategyName !== 'none' && advancedStrategies[autoStrategyName];

            if (useAdvancedStrategy) {
                if (state.betCount === 0) log(`Starting auto mode with advanced strategy: '${autoStrategyName}'`, "auto");
            } else {
                if (state.betCount === 0) log(`Starting auto mode with On Win/Loss % logic.`, "auto");
            }

            if (CONFIG.maxBetAmount > 0 && state.currentBet > CONFIG.maxBetAmount) {
                log(`SAFETY STOP: Bet amount (${state.currentBet.toFixed(8)}) exceeded max bet (${CONFIG.maxBetAmount}).`, 'error');
                toggleBot();
                break;
            }

            setBetAmount(state.currentBet);
            const result = await placeBetAndGetResult('auto');
            if (result === null) {
                if (state.running) toggleBot();
                break;
            }
            updateStateFromResult(result);

            const currentStrategyName = document.getElementById('auto-strategy-select').value;
            const currentUseAdvanced = currentStrategyName !== 'none' && advancedStrategies[currentStrategyName];

            if (currentUseAdvanced) {
                await executeAdvancedStrategy(advancedStrategies[currentStrategyName], state, state.baseBet);
            } else {
                updateNextBet(result.win);
            }

            await sleep(getBetDelay());
        }
    }

    function setBetAmount(amount) {
        setUIValue(CONFIG.amountInput, amount.toFixed(8));
    }

    function placeBetAndGetResult(betType = 'manual') {
        const amountForProfit = betType === 'auto' ? state.currentBet : semiAutoState.currentBet;
        const winChanceInput = document.querySelector(CONFIG.winChanceInput);
        const winChance = winChanceInput ? parseFloat(winChanceInput.value) : 49.5;

        return new Promise(resolve => {
            const betButton = document.querySelector(CONFIG.betButton);
            if (!betButton || betButton.disabled) {
                updateStatus("ERROR: Bet button not found or disabled!");
                resolve(null);
                return;
            }
            const pastBetsContainer = document.querySelector(CONFIG.pastBetsContainer);
            if (!pastBetsContainer) {
                updateStatus("ERROR: Past bets list not found!");
                resolve(null);
                return;
            }
            const lastBetId = pastBetsContainer.querySelector('[data-last-bet-index="0"]')?.getAttribute('data-past-bet-id');

            // Use the more robust click simulation
            simulateClick(betButton);

            let attempts = 0;
            const pollInterval = setInterval(() => {
                const newBetElement = pastBetsContainer.querySelector('[data-last-bet-index="0"]');
                const newBetId = newBetElement?.getAttribute('data-past-bet-id');
                if (newBetElement && newBetId !== lastBetId) {
                    clearInterval(pollInterval);
                    const isWin = newBetElement.classList.contains(CONFIG.winClass.replace('.', ''));
                    const multiplier = 99 / winChance;
                    const netProfit = isWin ? amountForProfit * (multiplier - 1) : -amountForProfit;
                    log(`Bet #${state.betCount + 1}: ${isWin ? 'WIN' : 'LOSS'}. Profit: ${netProfit.toFixed(8)}`, betType);
                    resolve({
                        win: isWin,
                        profit: netProfit
                    });
                } else if (++attempts >= 75) {
                    clearInterval(pollInterval);
                    updateStatus("ERROR: Bet result timed out!");
                    log("Bet result timed out.", "error");
                    resolve(null);
                }
            }, 200);
        });
    }

    function updateNextBet(isWin) {
        if (isWin) {
            state.currentBet = state.onWinAction === 'reset' ? state.baseBet : state.currentBet * (1 + state.onWinIncrease / 100);
        } else {
            state.currentBet = state.onLossAction === 'reset' ? state.baseBet : state.currentBet * (1 + state.onLossIncrease / 100);
        }
        state.currentBet = Math.max(0.00000001, state.currentBet);
    }

    async function runSemiAutoStep() {
        const stepButton = document.getElementById('semi-auto-step-btn');
        stepButton.disabled = true;

        updateStatus('Manual Step...');
        if (!semiAutoState.isStarted) {
            semiAutoState.isStarted = true;
            resetState();
            const stakeAmount = getStakeBetAmount();
            const botBaseAmountInput = document.getElementById('semi-auto-base-bet');
            let startingBet = parseFloat(botBaseAmountInput.value) || 0.01;

            if (stakeAmount > 0) {
                startingBet = stakeAmount;
                botBaseAmountInput.value = startingBet.toFixed(8);
                log(`Starting manual session with bet amount from Stake UI: ${startingBet.toFixed(8)}`, "manual");
            }
            semiAutoState.currentBet = startingBet;
        }

        setBetAmount(semiAutoState.currentBet);
        const result = await placeBetAndGetResult('manual');
        if (result === null) {
            updateStatus("Error: Couldn't get result.");
            stepButton.disabled = false;
            return;
        }
        updateStateFromResult(result);

        const strategyName = document.getElementById('semi-auto-strategy').value;
        if (strategyName !== 'none' && advancedStrategies[strategyName]) {
            const baseBet = parseFloat(document.getElementById('semi-auto-base-bet').value) || 0.01;
            await executeAdvancedStrategy(advancedStrategies[strategyName], semiAutoState, baseBet);
        }

        setBetAmount(semiAutoState.currentBet);
        updateStatus('Ready for next step.');
        stepButton.disabled = false;
    }

    async function handleManualSeedChange() {
        const btn = document.getElementById('manual-change-seed-btn');
        btn.disabled = true;
        btn.textContent = "Changing...";
        await changeSeedProgrammatically();
        btn.textContent = "Change Seed (API)";
        btn.disabled = false;
    }

    function resetSemiAutoProgression() {
        semiAutoState.isStarted = false;
        const baseBet = parseFloat(document.getElementById('semi-auto-base-bet').value) || 0.01;
        semiAutoState.currentBet = baseBet;
        setBetAmount(baseBet);
        updateStatus('Progression Reset.');
        log("Manual progression reset to base bet.", "manual");
    }

    function saveStrategies() {
        localStorage.setItem('stakeDiceBotStrategies', JSON.stringify(advancedStrategies));
        populateStrategyDropdowns();
    }

    function loadStrategies() {
        const saved = localStorage.getItem('stakeDiceBotStrategies');
        if (saved) {
            try {
                advancedStrategies = JSON.parse(saved);
            } catch (e) {
                console.error("Failed to load strategies:", e);
                advancedStrategies = {};
            }
        }
    }

    function populateStrategyDropdowns() {
        const semiAutoSelect = document.getElementById('semi-auto-strategy');
        const advancedList = document.getElementById('advanced-strategy-list');
        const autoSelect = document.getElementById('auto-strategy-select');

        const selectedSemiAuto = semiAutoSelect.value;
        const selectedAdvanced = advancedList.value;
        const selectedAuto = autoSelect.value;

        advancedList.innerHTML = '';
        while (semiAutoSelect.options.length > 1) semiAutoSelect.remove(1);
        while (autoSelect.options.length > 1) autoSelect.remove(1);

        for (const name in advancedStrategies) {
            advancedList.add(new Option(name, name));
            semiAutoSelect.add(new Option(name, name));
            autoSelect.add(new Option(name, name));
        }

        semiAutoSelect.value = advancedStrategies[selectedSemiAuto] || selectedSemiAuto === 'none' ? selectedSemiAuto : 'none';
        advancedList.value = advancedStrategies[selectedAdvanced] ? selectedAdvanced : '';
        autoSelect.value = advancedStrategies[selectedAuto] || selectedAuto === 'none' ? selectedAuto : 'none';
    }

    function updateSemiAutoDescription() {
        const select = document.getElementById('semi-auto-strategy');
        const desc = document.getElementById('semi-auto-desc');
        const strategyName = select.value;

        if (strategyName === 'none') {
            desc.innerHTML = `<b>Manual Betting:</b> Bet amount is not changed automatically. Use Reset (R) to return to base amount.`;
        } else if (advancedStrategies[strategyName]) {
            desc.textContent = `Using advanced strategy: ${strategyName}`;
        }
    }

    function applyLogFilters() {
        const logContainer = document.getElementById('log-container');
        if (!logContainer) return;
        logContainer.querySelectorAll('p').forEach(entry => {
            const type = entry.dataset.logType;
            if (logFilters[type]) {
                entry.style.display = '';
            } else {
                entry.style.display = 'none';
            }
        });
    }

    function log(message, type = 'system') {
        const logContainer = document.getElementById('log-container');
        if (!logContainer) return;

        const entry = document.createElement('p');
        const timestamp = new Date().toLocaleTimeString();
        entry.innerHTML = `[${timestamp}] ${message}`;
        entry.dataset.logType = type;

        switch (type) {
            case 'manual':
                entry.className = 'log-manual';
                break;
            case 'auto':
                entry.className = 'log-auto';
                break;
            case 'strategy':
                entry.className = 'log-strategy';
                break;
            default:
                break;
        }

        if (!logFilters[type]) {
            entry.style.display = 'none';
        }

        logContainer.appendChild(entry);
        logEntries.push(`[${timestamp}] ${message.replace(/<[^>]*>/g, '')}`);
        logContainer.scrollTop = logContainer.scrollHeight;
    }

    function saveLogToFile() {
        const blob = new Blob([logEntries.join('\n')], {
            type: 'text/plain'
        });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `stake_dice_bot_log_${new Date().toISOString()}.txt`;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
        log("Log saved to file.", "system");
    }

    function exportSelectedStrategy() {
        const selectedName = document.getElementById('advanced-strategy-list').value;
        if (!selectedName || !advancedStrategies[selectedName]) {
            showNotification("Please select a valid strategy to export.", "error");
            return;
        }

        const strategyData = {
            name: selectedName,
            rules: advancedStrategies[selectedName]
        };

        const blob = new Blob([JSON.stringify(strategyData, null, 2)], {
            type: 'application/json'
        });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `${selectedName}.strategy.json`;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
        log(`Strategy '${selectedName}' exported.`, "system");
    }

    function importStrategy() {
        const input = document.createElement('input');
        input.type = 'file';
        input.accept = '.json,.strategy';
        input.onchange = e => {
            const file = e.target.files[0];
            if (!file) return;

            const reader = new FileReader();
            reader.onload = readerEvent => {
                try {
                    const content = readerEvent.target.result;
                    const strategyData = JSON.parse(content);

                    if (!strategyData.name || !Array.isArray(strategyData.rules)) {
                        throw new Error("Invalid strategy file format.");
                    }

                    if (advancedStrategies[strategyData.name]) {
                        if (!confirm(`A strategy named "${strategyData.name}" already exists. Overwrite it?`)) {
                            return;
                        }
                    }

                    advancedStrategies[strategyData.name] = strategyData.rules;
                    saveStrategies();
                    showNotification(`Strategy "${strategyData.name}" imported successfully!`);
                    log(`Strategy '${strategyData.name}' imported.`, "system");
                } catch (err) {
                    showNotification(`Failed to import strategy: ${err.message}`, "error");
                    console.error("Import error:", err);
                }
            };
            reader.readAsText(file);
        };
        input.click();
    }

    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    function makeDraggable(element, handle) {
        let pos1 = 0,
            pos2 = 0,
            pos3 = 0,
            pos4 = 0;
        handle.onmousedown = (e) => {
            // Prevent dragging when clicking on a button inside the header
            if (e.target.closest('.window-btn')) return;
            e.preventDefault();

            // FIX: Prevent stretching when dragging right-aligned elements
            const rect = element.getBoundingClientRect();
            // Unpin from the right and pin to the left at its current position
            // This ensures that subsequent updates to 'left' will move the element instead of stretching it.
            element.style.right = 'auto';
            element.style.left = rect.left + 'px';

            pos3 = e.clientX;
            pos4 = e.clientY;
            document.onmouseup = () => {
                document.onmouseup = null;
                document.onmousemove = null;
            };
            document.onmousemove = (e) => {
                e.preventDefault();
                pos1 = pos3 - e.clientX;
                pos2 = pos4 - e.clientY;
                pos3 = e.clientX;
                pos4 = e.clientY;

                let newTop = element.offsetTop - pos2;
                let newLeft = element.offsetLeft - pos1;

                const elemRect = element.getBoundingClientRect();
                const parentRect = document.body.getBoundingClientRect();

                if (newTop < 0) newTop = 0;
                if (newLeft < 0) newLeft = 0;
                if (newTop + elemRect.height > parentRect.height) newTop = parentRect.height - elemRect.height;
                if (newLeft + elemRect.width > parentRect.width) newLeft = parentRect.width - elemRect.width;

                element.style.top = newTop + "px";
                element.style.left = newLeft + "px";
            };
        };
    }

    function makeResizable(element) {
        const resizers = element.querySelectorAll('.resizer');
        const minimum_size = {
            width: parseFloat(getComputedStyle(element, null).getPropertyValue('min-width')),
            height: parseFloat(getComputedStyle(element, null).getPropertyValue('min-height'))
        };
        let original_width = 0;
        let original_height = 0;
        let original_x = 0;
        let original_y = 0;
        let original_mouse_x = 0;
        let original_mouse_y = 0;

        resizers.forEach(currentResizer => {
            currentResizer.addEventListener('mousedown', (e) => {
                e.preventDefault();
                original_width = parseFloat(getComputedStyle(element, null).getPropertyValue('width').replace('px', ''));
                original_height = parseFloat(getComputedStyle(element, null).getPropertyValue('height').replace('px', ''));
                original_x = element.getBoundingClientRect().left;
                original_y = element.getBoundingClientRect().top;
                original_mouse_x = e.pageX;
                original_mouse_y = e.pageY;

                const mouseMoveHandler = (e) => {
                    const dx = e.pageX - original_mouse_x;
                    const dy = e.pageY - original_mouse_y;

                    if (currentResizer.classList.contains('resizer-b') || currentResizer.classList.contains('resizer-br') || currentResizer.classList.contains('resizer-bl')) {
                        const height = original_height + dy;
                        if (height > minimum_size.height) {
                            element.style.height = height + 'px';
                        }
                    }
                    if (currentResizer.classList.contains('resizer-t') || currentResizer.classList.contains('resizer-tr') || currentResizer.classList.contains('resizer-tl')) {
                        const height = original_height - dy;
                        if (height > minimum_size.height) {
                            element.style.height = height + 'px';
                            element.style.top = original_y + dy + 'px';
                        }
                    }
                    if (currentResizer.classList.contains('resizer-r') || currentResizer.classList.contains('resizer-br') || currentResizer.classList.contains('resizer-tr')) {
                        const width = original_width + dx;
                        if (width > minimum_size.width) {
                            element.style.width = width + 'px';
                        }
                    }
                    if (currentResizer.classList.contains('resizer-l') || currentResizer.classList.contains('resizer-bl') || currentResizer.classList.contains('resizer-tl')) {
                        const width = original_width - dx;
                        if (width > minimum_size.width) {
                            element.style.width = width + 'px';
                            element.style.left = original_x + dx + 'px';
                        }
                    }
                };

                const mouseUpHandler = () => {
                    window.removeEventListener('mousemove', mouseMoveHandler);
                    window.removeEventListener('mouseup', mouseUpHandler);
                };

                window.addEventListener('mousemove', mouseMoveHandler);
                window.addEventListener('mouseup', mouseUpHandler);
            });
        });
    }

    async function promptForSeedChange(conditionText, isRiskyTrigger = false) {
        // All checks removed to allow unrestricted seed changing.
        await changeSeedProgrammatically();
    }

    function handleKeydown(e) {

        const tag = document.activeElement.tagName;
        if (['INPUT', 'SELECT', 'TEXTAREA'].includes(tag) || isPickingElement || document.getElementById('password-prompt-modal').style.display === 'flex') return;

        switch (e.key.toLowerCase()) {
            case 's':
                document.getElementById('start-stop-btn').click();
                break;
            case 'd':
                document.getElementById('semi-auto-step-btn').click();
                break;
            case 'r':
                document.getElementById('semi-auto-reset-btn').click();
                break;
        }
    }

    function applyUiScale(scaleValue = CONFIG.uiScale) {
        const windowEl = document.getElementById('dice-bot-window');
        const minimizedEl = document.getElementById('dice-bot-minimized-bar');
        const scale = scaleValue / 100;
        if (windowEl) {
            windowEl.style.zoom = scale;
        }
        if (minimizedEl) {
            minimizedEl.style.zoom = scale;
        }
    }

    function updateBetDelayConfigUI() {
        const minInput = document.getElementById('config-betDelay-min');
        const maxInput = document.getElementById('config-betDelay-max');
        if (!minInput || !maxInput) return;

        const parts = String(CONFIG.betDelay).split('-').map(p => p.trim());
        minInput.value = parts[0] || '';
        maxInput.value = parts[1] || '';
    }

    // --- ROBUST INITIALIZATION ---
    function waitForGameAndEnable() {
        const interval = setInterval(() => {
            const betButton = document.querySelector(CONFIG.betButton);
            if (betButton) {
                clearInterval(interval);
                updateInputDisabledState();
                updateStatus("Ready");
                log("Game interface found. Bot is active.", "system");
            }
        }, 1000);

        updateInputDisabledState();
    }

    window.addEventListener('load', () => {
        setTimeout(init, 2000);
    });

})();