diff --git a/assets/js/theme-switcher.js b/assets/js/theme-switcher.js new file mode 100644 index 00000000..1e0e3a55 --- /dev/null +++ b/assets/js/theme-switcher.js @@ -0,0 +1,116 @@ +// Theme switching functionality +(function() { + // Theme options + const themeOptions = { + light: 'light', + dark: 'dark', + auto: 'auto' + }; + + // Set theme + function setTheme(themeName) { + // Save to local storage + localStorage.setItem('theme', themeName); + + // Apply theme + applyTheme(themeName); + + // Update active theme visual display + updateActiveTheme(themeName); + + // Update theme dropdown button display + updateDropdownButton(themeName); + } + + // Apply theme + function applyTheme(themeName) { + // If auto theme, determine light or dark based on system preference + if (themeName === themeOptions.auto) { + const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)').matches; + document.body.setAttribute('data-theme', prefersDarkScheme ? themeOptions.dark : themeOptions.light); + } else { + document.body.setAttribute('data-theme', themeName); + } + } + + // Update theme dropdown button display + function updateDropdownButton(themeName) { + // Get icon and display name + let icon = '🔆'; + let name = 'Light'; + + if (themeName === themeOptions.dark) { + icon = '🌙'; + name = 'Dark'; + } else if (themeName === themeOptions.auto) { + icon = '🔄'; + name = 'Auto'; + } + + // Update button content + const buttonIcon = document.querySelector('.theme-dropdown-btn .theme-icon'); + const buttonName = document.querySelector('.theme-dropdown-btn .theme-name'); + + if (buttonIcon) buttonIcon.textContent = icon; + if (buttonName) buttonName.textContent = name; + } + + // Update active theme visual display + function updateActiveTheme(themeName) { + // Remove all active classes + document.querySelectorAll('.theme-dropdown-item').forEach(option => { + option.classList.remove('active'); + }); + + // Add active class to current theme + const activeOption = document.querySelector(`.theme-dropdown-item[data-theme="${themeName}"]`); + if (activeOption) { + activeOption.classList.add('active'); + } + } + + // Initialize theme + function initTheme() { + // Check if theme is already set in local storage + const savedTheme = localStorage.getItem('theme') || themeOptions.light; + setTheme(savedTheme); + + // Listen for system theme changes (only effective in auto mode) + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => { + if (localStorage.getItem('theme') === themeOptions.auto) { + applyTheme(themeOptions.auto); + } + }); + + // Toggle dropdown menu display + const themeButton = document.querySelector('.theme-dropdown-btn'); + if (themeButton) { + themeButton.addEventListener('click', function(e) { + e.stopPropagation(); + document.querySelector('.theme-dropdown-content').classList.toggle('show'); + }); + } + + // Close dropdown menu when clicking outside + window.addEventListener('click', function() { + document.querySelector('.theme-dropdown-content').classList.remove('show'); + }); + + // Add event listeners for theme options + document.querySelectorAll('.theme-dropdown-item').forEach(option => { + option.addEventListener('click', function(e) { + e.stopPropagation(); + const theme = this.getAttribute('data-theme'); + setTheme(theme); + document.querySelector('.theme-dropdown-content').classList.remove('show'); + }); + }); + } + + // Execute initialization after DOM is loaded + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initTheme); + } else { + initTheme(); + } +})(); \ No newline at end of file diff --git a/assets/scss/_dark-theme.scss b/assets/scss/_dark-theme.scss new file mode 100644 index 00000000..4d99073a --- /dev/null +++ b/assets/scss/_dark-theme.scss @@ -0,0 +1,304 @@ +// Dark theme styles + +[data-theme="dark"] { + --primary-bg-color: #36454F; // Changed to dark gray-blue + --secondary-bg-color: #2e3b44; + --primary-text-color: #ffffff; // Changed to white + --secondary-text-color: #f0f0f0; + --link-color: #8ab4f8; + --link-hover-color: #aecbfa; + --code-bg-color: #0d1117; // GitHub dark theme code background color + --code-text-color: #c9d1d9; // GitHub dark theme code text color + --border-color: #444444; + --navbar-bg-color: inherit; // Navbar color remains unchanged + --dropdown-bg-color: #333333; + --dropdown-text-color: #f0f0f0; + --card-bg-color: #2d2d2d; + --header-bg-color: #252525; + --footer-bg-color: #252525; + --search-bg-color: #1e2329; // Search box background color + --search-text-color: #ffffff; // Search box text color + + // Apply dark theme colors + background-color: var(--primary-bg-color); + color: var(--primary-text-color); + + .navbar { + border-bottom: 1px solid var(--border-color); + + .dropdown-menu { + .dropdown-item { + &:hover, &:focus { + background-color: rgba(0, 0, 0, 0.5); + color: #ffffff; + } + } + } + } + + .dropdown-menu { + background-color: var(--dropdown-bg-color); + border: 1px solid var(--border-color); + + .dropdown-item { + color: var(--dropdown-text-color); + + &:hover, &:focus { + background-color: rgba(0, 0, 0, 0.3); + color: #ffffff; + } + } + } + + .nav-link { + color: inherit !important; + + &:hover { + color: var(--link-hover-color) !important; + } + } + + a { + color: var(--link-color); + + &:hover { + color: var(--link-hover-color); + } + } + + .card, .td-box { + background-color: var(--card-bg-color); + border-color: var(--border-color); + } + + pre, code { + background-color: var(--code-bg-color); + color: var(--code-text-color); + font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; + -webkit-font-smoothing: auto; + -moz-osx-font-smoothing: auto; + text-shadow: none; // Remove text shadow/ghosting + } + + .highlight { + background-color: var(--code-bg-color); + } + + .chroma { + background-color: var(--code-bg-color); + color: var(--code-text-color); + text-shadow: none; // Remove text shadow/ghosting + + .k, .kd, .kn { // Keywords + color: #ff7b72; + font-weight: normal; + } + + .s, .s1, .s2 { // Strings + color: #a5d6ff; + } + + .c, .c1, .cm { // Comments + color: #8b949e; + } + + .n, .nb { // Names + color: #c9d1d9; + } + + .o, .p { // Operators and punctuation + color: #c9d1d9; + } + + .mi, .mf { // Numbers + color: #79c0ff; + } + + .gr, .gt { // Errors etc. + color: #ff7b72; + } + } + + .td-sidebar { + background-color: var(--secondary-bg-color); + border-right: 1px solid var(--border-color); + } + + .td-sidebar-nav a { + color: var(--primary-text-color); + } + + .td-footer { + background-color: var(--footer-bg-color); + color: var(--primary-text-color); + } + + .td-search-input { + background-color: var(--search-bg-color) !important; + color: var(--search-text-color) !important; + border-color: #444444 !important; + + &::placeholder { + color: #8b949e !important; + } + } + + .popover.offline-search-result { + background-color: var(--dropdown-bg-color); + border-color: var(--border-color); + + .arrow::after { + border-bottom-color: var(--dropdown-bg-color); + } + } + + input, select, textarea { + background-color: var(--secondary-bg-color); + border-color: var(--border-color); + color: var(--primary-text-color); + } + + .btn-primary { + background-color: #0366d6; + border-color: #0366d6; + } + + .btn-secondary { + background-color: #444; + border-color: #444; + } + + table { + color: var(--primary-text-color); + + th, td { + border-color: var(--border-color); + } + } + + hr { + border-color: var(--border-color); + } + + blockquote { + border-left-color: var(--border-color); + } + + .td-home .td-box { + background-color: #36454F; + color: #ffffff; + } + + .td-about { + background-color: inherit; + color: inherit; + + * { + background-color: inherit; + color: inherit; + } + } + + .td-about .td-footer { + background-color: var(--footer-bg-color); + color: var(--primary-text-color); + } +} + +// Theme switch button styles +.theme-switch-wrapper { + display: flex; + align-items: center; + margin-left: 10px; + margin-right: 10px; +} + +// Theme switch dropdown menu styles +.theme-dropdown { + position: relative; + display: inline-block; +} + +.theme-dropdown-btn { + background: transparent; + border: none; + cursor: pointer; + padding: 5px; + font-size: 16px; + display: flex; + align-items: center; + color: inherit; +} + +// Ensure theme name is white in all themes +.theme-name { + color: #ffffff !important; +} + +.theme-dropdown-content { + display: none; + position: absolute; + right: 0; + min-width: 120px; + background-color: #f8f9fa; + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); + z-index: 1; + border-radius: 4px; + + &.show { + display: block; + } +} + +[data-theme="dark"] .theme-dropdown-content { + background-color: #333; + color: #fff; +} + +.theme-dropdown-item { + padding: 10px 12px; + display: block; + text-decoration: none; + color: #333; + cursor: pointer; + + &:hover { + background-color: rgba(0, 0, 0, 0.1); + } + + // Active state styles + &.active { + background-color: rgba(0, 0, 0, 0.2); + font-weight: bold; + } +} + +[data-theme="dark"] .theme-dropdown-item { + color: #fff; + + &:hover { + background-color: rgba(255, 255, 255, 0.1); + } + + // Active state styles in dark mode + &.active { + background-color: rgba(255, 255, 255, 0.2); + font-weight: bold; + } +} + +// Ensure dropdown menu text has correct color in all themes +.theme-dropdown-item-text { + color: inherit; +} + +// Ensure currently selected theme item is clearly marked in dropdown menu +.theme-dropdown-item.active::after { + content: "✓"; + margin-left: 5px; + float: right; +} + +.theme-icon { + margin-right: 5px; +} \ No newline at end of file diff --git a/assets/scss/main.scss b/assets/scss/main.scss index 1888264a..a049d456 100644 --- a/assets/scss/main.scss +++ b/assets/scss/main.scss @@ -33,11 +33,30 @@ @import "community"; @import "markdown"; @import "safety"; +@import "dark-theme"; @if $td-enable-google-fonts { @import url($web-font-path); } +// Define light theme variables (default theme) +:root { + --primary-bg-color: #fff; + --secondary-bg-color: #f8f9fa; + --primary-text-color: #212529; + --secondary-text-color: #495057; + --link-color: #007bff; + --link-hover-color: #0056b3; + --code-bg-color: #f8f9fa; + --border-color: #dee2e6; + --navbar-bg-color: #fff; + --dropdown-bg-color: #fff; + --dropdown-text-color: #212529; + --card-bg-color: #fff; + --header-bg-color: #f8f9fa; + --footer-bg-color: #f8f9fa; +} + footer { min-height: 150px; diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 5fb67d5c..c018cfe6 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -24,6 +24,8 @@ {{ partial "google_analytics.html" . }} {{ partialCached "head-css.html" . "asdf" }} + + {{ end }} - -{{ if .Site.Params.katex.enable }} - - - - -{{ if .Site.Params.katex.mhchem.enable }} - - -{{ end }} - - -{{ end }} - {{ $jsBase := resources.Get "js/base.js" }} {{ $security := resources.Get "js/security.js" }} {{ $jsAnchor := resources.Get "js/anchor.js" }} @@ -40,6 +26,10 @@ {{ $js := $js | minify | fingerprint }} {{ end }} + + + + {{ if .Site.Params.prism_syntax_highlighting }} diff --git a/static/css/dark-theme.css b/static/css/dark-theme.css new file mode 100644 index 00000000..c0e4b8a6 --- /dev/null +++ b/static/css/dark-theme.css @@ -0,0 +1,322 @@ +/* Dark theme styles */ + +[data-theme="dark"] { + --primary-bg-color: #36454F; /* Changed to dark gray-blue */ + --secondary-bg-color: #2e3b44; + --primary-text-color: #ffffff; /* Changed to white */ + --secondary-text-color: #f0f0f0; + --link-color: #8ab4f8; + --link-hover-color: #aecbfa; + --code-bg-color: #0d1117; /* GitHub dark theme code background color */ + --code-text-color: #c9d1d9; /* GitHub dark theme code text color */ + --border-color: #444444; + --navbar-bg-color: inherit; /* Navbar color remains unchanged */ + --dropdown-bg-color: #333333; + --dropdown-text-color: #f0f0f0; + --card-bg-color: #2d2d2d; + --header-bg-color: #252525; + --footer-bg-color: #252525; + --search-bg-color: #1e2329; /* Search box background color */ + --search-text-color: #ffffff; /* Search box text color */ + + /* Apply dark theme colors */ + background-color: var(--primary-bg-color); + color: var(--primary-text-color); +} + +/* Navbar styles - keep original color */ +[data-theme="dark"] .navbar { + /* Remove background color modification, maintain original style */ + border-bottom: 1px solid var(--border-color); +} + +/* Dropdown menu styles */ +[data-theme="dark"] .dropdown-menu { + background-color: var(--dropdown-bg-color); + border: 1px solid var(--border-color); +} + +[data-theme="dark"] .dropdown-menu .dropdown-item { + color: var(--dropdown-text-color); +} + +[data-theme="dark"] .dropdown-menu .dropdown-item:hover, +[data-theme="dark"] .dropdown-menu .dropdown-item:focus { + background-color: rgba(255, 255, 255, 0.1); +} + +/* Navigation link styles - keep navbar text visible */ +[data-theme="dark"] .nav-link { + color: inherit !important; +} + +[data-theme="dark"] .nav-link:hover { + color: var(--link-hover-color) !important; +} + +/* Link styles */ +[data-theme="dark"] a { + color: var(--link-color); +} + +[data-theme="dark"] a:hover { + color: var(--link-hover-color); +} + +/* Card styles */ +[data-theme="dark"] .card, +[data-theme="dark"] .td-box { + background-color: var(--card-bg-color); + border-color: var(--border-color); +} + +/* Code styles - using GitHub style */ +[data-theme="dark"] pre, +[data-theme="dark"] code { + background-color: var(--code-bg-color); + color: var(--code-text-color); + font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; + -webkit-font-smoothing: auto; + -moz-osx-font-smoothing: auto; + text-shadow: none; /* Remove text shadow/ghosting */ +} + +/* Code highlight section */ +[data-theme="dark"] .highlight { + background-color: var(--code-bg-color); +} + +[data-theme="dark"] .chroma { + background-color: var(--code-bg-color); + color: var(--code-text-color); + text-shadow: none; /* Remove text shadow/ghosting */ +} + +/* GitHub style code syntax highlighting element colors */ +[data-theme="dark"] .chroma .k, /* Keywords */ +[data-theme="dark"] .chroma .kd, /* Declaration keywords */ +[data-theme="dark"] .chroma .kn { /* Namespace keywords */ + color: #ff7b72; + font-weight: normal; +} + +[data-theme="dark"] .chroma .s, /* Strings */ +[data-theme="dark"] .chroma .s1, /* Single quote strings */ +[data-theme="dark"] .chroma .s2 { /* Double quote strings */ + color: #a5d6ff; +} + +[data-theme="dark"] .chroma .c, /* Comments */ +[data-theme="dark"] .chroma .c1, /* Single line comments */ +[data-theme="dark"] .chroma .cm { /* Multi-line comments */ + color: #8b949e; +} + +[data-theme="dark"] .chroma .n, /* Names */ +[data-theme="dark"] .chroma .nb { /* Built-in names */ + color: #c9d1d9; +} + +[data-theme="dark"] .chroma .o, /* Operators */ +[data-theme="dark"] .chroma .p { /* Punctuation */ + color: #c9d1d9; +} + +[data-theme="dark"] .chroma .mi, /* Integers */ +[data-theme="dark"] .chroma .mf { /* Floating point numbers */ + color: #79c0ff; +} + +[data-theme="dark"] .chroma .gr, +[data-theme="dark"] .chroma .gt { + color: #ff7b72; +} + +/* Sidebar styles */ +[data-theme="dark"] .td-sidebar { + background-color: var(--secondary-bg-color); + border-right: 1px solid var(--border-color); +} + +[data-theme="dark"] .td-sidebar-nav a { + color: var(--primary-text-color); +} + +/* Footer styles */ +[data-theme="dark"] .td-footer { + background-color: var(--footer-bg-color); + color: var(--primary-text-color); +} + +/* Search box styles */ +[data-theme="dark"] .td-search-input { + background-color: var(--search-bg-color) !important; + color: var(--search-text-color) !important; + border-color: #444444 !important; +} + +[data-theme="dark"] .td-search-input::placeholder { + color: #8b949e !important; +} + +[data-theme="dark"] .popover.offline-search-result { + background-color: var(--dropdown-bg-color); + border-color: var(--border-color); +} + +[data-theme="dark"] .popover.offline-search-result .arrow::after { + border-bottom-color: var(--dropdown-bg-color); +} + +/* Form element styles */ +[data-theme="dark"] input, +[data-theme="dark"] select, +[data-theme="dark"] textarea { + background-color: var(--secondary-bg-color); + border-color: var(--border-color); + color: var(--primary-text-color); +} + +/* Button styles */ +[data-theme="dark"] .btn-primary { + background-color: #0366d6; + border-color: #0366d6; +} + +[data-theme="dark"] .btn-secondary { + background-color: #444; + border-color: #444; +} + +/* Table styles */ +[data-theme="dark"] table { + color: var(--primary-text-color); +} + +[data-theme="dark"] table th, +[data-theme="dark"] table td { + border-color: var(--border-color); +} + +/* Horizontal rule styles */ +[data-theme="dark"] hr { + border-color: var(--border-color); +} + +/* Blockquote styles */ +[data-theme="dark"] blockquote { + border-left-color: var(--border-color); +} + +/* Home page special styles */ +[data-theme="dark"] .td-home .td-box { + background-color: #36454F; + color: #ffffff; +} + +/* About page only changes footer */ +[data-theme="dark"] .td-about { + background-color: inherit; + color: inherit; +} + +[data-theme="dark"] .td-about * { + background-color: inherit; + color: inherit; +} + +/* About page footer color change */ +[data-theme="dark"] .td-about .td-footer { + background-color: var(--footer-bg-color); + color: var(--primary-text-color); +} + +/* Theme switch button styles */ +.theme-switch-wrapper { + display: flex; + align-items: center; + margin-left: 10px; + margin-right: 10px; +} + +/* Theme switch dropdown menu styles */ +.theme-dropdown { + position: relative; + display: inline-block; +} + +.theme-dropdown-btn { + background: transparent; + border: none; + cursor: pointer; + padding: 5px; + font-size: 16px; + display: flex; + align-items: center; + color: inherit; +} + +.theme-dropdown-content { + display: none; + position: absolute; + right: 0; + min-width: 120px; + background-color: #f8f9fa; + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); + z-index: 1; + border-radius: 4px; +} + +.theme-dropdown-content.show { + display: block; +} + +[data-theme="dark"] .theme-dropdown-content { + background-color: #333; + color: #fff; +} + +.theme-dropdown-item { + padding: 10px 12px; + display: block; + text-decoration: none; + color: #333; + cursor: pointer; +} + +[data-theme="dark"] .theme-dropdown-item { + color: #fff; +} + +.theme-dropdown-item:hover { + background-color: rgba(0, 0, 0, 0.1); +} + +[data-theme="dark"] .theme-dropdown-item:hover { + background-color: rgba(255, 255, 255, 0.1); +} + +.theme-icon { + margin-right: 5px; +} + +/* Light theme variables (default theme) */ +:root { + --primary-bg-color: #fff; + --secondary-bg-color: #f8f9fa; + --primary-text-color: #212529; + --secondary-text-color: #495057; + --link-color: #007bff; + --link-hover-color: #0056b3; + --code-bg-color: #f6f8fa; + --code-text-color: #24292e; + --border-color: #dee2e6; + --navbar-bg-color: inherit; + --dropdown-bg-color: #fff; + --dropdown-text-color: #212529; + --card-bg-color: #fff; + --header-bg-color: #f8f9fa; + --footer-bg-color: #f8f9fa; + --search-bg-color: #fff; + --search-text-color: #212529; +} \ No newline at end of file diff --git a/static/js/theme-switcher.js b/static/js/theme-switcher.js new file mode 100644 index 00000000..67598994 --- /dev/null +++ b/static/js/theme-switcher.js @@ -0,0 +1,182 @@ +// Theme switching functionality +(function() { + // Theme options + const themeOptions = { + light: 'light', + dark: 'dark', + auto: 'auto' + }; + + // Theme icons + const themeIcons = { + light: '☀️', + dark: '🌙', + auto: '🔄' + }; + + // Set theme + function setTheme(themeName) { + // Save to local storage + localStorage.setItem('theme', themeName); + + // Apply theme + applyTheme(themeName); + + // Update dropdown button icon and text + updateDropdownButton(themeName); + } + + // Apply theme + function applyTheme(themeName) { + // If auto theme, determine light or dark based on system preference + let actualTheme = themeName; + if (themeName === themeOptions.auto) { + const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)').matches; + actualTheme = prefersDarkScheme ? themeOptions.dark : themeOptions.light; + document.body.setAttribute('data-theme', actualTheme); + } else { + document.body.setAttribute('data-theme', themeName); + } + + // Special handling for navbar + const navbar = document.querySelector('.navbar'); + if (navbar) { + // Keep navbar's original color + navbar.style.backgroundColor = ''; + } + + // Check if on About page + const isAboutPage = document.body.classList.contains('td-about'); + if (isAboutPage) { + // Keep original colors on About page (except footer) + document.querySelectorAll('.td-about *:not(.td-footer):not(.td-footer *)').forEach(element => { + element.style.backgroundColor = ''; + element.style.color = ''; + }); + } + + // Ensure specific elements on home page have correct colors + if (document.body.classList.contains('td-home')) { + if (actualTheme === themeOptions.dark) { + // In dark mode, ensure home page background is specified dark gray-blue + document.querySelectorAll('.td-home .td-box').forEach(box => { + box.style.backgroundColor = '#36454F'; + box.style.color = '#ffffff'; + }); + } else { + // In light mode, restore original colors + document.querySelectorAll('.td-home .td-box').forEach(box => { + box.style.backgroundColor = ''; + box.style.color = ''; + }); + } + } + + // Ensure code blocks have correct styles + if (actualTheme === themeOptions.dark) { + document.querySelectorAll('pre, code, .highlight, .chroma').forEach(codeBlock => { + codeBlock.style.backgroundColor = 'var(--code-bg-color)'; + codeBlock.style.color = 'var(--code-text-color)'; + codeBlock.style.textShadow = 'none'; + }); + } else { + document.querySelectorAll('pre, code, .highlight, .chroma').forEach(codeBlock => { + codeBlock.style.backgroundColor = ''; + codeBlock.style.color = ''; + codeBlock.style.textShadow = ''; + }); + } + } + + // Update dropdown button + function updateDropdownButton(themeName) { + const dropdownBtn = document.querySelector('.theme-dropdown-btn'); + if (dropdownBtn) { + // Update icon and text + const themeIcon = themeIcons[themeName] || themeIcons.light; + const themeText = getThemeLabel(themeName); + dropdownBtn.innerHTML = `${themeIcon} ${themeText}`; + + // Set active item + document.querySelectorAll('.theme-dropdown-item').forEach(item => { + if (item.getAttribute('data-theme') === themeName) { + item.classList.add('active'); + } else { + item.classList.remove('active'); + } + }); + } + } + + // Get theme name label + function getThemeLabel(themeName) { + switch(themeName) { + case themeOptions.light: + return 'Light'; + case themeOptions.dark: + return 'Dark'; + case themeOptions.auto: + return 'Auto'; + default: + return 'Light'; + } + } + + // Initialize dropdown menu + function initDropdown() { + const dropdownContainer = document.querySelector('.theme-dropdown'); + const dropdownButton = document.querySelector('.theme-dropdown-btn'); + const dropdownContent = document.querySelector('.theme-dropdown-content'); + + // Toggle dropdown menu display when button is clicked + if (dropdownButton && dropdownContent) { + dropdownButton.addEventListener('click', function(e) { + e.stopPropagation(); + dropdownContent.classList.toggle('show'); + }); + + // Close dropdown menu when clicking outside + document.addEventListener('click', function() { + dropdownContent.classList.remove('show'); + }); + + // Prevent menu from closing when clicking menu items + dropdownContent.addEventListener('click', function(e) { + e.stopPropagation(); + }); + } + + // Add event listeners for dropdown menu items + document.querySelectorAll('.theme-dropdown-item').forEach(item => { + item.addEventListener('click', function() { + const theme = this.getAttribute('data-theme'); + setTheme(theme); + dropdownContent.classList.remove('show'); + }); + }); + } + + // Initialize theme + function initTheme() { + // Check if theme is already set in local storage + const savedTheme = localStorage.getItem('theme') || themeOptions.light; + setTheme(savedTheme); + + // Initialize dropdown menu + initDropdown(); + + // Listen for system theme changes (only effective in auto mode) + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => { + if (localStorage.getItem('theme') === themeOptions.auto) { + applyTheme(themeOptions.auto); + } + }); + } + + // Execute initialization after DOM is loaded + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initTheme); + } else { + initTheme(); + } +})(); \ No newline at end of file