您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Dark mode for Torn Stats with theme selector and improved styling
// ==UserScript== // @name Torn Stats Dark Mode // @namespace http://tampermonkey.net/ // @version 1 // @description Dark mode for Torn Stats with theme selector and improved styling // @author TR0LL // @match https://*.tornstats.com/* // @match https://www.tornstats.com/* // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @run-at document-start // @license Proprietary // ==/UserScript== (function() { 'use strict'; // Script configuration const CURRENT_VERSION = '1.3'; const SETTINGS_KEY = 'tornStatsDarkMode_settings'; const LAST_CHECKED_KEY = 'tornStatsDarkMode_lastChecked'; // Default settings const defaultSettings = { hideVisuals: true, forceDarkMode: true, colorTheme: 'pure-black' }; // Always enable contrast const enhanceContrast = true; // Load settings or use defaults const settings = loadSettings(); // Force hideVisuals to be true when Princess theme is selected if (settings.colorTheme === 'princess') { settings.hideVisuals = true; } // Color themes const colorThemes = { 'pure-black': { background: { primary: '#000000', secondary: '#111111', tertiary: '#1A1A1A' } }, 'dark-gray': { background: { primary: '#121212', secondary: '#1E1E1E', tertiary: '#2A2A2A' } }, 'midnight-blue': { background: { primary: '#0A1929', secondary: '#132F4C', tertiary: '#173A5E' } }, 'princess': { background: { primary: '#1A0013', secondary: '#3D0A38', tertiary: '#5F1059' } } }; // Get current theme colors const themeColors = colorThemes[settings.colorTheme]; // Color scheme definition const colors = { background: themeColors.background, text: { primary: settings.colorTheme === 'princess' ? '#FFFFFF' : '#FFFFFF', secondary: settings.colorTheme === 'princess' ? '#FFEEFC' : '#E0E0E0', muted: settings.colorTheme === 'princess' ? '#FFD6EC' : '#CCCCCC' }, border: { light: settings.colorTheme === 'princess' ? '#FF69B4' : '#555555', medium: settings.colorTheme === 'princess' ? '#FF1493' : '#666666', focus: settings.colorTheme === 'princess' ? '#FF00FF' : '#1E90FF' }, accent: { blue: settings.colorTheme === 'princess' ? '#FF00FF' : '#4D90FE', green: settings.colorTheme === 'princess' ? '#FF69B4' : '#4CAF50', red: settings.colorTheme === 'princess' ? '#FF1493' : '#F44336', yellow: settings.colorTheme === 'princess' ? '#FFCBDB' : '#FFEB3B' }, table: { success: '#1E551E', warning: '#635800', danger: '#5C1F1F' }, chart: { background: themeColors.background.secondary, grid: '#333333', axis: '#777777', navigator: '#444444' }, bootstrap: { blue: '#007bff', indigo: '#6610f2', purple: '#6f42c1', pink: '#e83e8c', red: '#dc3545', orange: '#fd7e14', yellow: '#ffc107', green: '#28a745', teal: '#20c997', cyan: '#17a2b8', white: '#fff', gray: '#6c757d', grayDark: '#343a40', primary: '#007bff', secondary: '#6c757d', success: '#28a745', info: '#17a2b8', warning: '#ffc107', danger: '#dc3545', light: '#f8f9fa', dark: '#343a40' } }; // Apply flash prevention styles immediately GM_addStyle(` html, body { background-color: ${colors.background.primary} !important; color: #FFFFFF !important; transition: none !important; } `); // Dark mode CSS const fullDarkModeCSS = ` /* Base elements */ html, body { background-color: ${colors.background.primary} !important; color: ${colors.text.primary} !important; background-image: none !important; transition: none !important; --blue: ${colors.bootstrap.blue}; --indigo: ${colors.bootstrap.indigo}; --purple: ${colors.bootstrap.purple}; --pink: ${colors.bootstrap.pink}; --red: ${colors.bootstrap.red}; --orange: ${colors.bootstrap.orange}; --yellow: ${colors.bootstrap.yellow}; --green: ${colors.bootstrap.green}; --teal: ${colors.bootstrap.teal}; --cyan: ${colors.bootstrap.cyan}; --white: ${colors.text.primary}; --gray: ${colors.bootstrap.gray}; --gray-dark: ${colors.bootstrap.grayDark}; --primary: ${colors.bootstrap.primary}; --secondary: ${colors.bootstrap.secondary}; --success: ${colors.bootstrap.success}; --info: ${colors.bootstrap.info}; --warning: ${colors.bootstrap.warning}; --danger: ${colors.bootstrap.danger}; --light: ${colors.bootstrap.light}; --dark: ${colors.bootstrap.dark}; } /* Headers with enhanced contrast */ h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { color: ${colors.text.primary} !important; text-shadow: 0 0 1px rgba(255,255,255,0.1) !important; } /* Cards, panels, containers */ .card, .panel, .container, .container-fluid, .modal-content, .popover, .toast { background-color: ${colors.background.secondary} !important; color: ${colors.text.primary} !important; border-color: ${colors.border.light} !important; } /* Card headers and footers */ .card-header, .card-footer, .panel-heading, .panel-footer, .card-header.bg-dark, .card-header.text-white.bg-dark, .bg-dark { background-color: ${colors.background.tertiary} !important; border-color: ${colors.border.light} !important; color: ${colors.text.primary} !important; } /* Tables with better contrast */ table, .table { color: ${colors.text.primary} !important; background-color: ${colors.background.secondary} !important; border-color: ${colors.border.medium} !important; } .table-striped tbody tr:nth-of-type(odd) { background-color: ${colors.background.tertiary} !important; } .table th, .table td { border-color: ${colors.border.light} !important; } /* Table contextual classes */ .table-success, .table-success > th, .table-success > td, td.table-success { background-color: ${colors.table.success} !important; color: ${colors.text.primary} !important; } .table-warning, .table-warning > th, .table-warning > td, td.table-warning { background-color: ${colors.table.warning} !important; color: ${colors.text.primary} !important; } .table-danger, .table-danger > th, .table-danger > td, td.table-danger { background-color: ${colors.table.danger} !important; color: ${colors.text.primary} !important; } tr.table-success, tr.table-warning, tr.table-danger { background-color: inherit !important; } /* Form elements */ input, select, textarea, .form-control, .input-group-text, .custom-select { background-color: ${colors.background.tertiary} !important; color: ${colors.text.primary} !important; border-color: ${colors.border.medium} !important; } input:focus, select:focus, textarea:focus, .form-control:focus { border-color: ${colors.border.focus} !important; box-shadow: 0 0 0 0.2rem rgba(77, 144, 254, 0.5) !important; } /* Buttons */ .btn-primary { background-color: ${colors.accent.blue} !important; border-color: ${colors.accent.blue} !important; } .btn-success { background-color: ${colors.accent.green} !important; border-color: ${colors.accent.green} !important; } .btn-danger { background-color: ${colors.accent.red} !important; border-color: ${colors.accent.red} !important; } .btn-warning { background-color: ${colors.accent.yellow} !important; border-color: ${colors.accent.yellow} !important; color: #212529 !important; } .btn-secondary, .btn-default, .btn-light { background-color: ${colors.background.tertiary} !important; border-color: ${colors.border.medium} !important; color: ${colors.text.primary} !important; } /* Navigation */ .navbar.navbar-expand-md.navbar-dark.bg-dark.navbar-laravel, .card-header.text-center.text-white.bg-dark, .text-white.bg-dark { background-color: ${colors.background.primary} !important; color: ${colors.text.primary} !important; } .navbar, .nav, .pagination { background-color: ${colors.background.primary} !important; border-color: ${colors.border.light} !important; } .bg-dark { background-color: ${colors.background.primary} !important; } .navbar-dark .navbar-nav .nav-link, .nav-link { color: ${colors.text.primary} !important; } .navbar-dark .navbar-nav .nav-link:hover, .nav-link:hover { color: ${colors.accent.blue} !important; text-decoration: none !important; } .page-link { background-color: ${colors.background.tertiary} !important; border-color: ${colors.border.light} !important; color: ${colors.text.primary} !important; } .page-item.active .page-link { background-color: ${colors.accent.blue} !important; border-color: ${colors.accent.blue} !important; } /* Dropdown menus */ .dropdown-menu { background-color: ${colors.background.primary} !important; border-color: ${colors.border.medium} !important; box-shadow: 0 0 10px rgba(0,0,0,0.5) !important; } .dropdown-item { color: ${colors.text.primary} !important; } .dropdown-item:hover, .dropdown-item:focus { background-color: ${colors.background.tertiary} !important; color: ${colors.accent.blue} !important; } .dropdown-divider { border-top-color: ${colors.border.light} !important; } /* Charts - Highcharts */ .highcharts-background, .highcharts-plot-background { fill: ${colors.chart.background} !important; } .highcharts-grid-line { stroke: ${colors.chart.grid} !important; stroke-width: 1px !important; } .highcharts-axis-line, .highcharts-tick { stroke: ${colors.chart.axis} !important; } /* Chart text elements - improve readability */ .highcharts-axis-labels text, .highcharts-legend-item text, .highcharts-title text, .highcharts-subtitle text, .highcharts-data-label text, .highcharts-xaxis-labels text, .highcharts-yaxis-labels text, .highcharts-navigator text, .highcharts-tooltip text { fill: ${colors.text.primary} !important; font-weight: bold !important; stroke-width: 0 !important; text-shadow: 0 0 3px ${colors.background.primary}, 0 0 3px ${colors.background.primary} !important; } /* Ensure readable text in all chart areas */ .highcharts-xaxis text, .highcharts-yaxis text { font-size: 12px !important; fill: ${colors.text.primary} !important; stroke: none !important; font-weight: bold !important; text-shadow: 0 0 3px ${colors.background.primary}, 0 0 3px ${colors.background.primary} !important; } /* Legend specific styling */ .highcharts-legend-item-text { font-weight: bold !important; fill: ${colors.text.primary} !important; } /* Navigator specific fixes */ .highcharts-navigator-mask-inside { fill: transparent !important; } .highcharts-navigator-mask-outside { fill: transparent !important; } .highcharts-navigator-outline { stroke: ${settings.colorTheme === 'princess' ? '#FF69B4' : '#999999'} !important; stroke-width: 1px !important; } .highcharts-navigator-handle { stroke: ${settings.colorTheme === 'princess' ? '#FF69B4' : '#999999'} !important; fill: ${settings.colorTheme === 'princess' ? '#3D0A38' : '#f2f2f2'} !important; } /* Fix hardcoded styles */ [style*="background-color: white"], [style*="background-color: #fff"], [style*="background-color: rgb(255, 255, 255)"], [style*="background: white"], [style*="background: #fff"] { background-color: ${colors.background.secondary} !important; } [style*="color: black"], [style*="color: #000"], [style*="color: rgb(0, 0, 0)"] { color: ${colors.text.primary} !important; } /* TornStats specific fixes */ .progress { background-color: ${colors.background.tertiary} !important; } .progress-bar { background-color: ${colors.accent.blue} !important; } /* Links */ a, a:link, a:visited { color: ${colors.accent.blue} !important; } a:hover, a:active { color: #7EB1FF !important; text-decoration: underline !important; } /* Table rows */ tr.odd, tr.even { background-color: ${colors.background.secondary} !important; } tr.odd td, tr.even td { background-color: inherit !important; } /* Backgrounds */ body[style*="background-image:"] { background-image: none !important; background-color: ${colors.background.primary} !important; } /* Spacing */ .pt-5, .py-5 { padding-top: 2rem !important; } /* Stat colors */ .color-14 { color: ${settings.colorTheme === 'princess' ? '#FFFDFA' : '#FFD700'} !important; } .color-13 { color: ${settings.colorTheme === 'princess' ? '#FFFFFF' : '#E0E0E0'} !important; } .color-12 { color: ${settings.colorTheme === 'princess' ? '#FFE4F0' : '#C0C0C0'} !important; } .color-11 { color: ${settings.colorTheme === 'princess' ? '#FFD6EC' : '#90EE90'} !important; } .color-10 { color: ${settings.colorTheme === 'princess' ? '#FFC0E0' : '#98FB98'} !important; } .color-09 { color: ${settings.colorTheme === 'princess' ? '#FFADD8' : '#ADD8E6'} !important; } .color-08 { color: ${settings.colorTheme === 'princess' ? '#FF90CC' : '#87CEEB'} !important; } .color-07 { color: ${settings.colorTheme === 'princess' ? '#FF69B4' : '#FFA07A'} !important; } .color-05, .color-06 { color: ${settings.colorTheme === 'princess' ? '#FF47A3' : '#FFA500'} !important; } .color-04, .color-03, .color-02, .color-01 { color: ${settings.colorTheme === 'princess' ? '#FF00FF' : '#FF6347'} !important; } /* Accessibility */ :focus-visible { outline: 3px solid ${colors.accent.blue} !important; outline-offset: 2px !important; } /* Loading indicators */ .spinner-border, .spinner-grow { border-color: ${colors.text.secondary} !important; border-right-color: transparent !important; } /* Hide Google Ads */ .google-auto-placed, .adsbygoogle, [data-ad-client], div[id^="aswift_"], iframe[id^="google_ads_"], ins.adsbygoogle { display: none !important; height: 0 !important; visibility: hidden !important; } /* DataTables */ .dataTables_wrapper { background-color: ${colors.background.secondary} !important; color: ${colors.text.primary} !important; } .dataTables_length, .dataTables_filter, .dataTables_info, .dataTables_paginate { color: ${colors.text.primary} !important; } .dataTables_wrapper .dataTables_length select, .dataTables_wrapper .dataTables_filter input { background-color: ${colors.background.tertiary} !important; color: ${colors.text.primary} !important; border-color: ${colors.border.medium} !important; } .dataTables_wrapper .dataTables_paginate .paginate_button { background-color: ${colors.background.tertiary} !important; color: ${colors.text.primary} !important; border-color: ${colors.border.light} !important; } .dataTables_wrapper .dataTables_paginate .paginate_button.current, .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover { background-color: ${colors.accent.blue} !important; color: white !important; border-color: ${colors.accent.blue} !important; } .dataTables_wrapper .dataTables_paginate .paginate_button:hover { background-color: ${colors.background.tertiary} !important; color: ${colors.accent.blue} !important; } .table.dataTable thead th, .table.dataTable thead td { border-bottom-color: ${colors.border.medium} !important; } .table.dataTable.no-footer { border-bottom-color: ${colors.border.medium} !important; } /* Settings Panel */ #ts-darkmode-panel { position: fixed; bottom: 20px; right: 20px; z-index: 9999; background-color: ${colors.background.secondary}; border: 1px solid ${colors.border.medium}; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.5); padding: 10px; width: 260px; transition: transform 0.3s ease; transform: translateX(200px); } #ts-darkmode-panel:hover { transform: translateX(0); } #ts-darkmode-panel.pinned { transform: translateX(0); } #ts-darkmode-panel .settings-title { font-weight: bold; margin-bottom: 10px; color: ${colors.text.primary}; display: flex; justify-content: space-between; align-items: center; } #ts-darkmode-panel .pin-button { cursor: pointer; opacity: 0.7; transition: opacity 0.2s; margin-left: 5px; } #ts-darkmode-panel .pin-button:hover { opacity: 1; } #ts-darkmode-panel .settings-content { margin-bottom: 10px; } #ts-darkmode-panel .settings-option { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; } #ts-darkmode-panel label { margin-bottom: 0; color: ${colors.text.primary}; } #ts-darkmode-panel select { background-color: ${colors.background.tertiary}; color: ${colors.text.primary}; border-color: ${colors.border.medium}; padding: 2px 5px; width: 120px; } #ts-darkmode-panel .toggle-switch { position: relative; display: inline-block; width: 40px; height: 20px; } #ts-darkmode-panel .toggle-switch input { opacity: 0; width: 0; height: 0; } #ts-darkmode-panel .toggle-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: ${colors.background.tertiary}; transition: .4s; border-radius: 20px; } #ts-darkmode-panel .toggle-slider:before { position: absolute; content: ""; height: 16px; width: 16px; left: 2px; bottom: 2px; background-color: white; transition: .4s; border-radius: 50%; } #ts-darkmode-panel input:checked + .toggle-slider { background-color: ${settings.colorTheme === 'princess' ? '#FF00FF' : colors.accent.blue}; } #ts-darkmode-panel input:checked + .toggle-slider:before { transform: translateX(20px); } #ts-darkmode-panel .settings-footer { display: flex; justify-content: flex-end; align-items: center; margin-top: 10px; } #ts-darkmode-panel .settings-credit { font-size: 0.75em; text-align: center; margin-top: 8px; opacity: 0.8; border-top: 1px solid ${colors.border.light}; padding-top: 8px; } #ts-darkmode-panel .settings-credit a { color: ${colors.accent.blue} !important; text-decoration: none !important; } #ts-darkmode-panel .settings-credit a:hover { text-decoration: underline !important; } /* Theme preview */ #ts-darkmode-panel .theme-preview { display: inline-block; width: 15px; height: 15px; border-radius: 50%; margin-right: 5px; vertical-align: middle; border: 1px solid ${colors.border.light}; } #ts-darkmode-panel .theme-preview.pure-black { background-color: #000000; } #ts-darkmode-panel .theme-preview.dark-gray { background-color: #121212; } #ts-darkmode-panel .theme-preview.midnight-blue { background-color: #0A1929; } #ts-darkmode-panel .theme-preview.princess { background-color: #1A0013; border: 1px solid #FF00FF; } `; // Apply the styles GM_addStyle(fullDarkModeCSS); /** * Load settings from storage */ function loadSettings() { const savedSettings = GM_getValue(SETTINGS_KEY); if (savedSettings) { try { return JSON.parse(savedSettings); } catch (e) { console.error('Failed to parse saved settings:', e); } } return { ...defaultSettings }; } /** * Save settings to storage */ function saveSettings(settings) { GM_setValue(SETTINGS_KEY, JSON.stringify(settings)); } /** * Show the save indicator briefly */ function showSaveIndicator() { const indicator = document.getElementById('save-indicator'); if (indicator) { indicator.classList.add('active'); setTimeout(() => { indicator.classList.remove('active'); }, 1500); } } /** * Modifies the DOM to hide specific elements */ function modifyDOM() { try { const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches; if (!prefersDarkMode && !settings.forceDarkMode) { return; } if (settings.hideVisuals) { // Hide graph container const graphContainer = document.getElementById('graph_container'); if (graphContainer) { graphContainer.style.display = 'none'; } // Hide Graph/Growth Details links const linkDiv = document.querySelector('.col-md-12.text-center'); if (linkDiv) { linkDiv.style.display = 'none'; } // Hide chart elements toggleChartVisibility(true); } else { // Show all visual elements const graphContainer = document.getElementById('graph_container'); if (graphContainer) { graphContainer.style.display = ''; } const linkDiv = document.querySelector('.col-md-12.text-center'); if (linkDiv) { linkDiv.style.display = ''; } toggleChartVisibility(false); } } catch (error) { console.error('Torn Stats Dark Mode Error:', error); } } /** * Toggles the visibility of chart elements */ function toggleChartVisibility(hide) { try { let chartStyle = document.getElementById('chart-visibility-style'); if (!chartStyle) { chartStyle = document.createElement('style'); chartStyle.id = 'chart-visibility-style'; document.head.appendChild(chartStyle); } if (hide) { chartStyle.textContent = ` .highcharts-container, .highcharts-root, g.highcharts-grid, g.highcharts-axis, g.highcharts-series, g.highcharts-markers, g.highcharts-legend, g.highcharts-title, g.highcharts-subtitle, g.highcharts-label, g.highcharts-tooltip, g.highcharts-credits { display: none !important; } #chart { min-height: 100px !important; position: relative !important; } #chart::before { content: "Charts are hidden"; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #aaa; font-style: italic; display: none; } .col-md-12:has(#chart:empty) { display: none; } #chart:empty + div table { margin-top: 20px; } `; } else { chartStyle.textContent = ''; } if (hide && document.getElementById('chart')) { const statTables = document.querySelectorAll('table.table-striped'); statTables.forEach(table => { table.style.marginTop = '20px'; }); } } catch (error) { console.error('Chart visibility toggle error:', error); } } /** * Create and add the settings panel */ function createSettingsPanel() { const panel = document.createElement('div'); panel.id = 'ts-darkmode-panel'; panel.innerHTML = ` <div class="settings-title"> <span>🌙 Dark Mode</span> <span style="display: flex; align-items: center;"> <span title="Pin panel" class="pin-button" id="pin-button">📌</span> <span style="opacity: 0.7; font-size: 0.8em; margin-left: 5px;">v${CURRENT_VERSION}</span> </span> </div> <div class="settings-content"> <div class="settings-option"> <label for="theme-selector" title="Select color theme">Theme:</label> <select id="theme-selector"> <option value="pure-black" ${settings.colorTheme === 'pure-black' ? 'selected' : ''}>Pure Black</option> <option value="dark-gray" ${settings.colorTheme === 'dark-gray' ? 'selected' : ''}>Dark Gray</option> <option value="midnight-blue" ${settings.colorTheme === 'midnight-blue' ? 'selected' : ''}>Midnight Blue</option> <option value="princess" ${settings.colorTheme === 'princess' ? 'selected' : ''}>Princess</option> </select> </div> <div class="settings-option"> <label title="Force dark mode regardless of system preference">Force Dark Mode:</label> <label class="toggle-switch"> <input type="checkbox" id="force-darkmode" ${settings.forceDarkMode ? 'checked' : ''}> <span class="toggle-slider"></span> </label> </div> <div class="settings-option"> <label title="Hide all visual elements (graphs, charts, and links)">Hide Visuals:</label> <label class="toggle-switch" ${settings.colorTheme === 'princess' ? 'title="Always enabled in Princess theme"' : ''}> <input type="checkbox" id="hide-visuals" ${settings.hideVisuals ? 'checked' : ''} ${settings.colorTheme === 'princess' ? 'disabled' : ''}> <span class="toggle-slider"></span> </label> ${settings.colorTheme === 'princess' ? '<span style="font-size: 0.7em; margin-left: 5px; opacity: 0.8;">Locked in Princess theme</span>' : ''} </div> <div class="settings-footer"> <div id="save-indicator" class="save-indicator">Saved!</div> </div> <div class="settings-credit"> <a href="https://greasyfork.org/en/users/1431907-theeeunknown" target="_blank">Created by TR0LL [2561502]</a> </div> </div> `; document.body.appendChild(panel); // Add event listeners document.getElementById('theme-selector').addEventListener('change', function() { settings.colorTheme = this.value; // Force hideVisuals to be true when Princess theme is selected if (settings.colorTheme === 'princess') { settings.hideVisuals = true; } saveSettings(settings); showSaveIndicator(); reloadPage(); }); document.getElementById('force-darkmode').addEventListener('change', function() { settings.forceDarkMode = this.checked; saveSettings(settings); showSaveIndicator(); reloadPage(); }); document.getElementById('hide-visuals').addEventListener('change', function() { // Only allow changes if not in Princess theme if (settings.colorTheme !== 'princess') { settings.hideVisuals = this.checked; saveSettings(settings); showSaveIndicator(); modifyDOM(); } else { // Keep checked if in Princess theme this.checked = true; } }); // Pin panel button document.getElementById('pin-button').addEventListener('click', function() { const panel = document.getElementById('ts-darkmode-panel'); if (panel.classList.contains('pinned')) { panel.classList.remove('pinned'); this.textContent = '📌'; this.title = 'Pin panel'; } else { panel.classList.add('pinned'); this.textContent = '📍'; this.title = 'Unpin panel'; } }); // Add theme previews const themeSelector = document.getElementById('theme-selector'); Array.from(themeSelector.options).forEach(option => { const themePreview = document.createElement('span'); themePreview.classList.add('theme-preview', option.value); option.prepend(themePreview); }); } /** * Reload the page to apply new settings */ function reloadPage() { window.location.reload(); } /** * Observer for dynamic content */ const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if (mutation.addedNodes.length) { modifyDOM(); } }); }); /** * Start the observer */ function startObserver() { observer.observe(document.body, { childList: true, subtree: true }); } /** * Check for updates once per day */ function checkForUpdates() { const now = Date.now(); const lastChecked = GM_getValue(LAST_CHECKED_KEY, 0); if (now - lastChecked > 86400000) { GM_setValue(LAST_CHECKED_KEY, now); console.log('Torn Stats Dark Mode: Checking for updates...'); } } /** * Initialize everything */ function initialize() { checkForUpdates(); modifyDOM(); startObserver(); if (document.body) { createSettingsPanel(); } else { document.addEventListener('DOMContentLoaded', createSettingsPanel); } } // Initialize based on document readiness if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initialize); } else { initialize(); } })();