diff --git a/static/app.js b/static/app.js index 240d41c..2c999cf 100644 --- a/static/app.js +++ b/static/app.js @@ -1,4 +1,45 @@ (() => { + // Theme management + const themeToggle = document.getElementById("themeToggle"); + const prefersDark = window.matchMedia("(prefers-color-scheme: dark)"); + + function getTheme() { + const saved = localStorage.getItem("xp-theme"); + if (saved) return saved; + return prefersDark.matches ? "dark" : "light"; + } + + function setTheme(theme) { + if (theme === "dark") { + document.documentElement.setAttribute("data-theme", "dark"); + if (themeToggle) themeToggle.textContent = "☀️"; + } else { + document.documentElement.removeAttribute("data-theme"); + if (themeToggle) themeToggle.textContent = "🌙"; + } + localStorage.setItem("xp-theme", theme); + } + + function toggleTheme() { + const current = document.documentElement.getAttribute("data-theme") === "dark" ? "dark" : "light"; + setTheme(current === "dark" ? "light" : "dark"); + } + + // Initialize theme + setTheme(getTheme()); + + // Listen for theme toggle + if (themeToggle) { + themeToggle.addEventListener("click", toggleTheme); + } + + // Listen for system theme changes + prefersDark.addEventListener("change", (e) => { + if (!localStorage.getItem("xp-theme")) { + setTheme(e.matches ? "dark" : "light"); + } + }); + let qs = new URLSearchParams(window.location.search); const qInput = document.getElementById("q"); const channelDropdown = document.getElementById("channelDropdown"); diff --git a/static/index.html b/static/index.html index d3fe8cd..1742882 100644 --- a/static/index.html +++ b/static/index.html @@ -13,6 +13,7 @@
This Little Corner — Elastic Search
+ diff --git a/static/style.css b/static/style.css index 08ddc4e..526f992 100644 --- a/static/style.css +++ b/static/style.css @@ -1,5 +1,101 @@ /* Custom styles for XP.css integration */ +/* Theme variables - Light mode (default) */ +:root { + --xp-bg-desktop: teal; + --xp-bg-window: #ece9d8; + --xp-bg-white: white; + --xp-text-primary: black; + --xp-text-secondary: #666; + --xp-border-light: white; + --xp-border-dark: #0a0a0a; + --xp-border-shadow: grey; + --xp-border-highlight: #dfdfdf; + --xp-button-face: #ece9d8; + --xp-titlebar-bg: linear-gradient(to right, #0054e3, #1591e6); + --xp-titlebar-text: white; + --xp-selection-bg: #0a246a; + --xp-selection-text: white; + --xp-field-bg: white; + --xp-field-border: #7f9db9; +} + +/* Dark mode theme */ +[data-theme="dark"] { + --xp-bg-desktop: #1a1a2e; + --xp-bg-window: #2d2d44; + --xp-bg-white: #1e1e2e; + --xp-text-primary: #e0e0e0; + --xp-text-secondary: #a0a0a0; + --xp-border-light: #4a4a5e; + --xp-border-dark: #0a0a0a; + --xp-border-shadow: #1a1a1a; + --xp-border-highlight: #3a3a4e; + --xp-button-face: #2d2d44; + --xp-titlebar-bg: linear-gradient(to right, #1a3a5e, #2a4a6e); + --xp-titlebar-text: #e0e0e0; + --xp-selection-bg: #2a4a7e; + --xp-selection-text: white; + --xp-field-bg: #1e1e2e; + --xp-field-border: #4a5a6e; +} + +/* Apply theme variables */ +body { + background: var(--xp-bg-desktop); + color: var(--xp-text-primary); +} + +.window { + background: var(--xp-bg-window); +} + +.window-body { + background: var(--xp-bg-window); + color: var(--xp-text-primary); +} + +.title-bar { + background: var(--xp-titlebar-bg); + color: var(--xp-titlebar-text); +} + +button { + background: var(--xp-button-face); + color: var(--xp-text-primary); + box-shadow: inset -1px -1px var(--xp-border-dark), + inset 1px 1px var(--xp-border-light), + inset -2px -2px var(--xp-border-shadow), + inset 2px 2px var(--xp-border-highlight); +} + +button:active { + box-shadow: inset -1px -1px var(--xp-border-light), + inset 1px 1px var(--xp-border-dark), + inset -2px -2px var(--xp-border-highlight), + inset 2px 2px var(--xp-border-shadow); +} + +input[type="text"], +textarea, +select { + background: var(--xp-field-bg); + color: var(--xp-text-primary); + border-color: var(--xp-field-border); +} + +fieldset { + border-color: var(--xp-border-shadow) var(--xp-border-light) var(--xp-border-light) var(--xp-border-shadow); +} + +.status-bar { + background: var(--xp-bg-window); +} + +.status-bar-field { + color: var(--xp-text-primary); +} + /* Fix blurry text rendering - override XP.css font smoothing */ .window, .window *, @@ -33,10 +129,18 @@ label { font-size: 11px; } -body { - background: teal; - padding: 0; - margin: 0; +/* Smooth theme transitions */ +body, +.window, +.window-body, +button, +input, +select, +textarea, +.status-bar, +.channel-dropdown summary, +.channel-options { + transition: background 0.3s ease, color 0.3s ease, border-color 0.3s ease; } /* Channel dropdown custom styling */ @@ -49,9 +153,10 @@ body { list-style: none; cursor: pointer; padding: 3px 4px; - background: ButtonFace; + background: var(--xp-button-face); + color: var(--xp-text-primary); border: 1px solid; - border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; + border-color: var(--xp-border-light) var(--xp-border-shadow) var(--xp-border-shadow) var(--xp-border-light); min-width: 180px; text-align: left; } @@ -74,12 +179,13 @@ body { position: absolute; margin-top: 2px; padding: 4px; - background: ButtonFace; + background: var(--xp-bg-window); + color: var(--xp-text-primary); border: 1px solid; - border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; + border-color: var(--xp-border-light) var(--xp-border-shadow) var(--xp-border-shadow) var(--xp-border-light); max-height: 300px; overflow-y: auto; - box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.2); + box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.3); z-index: 100; min-width: 220px; } @@ -116,7 +222,7 @@ body { /* Results styling */ #results .item { - border-bottom: 1px solid ButtonShadow; + border-bottom: 1px solid var(--xp-border-shadow); padding: 12px 0; margin-bottom: 8px; } @@ -144,9 +250,10 @@ body { /* Transcript and highlights */ .transcript { - background: Window; + background: var(--xp-field-bg); + color: var(--xp-text-primary); border: 1px solid; - border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; + border-color: var(--xp-border-shadow) var(--xp-border-light) var(--xp-border-light) var(--xp-border-shadow); padding: 8px; margin-top: 6px; max-height: 200px; @@ -169,9 +276,9 @@ body { } .highlight-row:hover { - background: Highlight; - color: HighlightText; - border: 1px dotted WindowText; + background: var(--xp-selection-bg); + color: var(--xp-selection-text); + border: 1px dotted var(--xp-text-primary); } mark { @@ -187,9 +294,10 @@ mark { .full-transcript { margin-top: 12px; padding: 8px; - background: Window; + background: var(--xp-field-bg); + color: var(--xp-text-primary); border: 2px solid; - border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; + border-color: var(--xp-border-shadow) var(--xp-border-light) var(--xp-border-light) var(--xp-border-shadow); max-height: 400px; overflow-y: auto; font-size: 11px; @@ -198,7 +306,7 @@ mark { .transcript-segment { margin-bottom: 10px; padding-bottom: 6px; - border-bottom: 1px solid ButtonShadow; + border-bottom: 1px solid var(--xp-border-shadow); } .transcript-segment:last-child { @@ -241,7 +349,7 @@ mark { } .transcript-text { - color: WindowText; + color: var(--xp-text-primary); line-height: 1.4; } @@ -251,8 +359,8 @@ mark { display: flex; align-items: center; justify-content: space-between; - background: ActiveCaption; - color: CaptionText; + background: var(--xp-titlebar-bg); + color: var(--xp-titlebar-text); padding: 2px 4px; } @@ -264,8 +372,8 @@ mark { } .transcript-close:hover { - background: Highlight; - color: HighlightText; + background: var(--xp-selection-bg); + color: var(--xp-selection-text); } /* Chart styling */ @@ -283,7 +391,7 @@ mark { } #frequencyChart .axis text { - fill: WindowText; + fill: var(--xp-text-primary); font-size: 10px; }