TCAT - Torn Chain Alert & Tool

Provides chain timer alerts (border/tab flash), Discord webhook notifications, and a Chain Tool for managing target lists with attack navigation.

// ==UserScript==
// @name         TCAT - Torn Chain Alert & Tool
// @namespace    http://torn.com/HeyItzWerty
// @version      1.1
// @description  Provides chain timer alerts (border/tab flash), Discord webhook notifications, and a Chain Tool for managing target lists with attack navigation.
// @author       HeyItzWerty [3626448] (Assisted by Gemini)
// @match        https://www.torn.com/*
// @grant        GM_addStyle
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// @grant        GM_registerMenuCommand
// @grant        GM_openInTab
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// @connect      i.imgur.com
// @connect      discord.com
// @connect      discordapp.com
// @run-at       document-end
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // Prevent running in frames
    if (window.self !== window.top) { return; }
    const SCRIPT_VERSION = GM_info.script.version || '1.1'; // <-- V1.1: Updated version constant
    console.log(`[TCAT] Script execution started (v${SCRIPT_VERSION}).`);

    // --- Constants ---
    const DEFAULT_SETTINGS = {
        fontSize: '13px',
        tabTitleAlert: true, flashTitle: true, solidTabAlert: false,
        preWarningColor4min: '#2196F3', preWarningColor3min: '#4CAF50', preWarningColor2min: '#FFEB3B', preWarningColor1min: '#FF9800', emergencyColor: '#F44336',
        preWarningEmoji4min: '🔵', preWarningEmoji3min: '🟢', preWarningEmoji2min: '🟡', preWarningEmoji1min: '🟠', emergencyEmoji: '🔴',
        checkIntervalChain: 3000,
        emergencyProfiles: ['', '', ''],
        emergencyUrl: '',
        alert4minActionsEnable: false,
        alert3minActionsEnable: false,
        alert2minActionsEnable: false,
        alert1minActionsEnable: false,
        alert30secActionsEnable: false, // <-- V1.1: Default changed to false
        alert4minEnable: false, alert4minBorder: true, alert4minTab: true,
        alert3minEnable: true, alert3minBorder: true, alert3minTab: true,
        alert2minEnable: true, alert2minBorder: true, alert2minTab: true,
        alert1minEnable: true, alert1minBorder: true, alert1minTab: true,
        alert30secEnable: true, alert30secBorder: true, alert30secTab: true,
        enableWebhook: false, webhookUrl: '', webhookMessageFormat: '🚨 **Chain Retaliation!** {yourName} [{yourId}] was **{action}** by [{attackerName}]({profileUrl}) at {timeString}',
        userTornName: '',
        userTornId: '',
        webhookUseUserInfo: false,
        colorScheme: 'dark_orange',
    };
    const SETTINGS_MENU_ID = 'tcat-settings-menu';
    const BORDER_OVERLAY_ID = 'tcat-border-overlay';
    const MENU_CSS_PREFIX = 'tcat-';
    const STATUS_INDICATOR_ID = 'tcat-status-indicator';
    const TAB_PREVIEW_ID = 'tcat-tab-preview';
    const CHAIN_TIMER_SELECTOR = '#sidebar > div:nth-child(1) > div > div.user-information___VBSOk > div > div.toggle-content___BJ9Q9 > div > div:nth-child(5) > a.chain-bar___vjdPL.bar-desktop___F8PEF > div.bar-stats___E_LqA > p.bar-timeleft___B9RGV';
    const CHAIN_LIST_STORAGE_KEY = 'tcatChainLists';
    const CHAIN_TOOL_STATE_KEY = 'tcatChainToolState';
    const CHAIN_TOOL_LIST_SELECT_ID = `${MENU_CSS_PREFIX}chain-list-select`;
    const CHAIN_TOOL_LIST_NAME_INPUT_ID = `${MENU_CSS_PREFIX}chain-list-name`;
    const CHAIN_TOOL_ID_INPUT_ID = `${MENU_CSS_PREFIX}chain-id-input`;
    const CHAIN_TOOL_ID_LIST_DISPLAY_ID = `${MENU_CSS_PREFIX}chain-id-list-display`;
    const CHAIN_TOOL_CURRENT_TARGET_DISPLAY_ID = `${MENU_CSS_PREFIX}chain-current-target`;
    const DEFAULT_CHAIN_LIST_NAME = "Default List";
    const NEW_LOGO_URL = "https://i.imgur.com/JjTydW6.png";
    const FORUM_THREAD_URL = "https://www.torn.com/forums.php#/p=threads&f=67&t=16466635&b=0&a=0";

    const COLOR_SCHEMES = { /* Color schemes defined here */
        dark_orange: { '--tcat-bg-color': '#1e1e1e', '--tcat-bg-secondary-color': '#2a2a2a', '--tcat-content-bg-color': '#222222', '--tcat-text-color': '#dddddd', '--tcat-text-light-color': '#bbbbbb', '--tcat-border-color': '#444444', '--tcat-border-light-color': '#555555', '--tcat-accent-color': '#ff9800', '--tcat-accent-hover-color': '#e68a00', '--tcat-button-bg-color': '#333333', '--tcat-button-text-color': '#dddddd', '--tcat-button-hover-bg-color': '#444444', '--tcat-input-bg-color': '#282828', '--tcat-input-border-color': '#555555', '--tcat-input-text-color': '#dddddd', '--tcat-danger-color': '#f44336', '--tcat-danger-text-color': '#ffffff', '--tcat-danger-hover-color': '#d32f2f', '--tcat-log-bg-color': '#252525', '--tcat-log-header-bg-color': '#303030', '--tcat-log-border-color': '#484848', '--tcat-log-alt-row-color': '#282828', '--tcat-tab-inactive-bg': '#333333', '--tcat-tab-hover-bg': '#444444', },
        dark_blue: { '--tcat-bg-color': '#1a202c', '--tcat-bg-secondary-color': '#2d3748', '--tcat-content-bg-color': '#1c2431', '--tcat-text-color': '#e2e8f0', '--tcat-text-light-color': '#a0aec0', '--tcat-border-color': '#4a5568', '--tcat-border-light-color': '#718096', '--tcat-accent-color': '#4299e1', '--tcat-accent-hover-color': '#2b6cb0', '--tcat-button-bg-color': '#2d3748', '--tcat-button-text-color': '#e2e8f0', '--tcat-button-hover-bg-color': '#4a5568', '--tcat-input-bg-color': '#2d3748', '--tcat-input-border-color': '#718096', '--tcat-input-text-color': '#e2e8f0', '--tcat-danger-color': '#e53e3e', '--tcat-danger-text-color': '#ffffff', '--tcat-danger-hover-color': '#c53030', '--tcat-log-bg-color': '#202835', '--tcat-log-header-bg-color': '#283141', '--tcat-log-border-color': '#404a5c', '--tcat-log-alt-row-color': '#232c3b', '--tcat-tab-inactive-bg': '#2d3748', '--tcat-tab-hover-bg': '#4a5568', },
        dark_red: { '--tcat-bg-color': '#1e1e1e', '--tcat-bg-secondary-color': '#2a2a2a', '--tcat-content-bg-color': '#222222', '--tcat-text-color': '#dddddd', '--tcat-text-light-color': '#bbbbbb', '--tcat-border-color': '#444444', '--tcat-border-light-color': '#555555', '--tcat-accent-color': '#e74c3c', '--tcat-accent-hover-color': '#c0392b', '--tcat-button-bg-color': '#333333', '--tcat-button-text-color': '#dddddd', '--tcat-button-hover-bg-color': '#444444', '--tcat-input-bg-color': '#282828', '--tcat-input-border-color': '#555555', '--tcat-input-text-color': '#dddddd', '--tcat-danger-color': '#f44336', '--tcat-danger-text-color': '#ffffff', '--tcat-danger-hover-color': '#d32f2f', '--tcat-log-bg-color': '#252525', '--tcat-log-header-bg-color': '#303030', '--tcat-log-border-color': '#484848', '--tcat-log-alt-row-color': '#282828', '--tcat-tab-inactive-bg': '#333333', '--tcat-tab-hover-bg': '#444444', },
        dark_green: { '--tcat-bg-color': '#1e1e1e', '--tcat-bg-secondary-color': '#2a2a2a', '--tcat-content-bg-color': '#222222', '--tcat-text-color': '#dddddd', '--tcat-text-light-color': '#bbbbbb', '--tcat-border-color': '#444444', '--tcat-border-light-color': '#555555', '--tcat-accent-color': '#2ecc71', '--tcat-accent-hover-color': '#27ae60', '--tcat-button-bg-color': '#333333', '--tcat-button-text-color': '#dddddd', '--tcat-button-hover-bg-color': '#444444', '--tcat-input-bg-color': '#282828', '--tcat-input-border-color': '#555555', '--tcat-input-text-color': '#dddddd', '--tcat-danger-color': '#e74c3c', '--tcat-danger-text-color': '#ffffff', '--tcat-danger-hover-color': '#c0392b', '--tcat-log-bg-color': '#252525', '--tcat-log-header-bg-color': '#303030', '--tcat-log-border-color': '#484848', '--tcat-log-alt-row-color': '#282828', '--tcat-tab-inactive-bg': '#333333', '--tcat-tab-hover-bg': '#444444', },
    };
    const FONT_SIZE_OPTIONS = [ {value: '11px', text: '11px'}, {value: '12px', text: '12px'}, {value: '13px', text: '13px (Default)'}, {value: '14px', text: '14px'}, {value: '15px', text: '15px'}, {value: '16px', text: '16px'} ];

    // --- Globals ---
    let settings = {}; let settingsMenu = null; let borderOverlay = null;
    let originalTitle = document.title; let tabPreviewInterval = null;
    let chainIntervalId = null;
    let statusIntervalId = null; let isChainCurrentlyActive = false; let alerted4min = false, alerted3min = false, alerted2min = false, alerted1min = false, alerted30sec = false; let currentBorderLevel = null; let isFlashing = false; let solidTitleActive = false;
    let chainLists = {};
    let chainToolState = { currentListName: null, currentIndex: -1, currentListIDs: [] };
    let isTestingAlert = false; // <-- V1.1: Flag to prevent timer loop interference during tests

    // --- Helper Functions ---
    function showUserMessage(title, message, type = 'info') { if (type === 'error' || type === 'success' || type === 'warning') { console.log(`[TCAT ${type.toUpperCase()}]: ${title} - ${message}`); } }
    const safeAppend = (parent, childFactory, factoryArgs = [], elementName = 'element') => { if (!parent || !(parent instanceof Node)) { console.error(`[TCAT v${SCRIPT_VERSION}] Invalid parent for ${elementName}:`, parent); return null; } try { const child = childFactory(...factoryArgs); if (child instanceof Node) { parent.appendChild(child); return child; } else { console.error(`[TCAT v${SCRIPT_VERSION}] ${elementName} factory did not return a Node:`, child); return null; } } catch (e) { console.error(`[TCAT v${SCRIPT_VERSION}] Error creating/appending ${elementName} in parent:`, e); return null; } };
    function parseTimeString(timeString) { if (!timeString) return 0; try { const parts = String(timeString).trim().split(':').map(Number); if (parts.some(isNaN)) return 0; if (parts.length === 2) return (parts[0] * 60) + parts[1]; if (parts.length === 3) return (parts[0] * 3600) + (parts[1] * 60) + parts[2]; return 0; } catch(e) { console.error("Error parsing time string:", timeString, e); return 0; } }
    function openProfiles(profiles) { try { if (!Array.isArray(profiles)) { return; } const validProfiles = profiles.map(p => String(p).trim()).filter(id => id && /^\d+$/.test(id)); if (validProfiles.length === 0) return; validProfiles.forEach(id => { const attackUrl = `https://www.torn.com/loader.php?sid=attack&user2ID=${id}`; try { GM_openInTab(attackUrl, { active: false, setParent: true }); } catch(e){ console.error("Error opening attack loader tab:", id, e); } }); } catch(e){ console.error("Error in openProfiles:", e); } }
    function openUrl(url) { try { const trimmedUrl = String(url || '').trim(); if (trimmedUrl && (trimmedUrl.startsWith('http:') || trimmedUrl.startsWith('https:'))) { GM_openInTab(trimmedUrl, { active: true, setParent: true }); } } catch (e) { console.error("[TCAT] Failed to open URL:", url, e); } }
    function formatTimestamp(unixTimestamp) { if (!unixTimestamp) return '?'; try { return new Date(unixTimestamp * 1000).toLocaleString(); } catch (e) { return '?'; } }
    function isValidPlayerID(id) { return /^\d{1,8}$/.test(String(id).trim()); }

    // --- Chain Tool: Storage Functions ---
    function loadChainLists() { try { const storedLists = GM_getValue(CHAIN_LIST_STORAGE_KEY, null); if (storedLists) { chainLists = JSON.parse(storedLists); if (typeof chainLists !== 'object' || chainLists === null || Array.isArray(chainLists)) { console.warn("[TCAT ChainTool] Invalid format for stored chain lists, resetting."); chainLists = {}; GM_deleteValue(CHAIN_LIST_STORAGE_KEY); } } else { chainLists = {}; } const storedState = GM_getValue(CHAIN_TOOL_STATE_KEY, null); if (storedState) { const parsedState = JSON.parse(storedState); if (parsedState.currentListName && chainLists[parsedState.currentListName]) { chainToolState.currentListName = parsedState.currentListName; chainToolState.currentListIDs = [...chainLists[parsedState.currentListName]]; chainToolState.currentIndex = parsedState.currentIndex ?? -1; if (chainToolState.currentIndex >= chainToolState.currentListIDs.length) { chainToolState.currentIndex = chainToolState.currentListIDs.length - 1; } if (chainToolState.currentIndex < -1) { chainToolState.currentIndex = -1; } } else { resetChainToolState(); } } else { resetChainToolState(); } if (Object.keys(chainLists).length === 0 && !chainLists[DEFAULT_CHAIN_LIST_NAME]) { chainLists[DEFAULT_CHAIN_LIST_NAME] = []; saveChainLists(); chainToolState.currentListName = DEFAULT_CHAIN_LIST_NAME; chainToolState.currentListIDs = []; chainToolState.currentIndex = -1; saveChainToolState(); } else if (!chainToolState.currentListName && chainLists[DEFAULT_CHAIN_LIST_NAME]) { chainToolState.currentListName = DEFAULT_CHAIN_LIST_NAME; chainToolState.currentListIDs = [...chainLists[DEFAULT_CHAIN_LIST_NAME]]; chainToolState.currentIndex = -1; } } catch (e) { console.error("[TCAT ChainTool] Error loading chain lists or state:", e); chainLists = {}; resetChainToolState(); } }
    function saveChainLists() { try { GM_setValue(CHAIN_LIST_STORAGE_KEY, JSON.stringify(chainLists)); } catch (e) { console.error("[TCAT ChainTool] Error saving chain lists:", e); showUserMessage("Save Error", "Failed to save chain lists.", "error"); } }
    function saveChainToolState() { try { const stateToSave = { currentListName: chainToolState.currentListName, currentIndex: chainToolState.currentIndex }; GM_setValue(CHAIN_TOOL_STATE_KEY, JSON.stringify(stateToSave)); } catch (e) { console.error("[TCAT ChainTool] Error saving chain tool state:", e); } }
    function resetChainToolState() { chainToolState.currentListName = null; chainToolState.currentIndex = -1; chainToolState.currentListIDs = []; }

    // --- Color Scheme Function ---
    function applyColorScheme() { const schemeName = settings.colorScheme || 'dark_orange'; const scheme = COLOR_SCHEMES[schemeName] || COLOR_SCHEMES['dark_orange']; if (!settingsMenu) { return; } try { if (settingsMenu.style.setProperty) { for (const [variable, color] of Object.entries(scheme)) { settingsMenu.style.setProperty(variable, color); } } else { console.error("[TCAT] setProperty function not available on settingsMenu style."); } } catch (error) { console.error(`[TCAT v${SCRIPT_VERSION}] Error applying color scheme:`, error); } }

    // --- Settings Logic ---
    function initSettings() { let loadedSettings = {}; try { const savedJSON = GM_getValue('tcatSettings', null); if (savedJSON) { try { const parsed = JSON.parse(savedJSON); if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) { loadedSettings = parsed; } else { console.warn("[TCAT] Invalid settings format found, deleting."); try { GM_deleteValue('tcatSettings'); } catch(e){} } } catch (e) { console.error("[TCAT] Error parsing settings:", e); try { GM_deleteValue('tcatSettings'); } catch(e){} } } settings = { ...DEFAULT_SETTINGS, ...loadedSettings }; settings.webhookUrl = settings.webhookUrl || ''; if (!savedJSON) { saveAllSettings(); } loadChainLists(); } catch (e) { console.error(`[TCAT v${SCRIPT_VERSION}] CRITICAL Error initializing settings:`, e); settings = { ...DEFAULT_SETTINGS }; showUserMessage("TCAT Error", "Failed to initialize settings.", "error"); } applyUISettings(); }
    function saveSetting(key, value) { try { const validKeys = Object.keys(DEFAULT_SETTINGS); if (!validKeys.includes(key)) { console.warn(`[TCAT] Attempting to save unknown or removed setting: ${key}`); return; } settings[key] = value; let needsIntervalRestart = false; let needsAlertReset = false; if (key === 'checkIntervalChain') { needsIntervalRestart = true; } else if (key.startsWith('alert') && (key.endsWith('Enable') || key.endsWith('ActionsEnable'))) { needsAlertReset = true; } else if (key === 'enableWebhook' || key === 'webhookUrl' || key === 'webhookMessageFormat' || key === 'userTornName' || key === 'userTornId' || key === 'webhookUseUserInfo') { /* No immediate action */ } else if (key === 'alert4minBorder' || key === 'alert3minBorder' || key === 'alert2minBorder' || key === 'alert1minBorder' || key === 'alert30secBorder' || key.includes('Color') || key.includes('Emoji') || key === 'flashTitle' || key === 'solidTabAlert') { needsAlertReset = true; } saveAllSettings(); applyUISettings(); if (key === 'colorScheme') { applyColorScheme(); } if(needsAlertReset) { alerted4min = alerted3min = alerted2min = alerted1min = alerted30sec = false; resetSolidTitle(); setBodyBorder(null); } if (needsIntervalRestart) { restartIntervals(); } } catch(e) { console.error(`[TCAT v${SCRIPT_VERSION}] Error saving setting ${key}:`, e); } }
    function saveAllSettings() { try { GM_setValue('tcatSettings', JSON.stringify(settings)); } catch (e) { console.error(`[TCAT v${SCRIPT_VERSION}] Error saving all settings:`, e); } }
    function resetSettings() { try { if (confirm("Reset ALL TCAT settings (Alerts, General, Webhook, About - NOT Chain Lists) to default values?")) { try { GM_deleteValue('tcatSettings'); } catch(e){} settings = { ...DEFAULT_SETTINGS }; alerted4min = alerted3min = alerted2min = alerted1min = alerted30sec = false; resetSolidTitle(); setBodyBorder(null); showUserMessage("Settings Reset", "General/Alert/Webhook settings reset. Chain Lists remain.", "success"); if(settingsMenu) populateMenuTabs(); applyUISettings(); applyColorScheme(); restartIntervals(); } } catch(e) { console.error(`[TCAT v${SCRIPT_VERSION}] Error resetting settings:`, e); showUserMessage("Reset Error", "Failed to reset settings.", "error"); } }
    function applyUISettings() { if (settingsMenu && settingsMenu.style && settings.fontSize) { settingsMenu.style.fontSize = settings.fontSize; } updateStatusIndicator(); }
    function updateStatusIndicator() { if (!settingsMenu) return; const indicator = settingsMenu.querySelector(`#${STATUS_INDICATOR_ID}`); if (indicator) { const statuses = []; let statusText = "Status: "; let statusColor = 'var(--tcat-text-light-color)'; if (chainIntervalId) { if(isChainCurrentlyActive) { statusText += `Active Chain`; statusColor = '#2ECC71'; } else { statusText += `No Chain`; statusColor = '#3498DB'; } statuses.push(`(Scan ${settings.checkIntervalChain / 1000}s)`); } else { statusText += 'Chain Scan OFF'; statusColor = '#F39C12'; } indicator.textContent = `${statusText} ${statuses.join(' ')}`; indicator.style.color = statusColor; indicator.title = statuses.join('\n'); } }

    // --- UI Element Creation Functions ---
    function createSection(titleText, options = {}) { try { const section = document.createElement('div'); section.className = `${MENU_CSS_PREFIX}section`; if(options.id) section.id = options.id; const title = document.createElement('h3'); title.textContent = titleText || 'Section'; title.className = `${MENU_CSS_PREFIX}section-title ${options.titleClass || ''}`; section.appendChild(title); if (options.description) { const desc = document.createElement('p'); desc.className = `${MENU_CSS_PREFIX}section-description`; desc.innerHTML = options.description; section.appendChild(desc); } return section; } catch (e) { console.error(`[TCAT v${SCRIPT_VERSION}] Error creating section:`, e); return document.createElement('div'); } }
    function createCheckbox(settingKey, labelText, parentElement, tooltip = '') { try { const container = document.createElement('div'); container.className = `${MENU_CSS_PREFIX}setting-container ${MENU_CSS_PREFIX}checkbox-container`; if (tooltip) container.title = tooltip; const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.id = `${MENU_CSS_PREFIX}${settingKey}`; checkbox.checked = settings[settingKey] === true; checkbox.onchange = (event) => { saveSetting(settingKey, event.target.checked); }; const label = document.createElement('label'); label.textContent = ` ${labelText}`; label.htmlFor = checkbox.id; container.appendChild(checkbox); container.appendChild(label); parentElement.appendChild(container); return container; } catch (e) { console.error(`[TCAT v${SCRIPT_VERSION}] Error creating checkbox for ${settingKey}:`, e); return null; } }
    function createTextInput(settingKeyOrId, labelText, parentElement, options = {}) { try { const container = document.createElement('div'); container.className = `${MENU_CSS_PREFIX}setting-container ${options.containerClass || ''}`; const label = document.createElement('label'); label.textContent = `${labelText}: `; label.htmlFor = `${MENU_CSS_PREFIX}${settingKeyOrId}`; const input = document.createElement('input'); input.type = options.type || 'text'; input.id = `${MENU_CSS_PREFIX}${settingKeyOrId}`; input.value = options.value ?? (settings[settingKeyOrId] || options.defaultValue || ''); input.placeholder = options.placeholder || ''; input.className = `${MENU_CSS_PREFIX}input`; if(options.type === 'number') { input.min = options.min; input.max = options.max; input.step = options.step || 1; } if(options.inputMode) input.inputMode = options.inputMode; if(options.pattern) input.pattern = options.pattern; if (options.width) input.style.width = options.width; input.autocomplete = options.autocomplete || 'off'; input.disabled = options.disabled ?? false; if(options.isSetting !== false) { input.onchange = (event) => { let valueToSave = event.target.value; if (options.type === 'number') { valueToSave = parseInt(valueToSave, 10); if (isNaN(valueToSave)) valueToSave = options.defaultValue ?? ''; event.target.value = valueToSave; } else if (options.trim === true) { valueToSave = valueToSave.trim(); } if (options.validator && !options.validator(valueToSave)) { showUserMessage("Invalid Input", options.validationMsg || "Invalid format.", "warning"); event.target.value = settings[settingKeyOrId] || options.defaultValue || ''; return; } if (valueToSave === '' && options.defaultValue !== undefined) { valueToSave = options.defaultValue; } saveSetting(settingKeyOrId, valueToSave); }; } else if (options.onchange) { input.onchange = options.onchange; } container.appendChild(label); container.appendChild(input); if (options.unit) { const unitSpan = document.createElement('span'); unitSpan.textContent = ` ${options.unit}`; unitSpan.className = `${MENU_CSS_PREFIX}input-unit`; container.appendChild(unitSpan); } parentElement.appendChild(container); return container; } catch (e) { console.error(`[TCAT v${SCRIPT_VERSION}] Error creating text input for ${settingKeyOrId}:`, e); return null; } }
    function createIntervalInput(settingKey, labelText, parentElement, options = {}) { return createTextInput(settingKey, labelText, parentElement, { ...options, type: 'number', width: options.width || '80px', unit: 'ms', containerClass: `${MENU_CSS_PREFIX}interval-input-container` }); }
    function createWebhookUrlInput(settingKey, labelText, parentElement, options = {}) { return createTextInput(settingKey, labelText, parentElement, { ...options, type: 'password', autocomplete: 'off', width: '95%' }); }
    function createTextArea(settingKey, labelText, parentElement, options = {}) { try { const container = document.createElement('div'); container.className = `${MENU_CSS_PREFIX}setting-container`; container.style.flexDirection = 'column'; container.style.alignItems = 'stretch'; const label = document.createElement('label'); label.textContent = `${labelText}:`; label.htmlFor = `${MENU_CSS_PREFIX}${settingKey}`; label.style.marginBottom = '3px'; const textarea = document.createElement('textarea'); textarea.id = `${MENU_CSS_PREFIX}${settingKey}`; textarea.value = settings[settingKey] || options.defaultValue || ''; textarea.rows = options.rows || 3; textarea.placeholder = options.placeholder || ''; textarea.className = `${MENU_CSS_PREFIX}textarea`; textarea.onchange = (event) => { saveSetting(settingKey, event.target.value); }; container.appendChild(label); container.appendChild(textarea); parentElement.appendChild(container); return container; } catch (e) { console.error(`[TCAT v${SCRIPT_VERSION}] Error creating textarea for ${settingKey}:`, e); return null; } }
    function createColorPicker(settingKey, labelText, parentElement, options = {}) { try { const container = document.createElement('div'); container.className = `${MENU_CSS_PREFIX}setting-container`; container.style.justifyContent = 'space-between'; container.style.width = '150px'; const label = document.createElement('label'); label.textContent = `${labelText}: `; label.htmlFor = `${MENU_CSS_PREFIX}${settingKey}`; const input = document.createElement('input'); input.type = 'color'; input.id = `${MENU_CSS_PREFIX}${settingKey}`; input.value = settings[settingKey] || options.defaultValue || '#000000'; input.className = `${MENU_CSS_PREFIX}input ${MENU_CSS_PREFIX}input-color`; input.onchange = (event) => { saveSetting(settingKey, event.target.value); }; container.appendChild(label); container.appendChild(input); parentElement.appendChild(container); return container; } catch (e) { console.error(`[TCAT v${SCRIPT_VERSION}] Error creating color picker for ${settingKey}:`, e); return null; } }
    function createEmojiInput(settingKey, labelText, parentElement, options = {}) { try { const container = document.createElement('div'); container.className = `${MENU_CSS_PREFIX}setting-container ${MENU_CSS_PREFIX}emoji-input-container`; const label = document.createElement('label'); label.textContent = `${labelText}: `; label.htmlFor = `${MENU_CSS_PREFIX}${settingKey}`; const input = document.createElement('input'); input.type = 'text'; input.id = `${MENU_CSS_PREFIX}${settingKey}`; input.value = settings[settingKey] || options.defaultValue || ''; input.maxLength = 2; input.className = `${MENU_CSS_PREFIX}input ${MENU_CSS_PREFIX}input-emoji`; input.style.width = options.width || '40px'; input.style.textAlign = 'center'; input.onchange = (event) => { let value = event.target.value; if ([...value].length > 2) { value = [...value].slice(0, 2).join(''); event.target.value = value; } saveSetting(settingKey, value); }; container.appendChild(label); container.appendChild(input); parentElement.appendChild(container); return container; } catch(e) { console.error(`[TCAT v${SCRIPT_VERSION}] Error creating emoji input for ${settingKey}:`, e); return null; } }
    function createProfileInput(parentElement) { try { const container = document.createElement('div'); container.className = `${MENU_CSS_PREFIX}setting-container`; container.style.alignItems = 'flex-start'; container.style.flexDirection = 'column'; const label = document.createElement('label'); label.textContent = 'Profile IDs to Open:'; label.style.width = '100%'; label.style.marginBottom = '3px'; container.appendChild(label); const inputWrapper = document.createElement('div'); inputWrapper.style.display = 'flex'; inputWrapper.style.gap = '5px'; for (let i = 0; i < 3; i++) { const input = document.createElement('input'); input.type = 'text'; input.inputMode = 'numeric'; input.pattern = '[0-9]*'; input.id = `${MENU_CSS_PREFIX}emergencyProfiles${i}`; input.placeholder = `ID ${i + 1}`; input.value = (Array.isArray(settings.emergencyProfiles) && settings.emergencyProfiles[i]) ? settings.emergencyProfiles[i] : ''; input.className = `${MENU_CSS_PREFIX}input`; input.style.width="80px"; input.autocomplete = 'off'; input.onchange = (event) => { const value = event.target.value.trim(); if (value === '' || /^\d+$/.test(value)) { if (!Array.isArray(settings.emergencyProfiles)) settings.emergencyProfiles = ['', '', '']; settings.emergencyProfiles[i] = value; saveSetting('emergencyProfiles', [...settings.emergencyProfiles]); } else { event.target.value = (Array.isArray(settings.emergencyProfiles) && settings.emergencyProfiles[i]) ? settings.emergencyProfiles[i] : ''; showUserMessage('Invalid Input', 'Profile ID must be numbers only.', 'warning'); } }; inputWrapper.appendChild(input); } container.appendChild(inputWrapper); parentElement.appendChild(container); return container; } catch (e) { console.error(`[TCAT v${SCRIPT_VERSION}] Error creating profile input:`, e); return null; } }
    function createUrlInput(settingKey, labelText, parentElement, options = {}) { return createTextInput(settingKey, labelText, parentElement, { ...options, type: 'url', placeholder: options.placeholder || 'https://...' }); }
    // Simplified version - just creates the Enable checkbox now
    function createEnableToggle(levelPrefix, labelText, parentElement) {
        try {
            const sectionContainer = document.createElement('div');
            sectionContainer.className = `${MENU_CSS_PREFIX}alert-action-group`;
            // Only create the main Enable toggle here
            createCheckbox(`alert${levelPrefix}Enable`, labelText, sectionContainer, `Enable alerts for ${levelPrefix}`);
            if (parentElement instanceof Node) {
                parentElement.appendChild(sectionContainer);
            } else {
                 console.error(`[TCAT] createEnableToggle: Invalid parentElement provided for level ${levelPrefix}`);
                 return null;
            }
            return sectionContainer; // Return the container holding the Enable toggle
        } catch (e) {
            console.error(`[TCAT v${SCRIPT_VERSION}] Error creating enable toggle for level ${levelPrefix}:`, e);
            return null;
        }
    }
    function createTabPreview(parentElement) { try { const container = document.createElement('div'); container.className = `${MENU_CSS_PREFIX}tab-preview-container`; const label = document.createElement('label'); label.textContent = "Tab Title Preview:"; label.style.display = 'block'; label.style.marginBottom = '3px'; const previewArea = document.createElement('div'); previewArea.id = TAB_PREVIEW_ID; previewArea.className = `${MENU_CSS_PREFIX}tab-preview-area`; previewArea.textContent = `Original: ${originalTitle.substring(0,30)}`; const button = document.createElement('button'); button.textContent = "Preview Title Alert"; button.className = `${MENU_CSS_PREFIX}button`; button.style.marginTop = '5px'; button.onclick = () => runTabPreview(false); container.appendChild(label); container.appendChild(previewArea); container.appendChild(button); parentElement.appendChild(container); return container; } catch(e) { console.error(`[TCAT v${SCRIPT_VERSION}] Error creating tab preview:`, e); return null; } }
    function runTabPreview(silent = false) { try { if (tabPreviewInterval) { clearInterval(tabPreviewInterval); tabPreviewInterval = null; document.title = originalTitle; if (!silent) { const previewArea = document.getElementById(TAB_PREVIEW_ID); if (previewArea) previewArea.textContent = `Preview finished. Original: ${originalTitle.substring(0,30)}`; } return; } if (!silent) { const previewArea = document.getElementById(TAB_PREVIEW_ID); if (previewArea) previewArea.textContent = "Running preview..."; } const useSolid = settings.solidTabAlert; const useFlash = settings.flashTitle; const emojis = [settings.preWarningEmoji4min || '?', settings.preWarningEmoji3min || '?', settings.preWarningEmoji2min || '?', settings.preWarningEmoji1min || '?', settings.emergencyEmoji || '?']; const levels = ['4', '3', '2', '1', '0.5']; let currentLevelIndex = 0; let flashState = false; const flashIntervalMs = 500; const levelChangeMs = 1000; tabPreviewInterval = setInterval(() => { try { const emoji = emojis[currentLevelIndex]; const levelText = levels[currentLevelIndex]; if (useSolid) { document.title = `${emoji} Alert ${levelText}m ${emoji}`; } else if (useFlash) { flashState = !flashState; document.title = flashState ? `${emoji} CHAIN ALERT ${emoji}` : originalTitle; } else { document.title = originalTitle; } if (!useSolid || (useSolid && (Date.now() % levelChangeMs < flashIntervalMs))) { currentLevelIndex = (currentLevelIndex + 1) % emojis.length; } } catch(intervalError) { console.error("Error inside runTabPreview interval:", intervalError); try{clearInterval(tabPreviewInterval); tabPreviewInterval = null; document.title = originalTitle;}catch{} } }, flashIntervalMs); setTimeout(() => { try { if (tabPreviewInterval) { clearInterval(tabPreviewInterval); tabPreviewInterval = null; document.title = originalTitle; if (!silent) { const previewArea = document.getElementById(TAB_PREVIEW_ID); if (previewArea) previewArea.textContent = `Preview finished. Original: ${originalTitle.substring(0,30)}`; } } } catch(timeoutError){ console.error("Error inside runTabPreview timeout:", timeoutError); try{document.title = originalTitle;}catch{} } }, 5000); } catch(e) { console.error("Error starting runTabPreview:", e); } }
    function createDropdownInput(settingKeyOrId, labelText, parentElement, optionsArray, options = {}) { try { const container = document.createElement('div'); container.className = `${MENU_CSS_PREFIX}setting-container`; const label = document.createElement('label'); label.textContent = `${labelText}: `; label.htmlFor = `${MENU_CSS_PREFIX}${settingKeyOrId}`; const select = document.createElement('select'); select.id = `${MENU_CSS_PREFIX}${settingKeyOrId}`; select.className = `${MENU_CSS_PREFIX}select`; if (options.width) select.style.width = options.width; optionsArray.forEach(opt => { const option = document.createElement('option'); option.value = opt.value; option.textContent = opt.text || opt.value; option.disabled = opt.disabled ?? false; if(options.isSetting !== false) { if (settings[settingKeyOrId] === opt.value) { option.selected = true; } } else if (options.selectedValue === opt.value) { option.selected = true; } select.appendChild(option); }); if(options.isSetting !== false) { select.onchange = (event) => { saveSetting(settingKeyOrId, event.target.value); if (settingKeyOrId === 'fontSize' && settingsMenu && settingsMenu.style) { settingsMenu.style.fontSize = event.target.value; } }; } else if (options.onchange) { select.onchange = options.onchange; } container.appendChild(label); container.appendChild(select); parentElement.appendChild(container); return select; } catch (e) { console.error(`[TCAT] Error creating dropdown for ${settingKeyOrId}:`, e); return null; } }
    function createColorSchemeSelector(parentElement) { try { const container = document.createElement('div'); container.className = `${MENU_CSS_PREFIX}setting-container`; const label = document.createElement('label'); label.textContent = 'Color Scheme: '; label.htmlFor = `${MENU_CSS_PREFIX}colorScheme`; const select = document.createElement('select'); select.id = `${MENU_CSS_PREFIX}colorScheme`; select.className = `${MENU_CSS_PREFIX}select`; Object.keys(COLOR_SCHEMES).forEach(schemeName => { const option = document.createElement('option'); option.value = schemeName; option.textContent = schemeName.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase()); if (settings.colorScheme === schemeName) option.selected = true; select.appendChild(option); }); select.onchange = (event) => { saveSetting('colorScheme', event.target.value); applyColorScheme(); }; container.appendChild(label); container.appendChild(select); parentElement.appendChild(container); return container; } catch(e) { console.error(`[TCAT v${SCRIPT_VERSION}] Error creating color scheme selector:`, e); return null; } }
    function createButton(text, parentElement, onClick, options = {}) { try { const button = document.createElement('button'); button.textContent = text; button.className = `${MENU_CSS_PREFIX}button ${options.extraClass || ''}`; button.disabled = options.disabled ?? false; button.onclick = onClick; if (options.style) { Object.assign(button.style, options.style); } if (options.id) { button.id = `${MENU_CSS_PREFIX}${options.id}`; } parentElement.appendChild(button); return button; } catch (e) { console.error(`[TCAT v${SCRIPT_VERSION}] Error creating button:`, e); return null; } }

    // --- Alert Logic Functions ---
    function setBodyBorder(level) {
        try {
            if (!borderOverlay || !document.body.contains(borderOverlay)) {
                borderOverlay = document.getElementById(BORDER_OVERLAY_ID);
                if (!borderOverlay) {
                    borderOverlay = document.createElement('div');
                    borderOverlay.id = BORDER_OVERLAY_ID;
                    document.body.appendChild(borderOverlay);
                }
            }
            if (!borderOverlay) {
                console.error("[TCAT] Failed find/create border overlay.");
                return;
            }
            let borderColor = 'transparent';
            let newBorderLevel = null;
            const levelMap = { 'emerg': settings.emergencyColor, 'warn': settings.preWarningColor1min, 'pre2': settings.preWarningColor2min, 'pre': settings.preWarningColor3min, 'pre4': settings.preWarningColor4min };
            const enabledMap = { 'emerg': settings.alert30secBorder, 'warn': settings.alert1minBorder, 'pre2': settings.alert2minBorder, 'pre': settings.alert3minBorder, 'pre4': settings.alert4minBorder };

            if (level && levelMap[level] && enabledMap[level]) {
                borderColor = levelMap[level];
                newBorderLevel = level;
            }

            // <-- V1.1: Prevent clearing during test alert
            if (borderColor === 'transparent' && isTestingAlert) {
                return; // Don't clear if testing
            }

            if (borderColor !== 'transparent') {
                // if(currentBorderLevel !== newBorderLevel) {} // This check seems redundant?
                borderOverlay.style.borderColor = borderColor;
                borderOverlay.style.display = 'block';
            } else {
                if (currentBorderLevel !== null) {
                    borderOverlay.style.display = 'none';
                    borderOverlay.style.borderColor = 'transparent';
                }
            }
            currentBorderLevel = newBorderLevel;
        } catch(e) {
            console.error(`[TCAT v${SCRIPT_VERSION}] Error in setBodyBorder:`, e);
            if (borderOverlay && borderOverlay.style) {
                try { borderOverlay.style.display = 'none'; } catch(e2){}
            }
            currentBorderLevel = null;
        }
    }
    function flashTitle(level) { try { if (!settings.tabTitleAlert) return; const enabledMap = { 'emerg': settings.alert30secTab, 'warn': settings.alert1minTab, 'pre2': settings.alert2minTab, 'pre': settings.alert3minTab, 'pre4': settings.alert4minTab }; if (!level || !enabledMap[level]) return; if (settings.solidTabAlert) { setSolidTitle(level); return; } if (isFlashing) return; solidTitleActive = false; isFlashing = true; let count = 0; const maxFlashes = 10; const interval = 500; const emojiMap = { 'emerg': settings.emergencyEmoji, 'warn': settings.preWarningEmoji1min, 'pre2': settings.preWarningEmoji2min, 'pre': settings.preWarningEmoji3min, 'pre4': settings.preWarningEmoji4min }; const emoji = emojiMap[level] || '❗'; const flashText = `${emoji} CHAIN ALERT ${emoji}`; const flashInterval = setInterval(() => { try { document.title = (document.title === originalTitle) ? flashText : originalTitle; if (++count >= maxFlashes) { clearInterval(flashInterval); document.title = originalTitle; isFlashing = false; } } catch(e) { console.error("Error in flashTitle interval:", e); try { clearInterval(flashInterval); document.title = originalTitle; } catch(e2){} isFlashing = false; } }, interval); window.addEventListener('beforeunload', () => { if (isFlashing) { try { clearInterval(flashInterval); document.title = originalTitle; } catch(e){} isFlashing=false; } }, { once: true }); } catch(e) { console.error("Error starting flashTitle:", e); isFlashing = false; } }
    function setSolidTitle(level) { try { if (!settings.tabTitleAlert || !settings.solidTabAlert) return; const enabledMap = { 'emerg': settings.alert30secTab, 'warn': settings.alert1minTab, 'pre2': settings.alert2minTab, 'pre': settings.alert3minTab, 'pre4': settings.alert4minTab }; if (!level || !enabledMap[level]) return; const emojiMap = { 'emerg': settings.emergencyEmoji, 'warn': settings.preWarningEmoji1min, 'pre2': settings.preWarningEmoji2min, 'pre': settings.preWarningEmoji3min, 'pre4': settings.preWarningEmoji4min }; const levelTextMap = { 'emerg': '0.5', 'warn': '1', 'pre2': '2', 'pre': '3', 'pre4': '4' }; const emoji = emojiMap[level] || '❗'; const levelText = levelTextMap[level] || '?'; document.title = `${emoji} Alert ${levelText}m ${emoji}`; solidTitleActive = true; isFlashing = false; } catch(e) { console.error("Error in setSolidTitle:", e); } }
    function resetSolidTitle() {
        try {
            // <-- V1.1: Prevent clearing during test alert
            if (isTestingAlert) return;

            if (solidTitleActive) {
                document.title = originalTitle;
                solidTitleActive = false;
            }
        } catch(e) {
            console.error("Error in resetSolidTitle:", e);
        }
    }

    // --- Core Logic: Chain Timer Check ---
    function checkChainTimer() {
        try {
            const timerElement = document.querySelector(CHAIN_TIMER_SELECTOR);
            if (!timerElement) {
                if (isChainCurrentlyActive) {
                    isChainCurrentlyActive = false;
                    // <-- V1.1: Check test flag before clearing visuals
                    if (!isTestingAlert) {
                        setBodyBorder(null);
                        resetSolidTitle();
                    }
                    alerted4min = alerted3min = alerted2min = alerted1min = alerted30sec = false;
                }
                return;
            }

            const chainLinkElement = timerElement.closest('a.chain-bar___vjdPL');
            const isChainCoolingDown = chainLinkElement?.classList.contains('bar-negative___F7k99') ?? true;
            const timeLeftText = timerElement.textContent?.trim();

            if (!timeLeftText || isChainCoolingDown) {
                if (isChainCurrentlyActive) {
                    isChainCurrentlyActive = false;
                     // <-- V1.1: Check test flag before clearing visuals
                    if (!isTestingAlert) {
                        setBodyBorder(null);
                        resetSolidTitle();
                    }
                    alerted4min = alerted3min = alerted2min = alerted1min = alerted30sec = false;
                }
                return;
            }

            if (!isChainCurrentlyActive) {
                isChainCurrentlyActive = true;
                alerted4min = alerted3min = alerted2min = alerted1min = alerted30sec = false; // Reset alerts on new chain start
            }

            const secondsLeft = parseTimeString(timeLeftText);
            let activeLevel = null;

            if (secondsLeft <= 0) {
                if (isChainCurrentlyActive) {
                    isChainCurrentlyActive = false;
                     // <-- V1.1: Check test flag before clearing visuals
                    if (!isTestingAlert) {
                        setBodyBorder(null);
                        resetSolidTitle();
                    }
                    alerted4min = alerted3min = alerted2min = alerted1min = alerted30sec = false;
                }
                return;
            }

            // Check levels from lowest time up
            if (secondsLeft <= 30 && settings.alert30secEnable) {
                activeLevel = 'emerg';
                if (!alerted30sec) {
                    flashTitle('emerg');
                    if (settings.alert30secActionsEnable) {
                        openProfiles(settings.emergencyProfiles);
                        openUrl(settings.emergencyUrl);
                    }
                    alerted30sec = true; alerted1min = true; alerted2min = true; alerted3min = true; alerted4min = true;
                }
            } else if (secondsLeft <= 60 && settings.alert1minEnable) {
                activeLevel = 'warn';
                if (!alerted1min) {
                    flashTitle('warn');
                    if (settings.alert1minActionsEnable) {
                        openProfiles(settings.emergencyProfiles);
                        openUrl(settings.emergencyUrl);
                    }
                    alerted1min = true; alerted2min = true; alerted3min = true; alerted4min = true;
                }
            } else if (secondsLeft <= 120 && settings.alert2minEnable) {
                activeLevel = 'pre2';
                if (!alerted2min) {
                    flashTitle('pre2');
                    if (settings.alert2minActionsEnable) {
                        openProfiles(settings.emergencyProfiles);
                        openUrl(settings.emergencyUrl);
                    }
                    alerted2min = true; alerted3min = true; alerted4min = true;
                }
            } else if (secondsLeft <= 180 && settings.alert3minEnable) {
                activeLevel = 'pre';
                if (!alerted3min) {
                    flashTitle('pre');
                    if (settings.alert3minActionsEnable) {
                        openProfiles(settings.emergencyProfiles);
                        openUrl(settings.emergencyUrl);
                    }
                    alerted3min = true; alerted4min = true;
                }
            } else if (secondsLeft <= 240 && settings.alert4minEnable) {
                activeLevel = 'pre4';
                if (!alerted4min) {
                    flashTitle('pre4');
                    if (settings.alert4minActionsEnable) {
                        openProfiles(settings.emergencyProfiles);
                        openUrl(settings.emergencyUrl);
                    }
                    alerted4min = true;
                }
            }

            // Update border based on the highest active level met
            setBodyBorder(activeLevel);

        } catch (error) {
            console.error(`[TCAT v${SCRIPT_VERSION}] Error in checkChainTimer:`, error);
            if (isChainCurrentlyActive) {
                isChainCurrentlyActive = false;
                // <-- V1.1: Check test flag before clearing visuals
                if (!isTestingAlert) {
                    setBodyBorder(null);
                    resetSolidTitle();
                }
                alerted4min = alerted3min = alerted2min = alerted1min = alerted30sec = false;
            }
        }
    }


    // --- Interval Management ---
    function restartIntervals() { try { if (chainIntervalId) clearInterval(chainIntervalId); chainIntervalId = null; if (statusIntervalId) clearInterval(statusIntervalId); statusIntervalId = null; const chainCheckMs = Math.max(500, settings.checkIntervalChain || 3000); chainIntervalId = setInterval(checkChainTimer, chainCheckMs); statusIntervalId = setInterval(updateStatusIndicator, 30000); checkChainTimer(); updateStatusIndicator(); } catch (error) { console.error(`[TCAT v${SCRIPT_VERSION}] Error restarting intervals:`, error); } }

    // --- Webhook Logic ---
    function sendWebhookNotification(eventData) { if (!settings.enableWebhook || !settings.webhookUrl || !eventData) { return; } let message = settings.webhookMessageFormat || DEFAULT_SETTINGS.webhookMessageFormat; const profileUrl = `https://www.torn.com/profiles.php?XID=${eventData.attackerId || 0}`; const yourProfileUrl = settings.userTornId ? `https://www.torn.com/profiles.php?XID=${settings.userTornId}` : ''; const placeholders = { '{attackerName}': eventData.attackerName || 'Unknown', '{attackerId}': eventData.attackerId || '0', '{action}': eventData.action || 'interacted with', '{timeString}': eventData.timestampText || formatTimestamp(eventData.eventTimestamp) || new Date().toLocaleString(), '{profileUrl}': profileUrl, '{description}': eventData.description ? eventData.description.replace(/<a .*?>|<\/a>/gi, '').replace(/<br\/?>/gi, ' ').replace(/ +/g, ' ').trim() : 'N/A', '{yourName}': settings.userTornName || 'You', '{yourId}': settings.userTornId || '', '{yourProfileUrl}': yourProfileUrl }; for (const [key, value] of Object.entries(placeholders)) { const escapedKey = key.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); message = message.replace(new RegExp(escapedKey, 'g'), String(value)); } const payload = { content: message }; GM_xmlhttpRequest({ method: "POST", url: settings.webhookUrl, headers: { "Content-Type": "application/json" }, data: JSON.stringify(payload), timeout: 10000, onload: function(response) { if (!(response.status >= 200 && response.status < 300)) { console.error(`[TCAT Webhook] Error sending notification: Status ${response.status}`, response.responseText); showUserMessage("Webhook Error", `Failed to send: Status ${response.status}. Check console/URL.`, "error"); } }, onerror: function(response) { console.error("[TCAT Webhook] Request Error:", response); showUserMessage("Webhook Error", "Network error sending webhook. Check console.", "error"); }, ontimeout: function() { console.error("[TCAT Webhook] Request Timeout"); showUserMessage("Webhook Error", "Webhook request timed out.", "warning"); } }); }

    // --- Test Functions ---
    function testChainAlert(level) {
        try {
            const levelSettingMap = { 'emerg': '30sec', 'warn': '1min', 'pre2': '2min', 'pre': '3min', 'pre4': '4min' };
            const settingPrefix = levelSettingMap[level];
            if (!settingPrefix) {
                console.error("[TCAT TEST] Invalid level for testChainAlert:", level);
                return;
            }
            const actionsEnabledKey = `alert${settingPrefix}ActionsEnable`;

            isTestingAlert = true; // <-- V1.1: Set test flag

            setBodyBorder(level); // Apply visuals
            flashTitle(level);

            if (settings[actionsEnabledKey] === true) {
                if (Array.isArray(settings.emergencyProfiles) && settings.emergencyProfiles.some(p => String(p).trim())) {
                    openProfiles(settings.emergencyProfiles);
                }
                if (settings.emergencyUrl) {
                    openUrl(settings.emergencyUrl);
                }
                showUserMessage("Test Alert", `Emergency actions triggered for ${settingPrefix}.`, "info");
            } else {
                showUserMessage("Test Alert", `Visuals triggered for ${settingPrefix}. Actions disabled for this level.`, "info");
            }

            // <-- V1.1: Increased duration to 7 seconds (7000ms)
            setTimeout(() => {
                isTestingAlert = false; // <-- V1.1: Clear test flag *before* resetting
                setBodyBorder(null);
                resetSolidTitle();
            }, 7000); // Test duration extended

        } catch(e){
            console.error("[TCAT TEST] Error in testChainAlert:", e);
            showUserMessage("Test Error", `Failed test: ${level}`, "error");
            isTestingAlert = false; // Ensure flag is cleared on error
        }
    }
    function testRetaliationAlert() { try { if (!settings.enableWebhook || !settings.webhookUrl) { showUserMessage("Webhook Test", "Webhook is disabled or URL is not set in settings.", "info"); return; } const testEvent = { id: 'test-webhook', eventTimestamp: Math.floor(Date.now() / 1000), timestampText: new Date().toLocaleString(), attackerId: '3626448', attackerName: 'WebhookTester', description: 'WebhookTester [123] sent a test message!', type: 'event', action: 'tested' }; sendWebhookNotification(testEvent); showUserMessage("Webhook Test", "Sent test webhook notification. Check Discord.", "success"); } catch(e) { console.error("[TCAT TEST] Error in testRetaliationAlert:", e); showUserMessage("Test Error", "Failed webhook test.", "error"); } }

    // --- Menu Structure and Control ---
    function buildMenuHTML() { return ` <div class="${MENU_CSS_PREFIX}menu-header"> <div class="${MENU_CSS_PREFIX}title-wrapper"> <h2 class="${MENU_CSS_PREFIX}title"> <img src="${NEW_LOGO_URL}" alt="TCAT Logo" class="${MENU_CSS_PREFIX}title-icon"> TCAT Settings </h2> </div> <button class="${MENU_CSS_PREFIX}button-close" title="Close">×</button> </div> <div class="${MENU_CSS_PREFIX}tab-container"> <button class="${MENU_CSS_PREFIX}tab-button active" data-tab-id="general">General</button> <button class="${MENU_CSS_PREFIX}tab-button" data-tab-id="alerts">Alerts</button> <button class="${MENU_CSS_PREFIX}tab-button" data-tab-id="chain-tool">Chain Tool</button> <button class="${MENU_CSS_PREFIX}tab-button" data-tab-id="webhook">Webhook</button> <button class="${MENU_CSS_PREFIX}tab-button" data-tab-id="about">About</button> </div> <div class="${MENU_CSS_PREFIX}content-container"> <div class="${MENU_CSS_PREFIX}tab-content active" id="${MENU_CSS_PREFIX}tab-general"></div> <div class="${MENU_CSS_PREFIX}tab-content" id="${MENU_CSS_PREFIX}tab-alerts"></div> <div class="${MENU_CSS_PREFIX}tab-content" id="${MENU_CSS_PREFIX}tab-chain-tool"></div> <div class="${MENU_CSS_PREFIX}tab-content" id="${MENU_CSS_PREFIX}tab-webhook"></div> <div class="${MENU_CSS_PREFIX}tab-content" id="${MENU_CSS_PREFIX}tab-about"></div> </div> <div class="${MENU_CSS_PREFIX}menu-footer"> <div id="${STATUS_INDICATOR_ID}" class="${MENU_CSS_PREFIX}status-indicator">Status: Initializing...</div> <div class="${MENU_CSS_PREFIX}forum-link-container"> <a href="${FORUM_THREAD_URL}" target="_blank" rel="noopener noreferrer" class="${MENU_CSS_PREFIX}forum-link"> Like the script? Have ideas? Let me know! </a> </div> <span class="${MENU_CSS_PREFIX}version-info">v${SCRIPT_VERSION}</span> </div> `; } // <-- V1.1: Uses SCRIPT_VERSION

    // --- Chain Tool UI Population & Logic --- (largely unchanged)
    function populateChainToolTab(tabElement) { tabElement.innerHTML = ''; const mainContainer = document.createElement('div'); mainContainer.style.display = 'flex'; mainContainer.style.flexDirection = 'column'; mainContainer.style.gap = '0px'; const listMgmtSection = createSection('Chain Lists', {description: 'Load, save, or delete target lists.'}); const listSelectContainer = document.createElement('div'); listSelectContainer.className = `${MENU_CSS_PREFIX}setting-container`; listSelectContainer.style.alignItems = 'center'; const listSelectLabel = document.createElement('label'); listSelectLabel.textContent = 'Select List:'; listSelectLabel.htmlFor = CHAIN_TOOL_LIST_SELECT_ID; listSelectLabel.style.minWidth = '75px'; const listSelect = document.createElement('select'); listSelect.id = CHAIN_TOOL_LIST_SELECT_ID; listSelect.className = `${MENU_CSS_PREFIX}select`; listSelect.style.flexGrow = '1'; listSelect.style.marginRight = '10px'; populateListSelectDropdown(listSelect); listSelectContainer.appendChild(listSelectLabel); listSelectContainer.appendChild(listSelect); listMgmtSection.appendChild(listSelectContainer); const listNameContainer = document.createElement('div'); listNameContainer.className = `${MENU_CSS_PREFIX}setting-container`; createTextInput('chain-list-name', 'List Name', listNameContainer, { isSetting: false, width: '100%', placeholder: 'Enter name for new/saved list', value: chainToolState.currentListName || '', containerClass: `${MENU_CSS_PREFIX}full-width-container` }); listNameContainer.querySelector('label').style.minWidth = '75px'; listMgmtSection.appendChild(listNameContainer); const listButtonsContainer = document.createElement('div'); listButtonsContainer.style.display = 'flex'; listButtonsContainer.style.flexWrap = 'wrap'; listButtonsContainer.style.gap = '5px'; listButtonsContainer.style.marginTop = '10px'; createButton('Load', listButtonsContainer, handleLoadList); createButton('Save', listButtonsContainer, function(){handleSaveList(false)}); createButton('Save As New', listButtonsContainer, handleSaveAsNewList); createButton('Delete', listButtonsContainer, handleDeleteList, {extraClass: `${MENU_CSS_PREFIX}button-danger`}); listMgmtSection.appendChild(listButtonsContainer); mainContainer.appendChild(listMgmtSection); const idMgmtSection = createSection('Manage IDs', {description: 'Add or remove IDs from the current list.'}); const idInputContainer = document.createElement('div'); idInputContainer.className = `${MENU_CSS_PREFIX}setting-container`; idInputContainer.style.justifyContent = 'space-between'; createTextInput('chain-id-input', 'Player ID', idInputContainer, { isSetting: false, type: 'text', inputMode: 'numeric', pattern: '[0-9]*', placeholder: 'Enter ID', width: '120px' }); createButton('Add ID', idInputContainer, handleAddId); idMgmtSection.appendChild(idInputContainer); const idListLabel = document.createElement('label'); idListLabel.textContent = 'IDs in Current List:'; idListLabel.style.display = 'block'; idListLabel.style.marginTop = '10px'; idListLabel.style.marginBottom = '5px'; idMgmtSection.appendChild(idListLabel); const idListDisplay = document.createElement('select'); idListDisplay.id = CHAIN_TOOL_ID_LIST_DISPLAY_ID; idListDisplay.multiple = true; idListDisplay.className = `${MENU_CSS_PREFIX}select`; idListDisplay.style.width = '100%'; idListDisplay.style.minHeight = '150px'; idListDisplay.style.height = '150px'; populateIdListDisplay(idListDisplay); idMgmtSection.appendChild(idListDisplay); createButton('Remove Selected ID(s)', idMgmtSection, handleRemoveId, {style: {marginTop: '5px'}}); mainContainer.appendChild(idMgmtSection); const navSection = createSection('Navigation', {description: 'Cycle through targets in the loaded list.'}); const targetDisplayContainer = document.createElement('div'); targetDisplayContainer.style.marginBottom = '10px'; targetDisplayContainer.style.padding = '10px'; targetDisplayContainer.style.border = `1px solid var(--tcat-border-color)`; targetDisplayContainer.style.backgroundColor = `var(--tcat-input-bg-color)`; targetDisplayContainer.style.textAlign = 'center'; targetDisplayContainer.style.minHeight = '2.5em'; targetDisplayContainer.style.borderRadius = '3px'; const targetLabel = document.createElement('div'); targetLabel.textContent = 'Current Target:'; targetLabel.style.fontWeight = 'bold'; targetLabel.style.color = `var(--tcat-accent-color)`; targetLabel.style.marginBottom = '5px'; const currentTargetDisplay = document.createElement('div'); currentTargetDisplay.id = CHAIN_TOOL_CURRENT_TARGET_DISPLAY_ID; currentTargetDisplay.style.fontSize = '1.1em'; currentTargetDisplay.textContent = getCurrentTargetDisplayValue(); targetDisplayContainer.appendChild(targetLabel); targetDisplayContainer.appendChild(currentTargetDisplay); navSection.appendChild(targetDisplayContainer); const navButtonsContainer = document.createElement('div'); navButtonsContainer.style.display = 'flex'; navButtonsContainer.style.justifyContent = 'space-around'; navButtonsContainer.style.gap = '10px'; createButton('<< Previous Target', navButtonsContainer, handlePreviousTarget, {style: {flex: 1}}); createButton('Next Target >>', navButtonsContainer, handleNextTarget, {style: {flex: 1}}); navSection.appendChild(navButtonsContainer); mainContainer.appendChild(navSection); tabElement.appendChild(mainContainer); }
    function populateListSelectDropdown(selectElement) { selectElement.innerHTML = ''; const createOption = (value, text, disabled = false) => { const option = document.createElement('option'); option.value = value; option.textContent = text; option.disabled = disabled; if (chainToolState.currentListName === value) { option.selected = true; } selectElement.appendChild(option); }; createOption("__NEW__", "--- Create New List ---"); createOption("", "--- Select Saved List ---", true); const listNames = Object.keys(chainLists).sort(); if (listNames.length > 0) { listNames.forEach(name => createOption(name, name)); } else { if (chainLists[DEFAULT_CHAIN_LIST_NAME]) { createOption(DEFAULT_CHAIN_LIST_NAME, DEFAULT_CHAIN_LIST_NAME); } else { createOption("", "No lists saved yet", true); } } if(chainToolState.currentListName && !listNames.includes(chainToolState.currentListName) && chainToolState.currentListName === DEFAULT_CHAIN_LIST_NAME) { createOption(DEFAULT_CHAIN_LIST_NAME, DEFAULT_CHAIN_LIST_NAME); selectElement.value = DEFAULT_CHAIN_LIST_NAME; } else if (chainToolState.currentListName) { selectElement.value = chainToolState.currentListName; } else { selectElement.value = "__NEW__"; } }
    function populateIdListDisplay(displayElement) { displayElement.innerHTML = ''; chainToolState.currentListIDs.forEach((id, index) => { const option = document.createElement('option'); option.value = id; option.textContent = id; if (index === chainToolState.currentIndex) { option.style.backgroundColor = 'var(--tcat-accent-color)'; option.style.color = 'var(--tcat-bg-color)'; option.selected = true; } displayElement.appendChild(option); }); if (chainToolState.currentIndex !== -1 && displayElement.selectedIndex !== chainToolState.currentIndex) { displayElement.selectedIndex = chainToolState.currentIndex; } if (displayElement.selectedIndex !== -1) { displayElement.options[displayElement.selectedIndex]?.scrollIntoView({ block: 'nearest' }); } }
    function getCurrentTargetDisplayValue() { if (chainToolState.currentListName && chainToolState.currentIndex >= 0 && chainToolState.currentIndex < chainToolState.currentListIDs.length) { return chainToolState.currentListIDs[chainToolState.currentIndex]; } else if (chainToolState.currentListName && chainToolState.currentListIDs.length > 0) { return "(Press Next/Prev)"; } else if (chainToolState.currentListName) { return "(List Empty)"; } else { return "(No List Loaded)"; } }
    function updateChainToolUI() { const listSelect = document.getElementById(CHAIN_TOOL_LIST_SELECT_ID); const listNameInput = document.getElementById(CHAIN_TOOL_LIST_NAME_INPUT_ID); const idListDisplay = document.getElementById(CHAIN_TOOL_ID_LIST_DISPLAY_ID); const currentTargetDisplay = document.getElementById(CHAIN_TOOL_CURRENT_TARGET_DISPLAY_ID); if (listSelect) populateListSelectDropdown(listSelect); if (listNameInput) listNameInput.value = chainToolState.currentListName || ''; if (idListDisplay) populateIdListDisplay(idListDisplay); if (currentTargetDisplay) currentTargetDisplay.textContent = getCurrentTargetDisplayValue(); }
    function handleLoadList() { const listSelect = document.getElementById(CHAIN_TOOL_LIST_SELECT_ID); const selectedName = listSelect?.value; if (selectedName && selectedName !== "__NEW__" && chainLists[selectedName]) { chainToolState.currentListName = selectedName; chainToolState.currentListIDs = [...chainLists[selectedName]]; chainToolState.currentIndex = -1; saveChainToolState(); updateChainToolUI(); showUserMessage("List Loaded", `Loaded list: ${selectedName}`, "success"); } else if (selectedName === "__NEW__") { resetChainToolState(); saveChainToolState(); updateChainToolUI(); const listNameInput = document.getElementById(CHAIN_TOOL_LIST_NAME_INPUT_ID); if(listNameInput) listNameInput.focus(); showUserMessage("New List", "Enter a name and add IDs.", "info"); } else { showUserMessage("Load Error", "Please select a valid saved list to load.", "warning"); } }
    function handleSaveList(isSaveAs = false) { const listNameInput = document.getElementById(CHAIN_TOOL_LIST_NAME_INPUT_ID); let listName = listNameInput?.value.trim(); if (!listName) { showUserMessage("Save Error", "Please enter a name for the list.", "warning"); return; } const savingCurrentList = (!isSaveAs && listName === chainToolState.currentListName); const nameExists = chainLists[listName] !== undefined; if (!savingCurrentList && nameExists) { if (!confirm(`A list named "${listName}" already exists. Overwrite it?`)) { return; } } chainLists[listName] = [...chainToolState.currentListIDs]; chainToolState.currentListName = listName; saveChainLists(); saveChainToolState(); updateChainToolUI(); showUserMessage("List Saved", `List "${listName}" saved successfully.`, "success"); }
    function handleSaveAsNewList() { handleSaveList(true); }
    function handleDeleteList() { const listSelect = document.getElementById(CHAIN_TOOL_LIST_SELECT_ID); const selectedName = listSelect?.value; if (!selectedName || selectedName === "__NEW__" || !chainLists[selectedName]) { showUserMessage("Delete Error", "Please select a valid saved list to delete.", "warning"); return; } if (confirm(`Are you sure you want to permanently delete the list "${selectedName}"?`)) { delete chainLists[selectedName]; saveChainLists(); if (chainToolState.currentListName === selectedName) { resetChainToolState(); saveChainToolState(); } updateChainToolUI(); showUserMessage("List Deleted", `List "${selectedName}" deleted.`, "success"); } }
    function handleAddId() { const idInput = document.getElementById(CHAIN_TOOL_ID_INPUT_ID); const idValue = idInput?.value.trim(); if (!chainToolState.currentListName) { showUserMessage("Add ID Error", "Please load or create/name a list first.", "warning"); return; } if (idValue && isValidPlayerID(idValue)) { if (!chainToolState.currentListIDs.includes(idValue)) { chainToolState.currentListIDs.push(idValue); updateChainToolUI(); if (idInput) idInput.value = ''; } else { showUserMessage("Add ID Info", "That ID is already in the list.", "info"); } } else { showUserMessage("Add ID Error", "Please enter a valid numeric player ID (1-8 digits).", "warning"); } }
    function handleRemoveId() { const idListDisplay = document.getElementById(CHAIN_TOOL_ID_LIST_DISPLAY_ID); if (!idListDisplay || idListDisplay.selectedOptions.length === 0) { showUserMessage("Remove ID Error", "Please select one or more IDs from the list to remove.", "warning"); return; } if (!chainToolState.currentListName) { showUserMessage("Remove ID Error", "No list loaded.", "warning"); return; } const idsToRemove = Array.from(idListDisplay.selectedOptions).map(opt => opt.value); const initialLength = chainToolState.currentListIDs.length; chainToolState.currentListIDs = chainToolState.currentListIDs.filter(id => !idsToRemove.includes(id)); if (chainToolState.currentListIDs.length < initialLength) { if (chainToolState.currentIndex >= chainToolState.currentListIDs.length) { chainToolState.currentIndex = chainToolState.currentListIDs.length - 1; } saveChainToolState(); } updateChainToolUI(); }
    function handleNextTarget() { if (!chainToolState.currentListName || chainToolState.currentListIDs.length === 0) { showUserMessage("Navigation Error", "No list loaded or list is empty.", "warning"); return; } chainToolState.currentIndex++; if (chainToolState.currentIndex >= chainToolState.currentListIDs.length) { chainToolState.currentIndex = 0; } saveChainToolState(); updateChainToolUI(); const targetId = chainToolState.currentListIDs[chainToolState.currentIndex]; const attackUrl = `https://www.torn.com/loader.php?sid=attack&user2ID=${targetId}`; try { GM_openInTab(attackUrl, { active: true, setParent: true }); } catch(e){ console.error("Error opening attack loader tab:", targetId, e); showUserMessage("Navigation Error", "Failed to open attack tab.", "error"); } }
    function handlePreviousTarget() { if (!chainToolState.currentListName || chainToolState.currentListIDs.length === 0) { showUserMessage("Navigation Error", "No list loaded or list is empty.", "warning"); return; } chainToolState.currentIndex--; if (chainToolState.currentIndex < 0) { chainToolState.currentIndex = chainToolState.currentListIDs.length - 1; } saveChainToolState(); updateChainToolUI(); const targetId = chainToolState.currentListIDs[chainToolState.currentIndex]; const attackUrl = `https://www.torn.com/loader.php?sid=attack&user2ID=${targetId}`; try { GM_openInTab(attackUrl, { active: true, setParent: true }); } catch(e){ console.error("Error opening attack loader tab:", targetId, e); showUserMessage("Navigation Error", "Failed to open attack tab.", "error"); } }

    // --- Menu Population ---
    function populateMenuTabs() {
        if (!settingsMenu) { console.error("Cannot populate tabs."); return; }
        try {
            // --- General Tab ---
            const generalTab = settingsMenu.querySelector(`#${MENU_CSS_PREFIX}tab-general`);
            if (generalTab) {
                generalTab.innerHTML = '';
                const topSection = createSection('Core Settings');
                createIntervalInput('checkIntervalChain', 'Chain Check Int.', topSection, { defaultValue: DEFAULT_SETTINGS.checkIntervalChain, min: 500, max: 60000 });
                createCheckbox('tabTitleAlert', 'Enable Tab Title Alerts', topSection);
                generalTab.appendChild(topSection);

                const emojiPreviewSection = createSection('Alert Emojis & Tab Preview', { description: 'Customize emojis and test tab title alerts.' });
                const emojiPreviewFlexContainer = document.createElement('div');
                emojiPreviewFlexContainer.style.display = 'flex'; emojiPreviewFlexContainer.style.gap = '30px'; emojiPreviewFlexContainer.style.alignItems = 'flex-start'; emojiPreviewFlexContainer.style.marginBottom = '15px';
                const emojiGridContainer = document.createElement('div');
                emojiGridContainer.style.flex = '1';
                const emojiGrid = document.createElement('div');
                emojiGrid.className = `${MENU_CSS_PREFIX}emoji-grid`;
                createEmojiInput('preWarningEmoji4min', '4min Emoji', emojiGrid); createEmojiInput('preWarningEmoji3min', '3min Emoji', emojiGrid); createEmojiInput('preWarningEmoji2min', '2min Emoji', emojiGrid); createEmojiInput('preWarningEmoji1min', '1min Emoji', emojiGrid); createEmojiInput('emergencyEmoji', '30s Emoji', emojiGrid);
                emojiGridContainer.appendChild(emojiGrid);
                const tipText = document.createElement('p'); tipText.className = `${MENU_CSS_PREFIX}tip-text`; tipText.innerHTML = `Tip: Copy emojis from <a href="https://getemoji.com/" target="_blank" rel="noopener noreferrer">GetEmoji.com</a>`; emojiGridContainer.appendChild(tipText);
                emojiPreviewFlexContainer.appendChild(emojiGridContainer);
                const previewElementsContainer = document.createElement('div'); previewElementsContainer.style.flex = '1'; createTabPreview(previewElementsContainer);
                emojiPreviewFlexContainer.appendChild(previewElementsContainer);
                emojiPreviewSection.appendChild(emojiPreviewFlexContainer);
                createCheckbox('flashTitle', 'Use Flashing Title Alert', emojiPreviewSection); createCheckbox('solidTabAlert', 'Use Solid Title Alert (Overrides Flashing)', emojiPreviewSection);
                generalTab.appendChild(emojiPreviewSection);

                const borderSection = createSection('Border Colors', {description: 'Colors the browser window border overlay will flash.'});
                const borderGrid = document.createElement('div'); borderGrid.className = `${MENU_CSS_PREFIX}color-picker-grid`;
                createColorPicker('preWarningColor4min', '4min Border', borderGrid); createColorPicker('preWarningColor3min', '3min Border', borderGrid); createColorPicker('preWarningColor2min', '2min Border', borderGrid); createColorPicker('preWarningColor1min', '1min Border', borderGrid); createColorPicker('emergencyColor', '30s Border', borderGrid);
                borderSection.appendChild(borderGrid);
                generalTab.appendChild(borderSection);
            } else { console.error("General tab not found!"); }

            // --- Alerts Tab ---
            const alertsTab = settingsMenu.querySelector(`#${MENU_CSS_PREFIX}tab-alerts`);
            if (alertsTab) {
                alertsTab.innerHTML = '';
                const levelsSection = createSection('Alert Levels & Actions', { description: 'Configure which alerts are active and how they behave.'});
                alertsTab.appendChild(levelsSection);

                const alertLevels = [
                    { prefix: '4min', label: '4 Min Warning' },
                    { prefix: '3min', label: '3 Min Warning' },
                    { prefix: '2min', label: '2 Min Warning' },
                    { prefix: '1min', label: '1 Min Warning' },
                    { prefix: '30sec', label: '30 Sec Warning' }
                ];

                alertLevels.forEach(level => {
                    try {
                        const levelContainer = document.createElement('div');
                        levelContainer.className = `${MENU_CSS_PREFIX}level-block`;

                        // Create main Enable toggle first
                        const enableContainer = createEnableToggle(level.prefix, level.label, levelContainer);

                        // Create container for Border/Tab/Action toggles (indented)
                        const togglesContainer = document.createElement('div');
                        togglesContainer.className = `${MENU_CSS_PREFIX}alert-action-toggles`;
                        togglesContainer.style.marginLeft="25px"; // Keep indentation
                        togglesContainer.style.display = 'flex';
                        togglesContainer.style.flexDirection = 'column'; // Stack vertically
                        togglesContainer.style.gap = '2px'; // Reduce gap

                        // Add Border toggle
                        createCheckbox(`alert${level.prefix}Border`, 'Border', togglesContainer, `Enable Border at ${level.label}`);
                        // Add Tab toggle
                        createCheckbox(`alert${level.prefix}Tab`, 'Tab', togglesContainer, `Enable Tab Title alert at ${level.label}`);
                        // Add Enable Actions toggle
                        // <-- V1.1: Changed label text
                        createCheckbox(`alert${level.prefix}ActionsEnable`, 'Emergency Actions', togglesContainer, `Trigger profile/URL opening actions defined below at ${level.label}`);

                        // Append the toggles container to the main enable container
                        if (enableContainer) {
                             enableContainer.appendChild(togglesContainer);
                        } else {
                             // Fallback if createEnableToggle failed
                             levelContainer.appendChild(togglesContainer);
                        }

                        levelsSection.appendChild(levelContainer);
                    } catch(e) {
                         console.error(`[TCAT] Error creating UI block for level ${level.prefix}:`, e);
                         const errorP = document.createElement('p');
                         errorP.style.color = 'red';
                         errorP.textContent = `Error loading UI for ${level.label}. Check console.`;
                         levelsSection.appendChild(errorP);
                    }
                });


                // Add the section for configuring *what* the emergency actions open
                // <-- V1.1: Changed section title
                const emergencyActionsSection = createSection('Emergency Actions', {
                    titleClass: `${MENU_CSS_PREFIX}section-title-large`,
                    description: 'Profiles and URL to open when triggered by any interval with "Emergency Actions" checked above.'
                });
                createProfileInput(emergencyActionsSection);
                createUrlInput('emergencyUrl', 'Emergency URL', emergencyActionsSection, {width: '95%'});
                alertsTab.appendChild(emergencyActionsSection);


                const testSection = createSection('Test Chain Alerts', {
                     titleClass: `${MENU_CSS_PREFIX}section-title-large`,
                     // <-- V1.1: Updated test duration in description
                     description: 'Manually trigger alert visuals (border/tab) and actions (profiles/URL) if enabled for the level. Tests last ~7 seconds.'
                });
                const testButtonContainer = document.createElement('div');
                testButtonContainer.className = `${MENU_CSS_PREFIX}test-button-container`;
                const createTestButton = (text, level) => { createButton(text, testButtonContainer, function() { testChainAlert(level); }); };
                createTestButton('Test 4m Alert', 'pre4'); createTestButton('Test 3m Alert', 'pre'); createTestButton('Test 2m Alert', 'pre2'); createTestButton('Test 1m Alert', 'warn'); createTestButton('Test 30s Alert', 'emerg');
                testSection.appendChild(testButtonContainer);
                alertsTab.appendChild(testSection);

            } else { console.error("Alerts tab not found!"); }

            // --- Chain Tool Tab ---
            const chainToolTab = settingsMenu.querySelector(`#${MENU_CSS_PREFIX}tab-chain-tool`);
            if (chainToolTab) { populateChainToolTab(chainToolTab); } else { console.error("Chain Tool tab not found!"); }

            // --- Webhook Tab ---
            const webhookTab = settingsMenu.querySelector(`#${MENU_CSS_PREFIX}tab-webhook`);
            if (webhookTab) {
                webhookTab.innerHTML = '';
                const webhookSection = createSection('Discord Webhook', { description: 'Send a message to Discord using the Test button below. Enter your Torn Info for placeholders.' });
                webhookTab.appendChild(webhookSection);
                createCheckbox('enableWebhook', 'Enable Discord Webhook Notifications', webhookSection);
                createWebhookUrlInput('webhookUrl', 'Webhook URL', webhookSection, { placeholder: 'Enter Discord Webhook URL' });
                const userInfoContainer = document.createElement('div'); userInfoContainer.className = `${MENU_CSS_PREFIX}setting-container`; userInfoContainer.style.display = 'flex'; userInfoContainer.style.alignItems = 'baseline'; userInfoContainer.style.gap = '5px';
                const nameInputContainer = createTextInput('userTornName', 'Your Torn Info', userInfoContainer, { placeholder: 'Name', width: '180px', containerClass: `${MENU_CSS_PREFIX}inline-input-group` });
                userInfoContainer.removeChild(nameInputContainer); userInfoContainer.appendChild(nameInputContainer.querySelector('label')); userInfoContainer.appendChild(nameInputContainer.querySelector('input'));
                const hashSpan = document.createElement('span'); hashSpan.textContent = '#'; hashSpan.style.margin = '0 3px'; userInfoContainer.appendChild(hashSpan);
                const idInput = document.createElement('input'); idInput.type = 'text'; idInput.inputMode = 'numeric'; idInput.pattern = '[0-9]*'; idInput.id = `${MENU_CSS_PREFIX}userTornId`; idInput.value = settings.userTornId || ''; idInput.placeholder = 'ID'; idInput.className = `${MENU_CSS_PREFIX}input`; idInput.style.width = '100px'; idInput.onchange = (event) => { saveSetting('userTornId', event.target.value.trim()); }; userInfoContainer.appendChild(idInput);
                webhookSection.appendChild(userInfoContainer);
                createTextArea('webhookMessageFormat', 'Webhook Message Format', webhookSection, { defaultValue: DEFAULT_SETTINGS.webhookMessageFormat, rows: 4 });
                const formatHelp = document.createElement('p'); formatHelp.innerHTML = `Available Placeholders: <code>{attackerName}</code>, <code>{attackerId}</code>, <code>{action}</code>, <code>{timeString}</code>, <code>{profileUrl}</code> (attacker), <code>{description}</code>, <code>{yourName}</code>, <code>{yourId}</code>, <code>{yourProfileUrl}</code>.`; formatHelp.className = `${MENU_CSS_PREFIX}tip-text`; webhookSection.appendChild(formatHelp);
                createCheckbox('webhookUseUserInfo',"Use My Info Placeholders ({yourName}, etc.)", webhookSection, "Indicates if you intend to use your info placeholders in the message format (requires Name/ID above).");
                const testWebhookBtnContainer = document.createElement('div'); testWebhookBtnContainer.style.marginTop = '10px'; createButton('Test Webhook', testWebhookBtnContainer, testRetaliationAlert, {disabled: false}); webhookSection.appendChild(testWebhookBtnContainer);
            } else { console.error("Webhook tab not found!"); }

            // --- About Tab ---
            const aboutTab = settingsMenu.querySelector(`#${MENU_CSS_PREFIX}tab-about`);
            if (aboutTab) {
                aboutTab.innerHTML = '';
                const aboutSection = document.createElement('div'); aboutSection.style.textAlign = 'center'; aboutSection.style.marginBottom = '15px';
                const title = document.createElement('h2'); title.textContent = "About TCAT"; title.className = `${MENU_CSS_PREFIX}section-title-large`; aboutSection.appendChild(title);
                const imgContainer = document.createElement('div'); imgContainer.className = `${MENU_CSS_PREFIX}about-profile-pic-container`; const img = document.createElement('img'); img.src = 'https://profileimages.torn.com/7f15b5d8-872c-44c4-8e27-612f90525fd8-3626448.png'; img.alt = 'Profile Image'; img.className = `${MENU_CSS_PREFIX}about-profile-pic`; imgContainer.appendChild(img); aboutSection.appendChild(imgContainer);
                const userLink = document.createElement('p'); userLink.className = `${MENU_CSS_PREFIX}about-centered-text`; userLink.innerHTML = `<a href="https://www.torn.com/profiles.php?XID=3626448" target="_blank" rel="noopener noreferrer">HeyItzWerty [3626448]</a>`; aboutSection.appendChild(userLink);
                const scriptInfo = document.createElement('p'); scriptInfo.className = `${MENU_CSS_PREFIX}about-centered-text ${MENU_CSS_PREFIX}about-script-info`; scriptInfo.innerHTML = `Torn Chain Alert & Tools v${SCRIPT_VERSION}<br>Provides chain alerts & Chain Tool for list management.`; aboutSection.appendChild(scriptInfo); // <-- V1.1: Uses SCRIPT_VERSION
                const devInfo = document.createElement('p'); devInfo.className = `${MENU_CSS_PREFIX}about-centered-text ${MENU_CSS_PREFIX}about-dev-info`; devInfo.textContent = `Thought of, created and tested during a 2k+ chain over a single night of chain watching.`; aboutSection.appendChild(devInfo);
                aboutTab.appendChild(aboutSection);
                const appearanceSection = createSection('Layout & Appearance', { titleClass: `${MENU_CSS_PREFIX}section-title-large`, description: 'Adjust visual elements of the menu.'});
                createDropdownInput('fontSize', 'Menu Font Size', appearanceSection, FONT_SIZE_OPTIONS, {width: '150px'}); createColorSchemeSelector(appearanceSection);
                aboutTab.appendChild(appearanceSection);
                const resetSection = createSection('Reset General Settings', { description: 'Reset alert/general/webhook/appearance settings to defaults. Chain Lists will NOT be affected.' });
                const resetBtnContainer = document.createElement('div'); resetBtnContainer.style.textAlign = 'center'; resetBtnContainer.style.marginTop = '10px'; createButton("Reset TCAT Options", resetBtnContainer, resetSettings, {extraClass: `${MENU_CSS_PREFIX}button-danger`}); resetSection.appendChild(resetBtnContainer); aboutTab.appendChild(resetSection);
            } else { console.error(`[TCAT v${SCRIPT_VERSION}] About tab not found!`); }

        } catch(e) { console.error(`[TCAT v${SCRIPT_VERSION}] Error populating tabs:`, e); const contentArea = settingsMenu.querySelector(`.${MENU_CSS_PREFIX}content-container`); if(contentArea) contentArea.innerHTML = "<p style='color: red;'>Error loading UI.</p>"; }
    }

    function createMenuIfNotExists() { if (settingsMenu && document.body.contains(settingsMenu)) { return settingsMenu; } try { settingsMenu = document.createElement('div'); settingsMenu.id = SETTINGS_MENU_ID; settingsMenu.style.display = 'none'; if (settings.fontSize) settingsMenu.style.fontSize = settings.fontSize; settingsMenu.innerHTML = buildMenuHTML(); document.body.appendChild(settingsMenu); populateMenuTabs(); applyColorScheme(); const closeButton = settingsMenu.querySelector(`.${MENU_CSS_PREFIX}button-close`); if (closeButton) { closeButton.onclick = toggleMenu; } const tabButtons = settingsMenu.querySelectorAll(`.${MENU_CSS_PREFIX}tab-button`); tabButtons.forEach(button => { button.onclick = (e) => { const tabId = e.target.dataset.tabId; if (!tabId) return; settingsMenu.querySelectorAll(`.${MENU_CSS_PREFIX}tab-button`).forEach(btn => btn.classList.remove('active')); settingsMenu.querySelectorAll(`.${MENU_CSS_PREFIX}tab-content`).forEach(content => content.classList.remove('active')); e.target.classList.add('active'); const targetContent = settingsMenu.querySelector(`#${MENU_CSS_PREFIX}tab-${tabId}`); if (targetContent) targetContent.classList.add('active'); if (tabId === 'chain-tool') { updateChainToolUI(); } }; }); const contentContainer = settingsMenu.querySelector(`.${MENU_CSS_PREFIX}content-container`); if (contentContainer) { contentContainer.addEventListener('wheel', function(event) { const el = event.currentTarget; const isScrollable = el.scrollHeight > el.clientHeight; const isScrollingUp = event.deltaY < 0; const isScrollingDown = event.deltaY > 0; if (isScrollable) { if (isScrollingUp && el.scrollTop === 0) { return; } if (isScrollingDown && el.scrollTop + el.clientHeight >= el.scrollHeight -1 ) { return; } event.stopPropagation(); } }, { passive: false }); } return settingsMenu; } catch (error) { console.error(`[TCAT v${SCRIPT_VERSION}] CRITICAL error createMenu:`, error); showUserMessage("TCAT Error", "Failed create menu.", "error"); if (settingsMenu && settingsMenu.parentNode) settingsMenu.remove(); settingsMenu = null; return null; } }
    function toggleMenu() { try { if (!createMenuIfNotExists()) { return; } const currentDisplay = settingsMenu.style.display; const isHidden = !currentDisplay || currentDisplay === 'none'; settingsMenu.style.display = isHidden ? 'flex' : 'none'; if (isHidden) { applyUISettings(); applyColorScheme(); updateChainToolUI(); updateStatusIndicator(); } } catch (error) { console.error(`[TCAT v${SCRIPT_VERSION}] Error toggling menu:`, error); } }

    // --- Menu Styles ---
    function addMenuStyles() { try { const css = ` /* --- Border Overlay --- */ #${BORDER_OVERLAY_ID} { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; box-sizing: border-box; border: 5px solid transparent; z-index: 2147483646; pointer-events: none; display: none; } /* --- Main Menu Container --- */ #${SETTINGS_MENU_ID} { display: none; position: fixed !important; top: 50% !important; left: 50% !important; transform: translate(-50%, -50%) !important; width: 650px !important; max-width: 95% !important; height: 550px !important; max-height: 90vh !important; background-color: var(--tcat-bg-color) !important; border: 1px solid var(--tcat-border-color) !important; z-index: 2147483647 !important; box-shadow: 4px 4px 12px rgba(0,0,0,0.3) !important; color: var(--tcat-text-color) !important; font-size: 13px; flex-direction: column !important; overflow: hidden; border-radius: 5px; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}menu-header { display: flex; justify-content: space-between; align-items: center; padding: 10px 15px; border-bottom: 1px solid var(--tcat-border-light-color); background-color: var(--tcat-bg-secondary-color); flex-shrink: 0; border-radius: 5px 5px 0 0; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}title-wrapper { flex-grow: 1; text-align: center; margin-left: 30px; /* Space for close button */ } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}title { margin: 0; font-size: 1.3em; font-weight: bold; display: inline-flex; align-items: center; gap: 8px; color: var(--tcat-text-color); } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}title-icon { width: 22px; height: 22px; vertical-align: middle; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}button-close { background: none; border: none; font-size: 1.8em; font-weight: bold; color: var(--tcat-text-light-color); cursor: pointer; padding: 0 5px; line-height: 1; flex-shrink: 0; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}button-close:hover { color: var(--tcat-text-color); } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}tab-container { padding: 5px 5px 0px 5px; border-bottom: 1px solid var(--tcat-border-light-color); background-color: var(--tcat-bg-secondary-color); flex-shrink: 0; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}tab-button { padding: 6px 10px; margin: 0 1px; border: 1px solid var(--tcat-border-light-color); border-bottom: none; border-radius: 4px 4px 0 0; cursor: pointer; background-color: var(--tcat-tab-inactive-bg); color: var(--tcat-text-light-color); display: inline-block; position: relative; bottom: -1px; font-size: 0.95em; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}tab-button.active { background-color: var(--tcat-content-bg-color); border-color: var(--tcat-border-light-color); border-bottom-color: var(--tcat-content-bg-color); font-weight: 600; z-index: 1; color: var(--tcat-accent-color); } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}tab-button:hover:not(.active) { background-color: var(--tcat-tab-hover-bg); color: var(--tcat-text-color); } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}content-container { padding: 15px 20px; flex-grow: 1; overflow-y: auto; background-color: var(--tcat-content-bg-color); color: var(--tcat-text-color); } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}tab-content { display: none; animation: fadeIn 0.3s ease-in-out; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}tab-content.active { display: block; } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}menu-footer { padding: 8px 15px; background-color: var(--tcat-bg-secondary-color); font-size: 0.9em; color: var(--tcat-text-light-color); display: flex; justify-content: space-between; align-items: center; flex-shrink: 0; border-top: 1px solid var(--tcat-border-color); border-radius: 0 0 5px 5px;} #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}status-indicator { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 40%; /* Adjust if needed */ font-weight: bold; flex-shrink: 0; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}version-info { font-style: italic; flex-shrink: 0; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}forum-link-container { flex-grow: 1; text-align: center; margin: 0 10px; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}forum-link { color: var(--tcat-accent-color); text-decoration: none; font-size: 0.9em; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}forum-link:hover { text-decoration: underline; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}section { margin-bottom: 15px; padding-bottom: 15px; border-bottom: 1px dashed var(--tcat-border-light-color); } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}section:last-child { border-bottom: none; margin-bottom: 0;} #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}section-title { margin-top: 0; margin-bottom: 8px; color: var(--tcat-accent-color); font-size: 1.15em; border-bottom: 1px solid var(--tcat-border-color); padding-bottom: 5px; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}section-description { font-size: 0.9em; color: var(--tcat-text-light-color); margin-top: -5px; margin-bottom: 10px; padding-left: 5px; border-left: 3px solid var(--tcat-accent-color); opacity: 0.8; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}setting-container { margin-bottom: 8px; padding: 2px 0; display: flex; align-items: center; flex-wrap: wrap; gap: 5px 10px; } #${SETTINGS_MENU_ID} label { cursor: pointer; margin-right: 5px; color: var(--tcat-text-color); flex-shrink: 0; } #${SETTINGS_MENU_ID} input[type="checkbox"] { accent-color: var(--tcat-accent-color); vertical-align: middle; width: 16px; height: 16px; } #${SETTINGS_MENU_ID} input[type="checkbox"] + label { margin-right: 15px; vertical-align: middle; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}input, #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}textarea, #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}select { padding: 5px 8px; border: 1px solid var(--tcat-input-border-color); border-radius: 3px; background-color: var(--tcat-input-bg-color); color: var(--tcat-input-text-color); font-size: 1em; box-sizing: border-box; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}input:focus, #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}textarea:focus, #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}select:focus { border-color: var(--tcat-accent-color); box-shadow: 0 0 3px var(--tcat-accent-color); outline: none; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}textarea { width: 100%; max-width: 100%; resize: vertical; display: block; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}input-color { padding: 1px 2px; height: 28px; width: 45px; vertical-align: middle; border: 1px solid var(--tcat-input-border-color); cursor: pointer; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}input-emoji { width: 40px; text-align: center; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}select { cursor: pointer; background-color: var(--tcat-input-bg-color); color: var(--tcat-input-text-color); border: 1px solid var(--tcat-input-border-color); padding: 4px; border-radius: 3px;} #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}button { background-color: var(--tcat-button-bg-color); border: 1px solid var(--tcat-border-light-color); color: var(--tcat-button-text-color); padding: 6px 12px; border-radius: 3px; cursor: pointer; margin: 0 5px 5px 0; transition: background-color 0.2s ease; font-weight: 500; text-shadow: 1px 1px 1px rgba(0,0,0,0.1); box-shadow: inset 0 -2px 1px rgba(0,0,0,0.1); } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}button:hover { background-color: var(--tcat-button-hover-bg-color); border-color: var(--tcat-border-color); } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}button:active { box-shadow: inset 0 1px 1px rgba(0,0,0,0.2); transform: translateY(1px); } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}button-danger { background-color: var(--tcat-danger-color); border-color: var(--tcat-danger-hover-color); color: var(--tcat-danger-text-color); font-weight: bold; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}button-danger:hover { background-color: var(--tcat-danger-hover-color); border-color: var(--tcat-danger-color); } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}button:disabled { cursor: not-allowed; opacity: 0.6; background-color: var(--tcat-button-bg-color) !important; border-color: var(--tcat-border-light-color) !important; color: var(--tcat-text-light-color) !important; box-shadow: none; text-shadow: none; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}tab-preview-area { min-height:2em; border:1px dashed var(--tcat-border-color); padding:5px; margin:5px 0; background-color:var(--tcat-input-bg-color); font-style:italic; color:var(--tcat-text-light-color); } #${SETTINGS_MENU_ID} code { background-color: var(--tcat-bg-secondary-color); padding: 1px 3px; border-radius: 3px; font-family: monospace; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}tip-text { font-size: 0.9em; margin-top: 10px; color: var(--tcat-text-light-color); line-height: 1.3; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}tip-text a { color: var(--tcat-accent-color); } /* Layout Specific CSS */ #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}interval-input-container { justify-content: flex-start; width: auto; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}interval-input-container input { width: 70px !important; margin-right: 3px; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}input-unit { color: var(--tcat-text-light-color); margin-left: 2px; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}section-title-large { font-size: 1.3em !important; text-align: center; border-bottom: 1px solid var(--tcat-accent-color) !important; margin-top: 25px !important; margin-bottom: 15px !important; color: var(--tcat-accent-color) !important; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}alert-action-toggles { /* Styles for Border/Tab/Action toggles container */ /* Using flex-direction column now */ } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}level-block { margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px solid var(--tcat-border-light-color); } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}level-block:last-of-type { border-bottom: none; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}checkbox-container { margin-bottom: 2px !important; /* Reduce spacing */ } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}full-width-container input { width: 100% !important; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}color-picker-grid { display: flex; flex-wrap: wrap; gap: 10px 20px; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}color-picker-grid .${MENU_CSS_PREFIX}setting-container { margin-bottom: 5px; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}emoji-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 5px 20px; align-items: center; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}emoji-grid .${MENU_CSS_PREFIX}setting-container { margin-bottom: 0px; width: auto; display:flex; justify-content: flex-start; align-items: center; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}color-picker-grid label { min-width: auto; text-align: left; margin-right: 5px; flex-shrink: 0; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}emoji-grid .${MENU_CSS_PREFIX}setting-container label { min-width: 65px; /* Adjust as needed */ text-align: right; margin-right: 5px; flex-shrink: 0; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}test-button-container { display: flex; flex-wrap: wrap; gap: 10px; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}about-profile-pic-container { text-align: center; margin-bottom: 10px; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}about-profile-pic { border-radius: 4px; width: 80px; height: 80px; border: 2px solid var(--tcat-border-color); margin: 10px auto 5px auto; display: block; object-fit: cover; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}about-centered-text { text-align: center; margin-bottom: 5px; margin-top: 0; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}about-script-info { font-size: 0.95em; color: var(--tcat-text-light-color); line-height: 1.4; } #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}about-dev-info { font-size: 0.85em; font-style: italic; color: var(--tcat-text-light-color); margin-top: 10px; } /* Chain Tool Specific Styles */ #${CHAIN_TOOL_ID_LIST_DISPLAY_ID} { font-family: monospace; font-size: 0.95em; background-color: var(--tcat-input-bg-color); border: 1px solid var(--tcat-input-border-color); color: var(--tcat-input-text-color); border-radius: 3px; } #${CHAIN_TOOL_ID_LIST_DISPLAY_ID} option:hover { background-color: var(--tcat-tab-hover-bg) !important; color: var(--tcat-text-color) !important; } #${CHAIN_TOOL_ID_LIST_DISPLAY_ID} option:checked { box-shadow: 0 0 0 1px var(--tcat-accent-color) inset; background-color: var(--tcat-bg-secondary-color) !important; color: var(--tcat-text-color) !important; } #${CHAIN_TOOL_ID_LIST_DISPLAY_ID} option { padding: 2px 5px; } /* Ensure Webhook Name/ID line aligns */ #${SETTINGS_MENU_ID} .${MENU_CSS_PREFIX}setting-container.${MENU_CSS_PREFIX}inline-input-group label { flex-basis: 100px; /* Adjust as needed */ flex-shrink: 0; text-align: right; } `; if (typeof GM_addStyle === 'function') { GM_addStyle(css); } else { console.warn(`[TCAT v${SCRIPT_VERSION}] GM_addStyle not available. Using fallback.`); const S=document.createElement('style'); S.textContent=css; document.head.appendChild(S); } } catch (error) { console.error(`[TCAT v${SCRIPT_VERSION}] Failed to add styles:`, error); showUserMessage("TCAT Error", "Failed to apply styles.", "error"); } }

    // --- Main Execution ---
    function main() { try { initSettings(); addMenuStyles(); if (typeof GM_registerMenuCommand === 'function') { GM_registerMenuCommand("Toggle TCAT Settings", toggleMenu); } else { console.warn(`[TCAT v${SCRIPT_VERSION}] GM_registerMenuCommand not available.`); } restartIntervals(); } catch (error) { console.error(`[TCAT v${SCRIPT_VERSION}] CRITICAL error in main():`, error); showUserMessage("TCAT Error", `Initialization failed: ${error.message}`, "error"); } }

    // --- Script Entry Point ---
    try { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', main); } else { main(); } } catch(e) { console.error(`[TCAT v${SCRIPT_VERSION}] CRITICAL Error at script entry point:`, e); alert("TCAT Script failed to initialize. Check the browser console (F12) for errors."); }

})(); // End of IIFE wrapper