aboutsummaryrefslogtreecommitdiffstats
path: root/frontend-vanilla
diff options
context:
space:
mode:
Diffstat (limited to 'frontend-vanilla')
-rw-r--r--frontend-vanilla/THEMES.md151
-rw-r--r--frontend-vanilla/public/themes/refined.css33
-rw-r--r--frontend-vanilla/public/themes/terminal.css169
-rw-r--r--frontend-vanilla/src/main.ts28
-rw-r--r--frontend-vanilla/src/style.css41
5 files changed, 342 insertions, 80 deletions
diff --git a/frontend-vanilla/THEMES.md b/frontend-vanilla/THEMES.md
new file mode 100644
index 0000000..8367046
--- /dev/null
+++ b/frontend-vanilla/THEMES.md
@@ -0,0 +1,151 @@
+# Creating a New Theme
+
+Neko's style theme system layers an additional CSS file on top of the base
+stylesheet. The base `style.css` defines CSS custom properties (variables) and
+all component styles. A theme file overrides whichever of those it wants.
+
+## Quick Start
+
+1. Create a new CSS file in `frontend-vanilla/public/themes/yourtheme.css`
+2. Register the theme name in `frontend-vanilla/src/main.ts` — add it to the
+ `STYLE_THEMES` array:
+ ```ts
+ const STYLE_THEMES = ['default', 'refined', 'terminal', 'codex', 'sakura', 'yourtheme'] as const;
+ ```
+3. Rebuild: `cd frontend-vanilla && npm run build`
+4. Copy output: `cp -r dist/* ../web/dist/v3/`
+
+That's it. The theme will appear in Settings > Style and in the sidebar cycle
+button.
+
+## How it works
+
+When a user picks a style theme, JavaScript inserts a `<link>` tag:
+
+```html
+<link id="style-theme-link" rel="stylesheet" href="/v3/themes/yourtheme.css">
+```
+
+This loads *after* the base stylesheet, so any rules you write will override
+the defaults via normal CSS cascade (same specificity = last one wins). When
+the user switches to "Default," the link tag is removed entirely.
+
+The theme CSS files live in `public/themes/` so Vite copies them as-is into the
+build output (no hashing, no bundling). They're plain CSS — no build step
+required for the theme file itself.
+
+## CSS Variables You Can Override
+
+The base stylesheet defines these custom properties on `:root` (light mode)
+and `.theme-dark` (dark mode):
+
+```css
+/* Colors */
+--bg-color /* Page background */
+--text-color /* Primary text */
+--sidebar-bg /* Sidebar background */
+--link-color /* Links and titles */
+--border-color /* Borders, rules, dividers */
+--accent-color /* Interactive accent (selection, focus) */
+
+/* Fonts */
+--font-body /* Body/article text (default: Palatino stack) */
+--font-heading /* Dynamic heading font (user-selectable) */
+--font-heading-system /* System heading font (Helvetica Neue stack) */
+--font-sans /* Sans-serif stack (Inter/system-ui) */
+--font-mono /* Monospace stack (Courier New) */
+```
+
+### Supporting both light and dark mode
+
+Your theme should define colors for both modes:
+
+```css
+/* Light mode */
+:root {
+ --bg-color: #faf8f4;
+ --text-color: #2c2c2c;
+ --link-color: #8b4513;
+ /* ... */
+}
+
+/* Dark mode */
+.theme-dark {
+ --bg-color: #1c1a17;
+ --text-color: #d4cfc6;
+ --link-color: #c9956b;
+ /* ... */
+}
+```
+
+The light/dark toggle adds/removes the `theme-dark` class on `#app`. Your
+theme's `.theme-dark` rules will override your `:root` rules when active.
+
+**Important:** The base stylesheet has some `.theme-dark .sidebar` rules that
+set the sidebar to a grey background with dark text. If your theme wants a
+different dark-mode sidebar, you'll need to override those specifically:
+
+```css
+.theme-dark .sidebar { background: ...; }
+.theme-dark .sidebar-section li a { color: ...; }
+.theme-dark .sidebar-section h3 { color: ...; }
+.theme-dark .sidebar-footer a { color: ...; }
+```
+
+## Key Selectors Reference
+
+### Layout
+- `.sidebar` — Fixed sidebar (11rem wide)
+- `.main-content` — Scrollable content area
+- `.main-content > *` — Content max-width container (default: 35em)
+
+### Feed items
+- `.feed-item` — Individual article wrapper
+- `.item-title` — Article title/link
+- `.dateline` — Date + feed source line
+- `.item-description` — Article body content
+- `.star-btn` / `.star-btn.is-starred` / `.star-btn.is-unstarred` — Star toggle
+- `.scrape-btn` — "text" button for full-content fetch
+
+### Settings page
+- `.settings-view` — Settings container
+- `.settings-section` / `.settings-section h3` — Section blocks
+- `.settings-group` / `.data-group` — Form groups
+- `.theme-options` — Button row for theme/style selectors
+- `.button-group` — Button row for export/import
+- `.manage-feed-list` / `.manage-feed-item` — Feed management list
+
+### Buttons
+- `button` / `.button` — All buttons and button-styled links
+- `button.active` — Currently selected option
+
+### Sidebar details
+- `.sidebar-section h3` — Section headers (FEEDS, TAGS)
+- `.sidebar-section li a` — Feed/filter links
+- `.sidebar-section li.active a` — Selected item
+- `.sidebar-footer` — Bottom area (settings, logout, controls)
+- `.sidebar-quick-controls` / `.sidebar-icon-btn` — Theme toggle icons
+
+## Tips
+
+- **Override fonts broadly.** Set `font-family` on `body` for article text and
+ on `.sidebar`, `.settings-view`, `button` for UI elements.
+- **Use the cascade.** You don't need `!important` — your theme loads after the
+ base stylesheet. Just match or exceed the specificity of the base rule.
+- **Keep it to overrides.** Don't redefine layout or structural properties
+ unless you have a reason. Focus on colors, typography, and spacing.
+- **Test both modes.** Always check your theme in both light and dark.
+- **Note on font overrides:** The user can independently select heading and body
+ fonts in Settings > Fonts. These apply CSS classes like `.font-sans`,
+ `.heading-font-serif`, etc. Your theme's font choices will be the "default"
+ that users see before changing font settings.
+
+## Existing Themes
+
+| Theme | Character |
+|------------|-----------|
+| `default` | No extra CSS — the base stylesheet as-is |
+| `refined` | Tightened spacing, better typographic rhythm, polished details |
+| `terminal` | Monospace, green phosphor accent, CRT scanlines in dark mode |
+| `codex` | Book-inspired: warm cream paper, serif type, fleuron separators |
+| `sakura` | Japanese aesthetic: restrained palette, muted rose accent, calm spacing |
diff --git a/frontend-vanilla/public/themes/refined.css b/frontend-vanilla/public/themes/refined.css
index 9143552..fab2b96 100644
--- a/frontend-vanilla/public/themes/refined.css
+++ b/frontend-vanilla/public/themes/refined.css
@@ -14,7 +14,12 @@
--spacing-md: 1rem;
--spacing-lg: 1.5rem;
--spacing-xl: 2rem;
- --spacing-2xl: 3rem;
+}
+
+/* Dark mode: a warmer, softer link color */
+.theme-dark {
+ --link-color: #a0c4e8;
+ --accent-color: #6fa8d6;
}
/* Slightly refined base typography */
@@ -114,22 +119,21 @@ body {
}
/* ---- Settings Page Refinements ---- */
-/* This is where the biggest improvements are needed */
.settings-view {
- padding-top: var(--spacing-xl);
+ padding-top: var(--spacing-lg);
}
.settings-view h2 {
font-size: 1.8rem;
font-weight: 700;
- margin-bottom: var(--spacing-2xl);
+ margin-bottom: var(--spacing-xl);
letter-spacing: -0.025em;
}
.settings-grid {
- gap: var(--spacing-2xl);
- margin-bottom: var(--spacing-2xl);
+ gap: var(--spacing-lg);
+ margin-bottom: var(--spacing-lg);
}
.settings-section {
@@ -140,28 +144,28 @@ body {
.settings-section h3 {
font-size: 1.1rem;
font-weight: 700;
- margin-bottom: var(--spacing-lg);
- padding-bottom: var(--spacing-sm);
+ margin-bottom: var(--spacing-sm);
+ padding-bottom: var(--spacing-xs);
border-bottom: 1px solid var(--border-color);
}
.settings-group,
.data-group {
- margin-bottom: var(--spacing-lg);
+ margin-bottom: var(--spacing-sm);
}
.settings-group label,
.data-group label {
font-size: 0.75rem;
letter-spacing: 0.1em;
- margin-bottom: var(--spacing-sm);
+ margin-bottom: var(--spacing-xs);
}
.theme-options {
gap: var(--spacing-sm);
}
-/* Consistent button sizing */
+/* Consistent button sizing & vertical centering fix */
button,
.button {
height: 2.2rem;
@@ -169,12 +173,15 @@ button,
font-size: 0.75rem;
letter-spacing: 0.06em;
border-radius: 5px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
}
/* Add feed form alignment */
.add-feed-form {
gap: var(--spacing-sm);
- margin-bottom: var(--spacing-xl);
+ margin-bottom: var(--spacing-lg);
}
.add-feed-form input {
@@ -183,7 +190,7 @@ button,
/* Manage feeds list consistency */
.manage-feeds-section {
- margin-top: var(--spacing-2xl);
+ margin-top: var(--spacing-xl);
}
.manage-feed-item {
diff --git a/frontend-vanilla/public/themes/terminal.css b/frontend-vanilla/public/themes/terminal.css
index f497dfa..dd9c1b2 100644
--- a/frontend-vanilla/public/themes/terminal.css
+++ b/frontend-vanilla/public/themes/terminal.css
@@ -6,32 +6,38 @@
*/
/* ---- Color System ---- */
+/* Light mode: bright terminal on a pale steel background */
:root {
- --bg-color: #0a0e14;
- --text-color: #b0bec5;
- --sidebar-bg: #0d1117;
- --link-color: #00e5ff;
- --border-color: #1e2a35;
- --accent-color: #00e5ff;
-
- --terminal-glow: rgba(0, 229, 255, 0.08);
- --terminal-dim: rgba(0, 229, 255, 0.03);
- --terminal-green: #39ff14;
- --terminal-cyan: #00e5ff;
- --terminal-magenta: #ff00ff;
- --terminal-amber: #ffab00;
+ --bg-color: #f0f2f0;
+ --text-color: #1e2d1e;
+ --sidebar-bg: #e4e8e4;
+ --link-color: #1a7a2e;
+ --border-color: #c4cec4;
+ --accent-color: #1a7a2e;
+
+ --terminal-accent: #1a7a2e;
+ --terminal-glow: rgba(26, 122, 46, 0.08);
+ --terminal-dim: rgba(26, 122, 46, 0.03);
+ --terminal-amber: #a66800;
+ --terminal-red: #c62828;
- color-scheme: dark;
+ color-scheme: light dark;
}
-/* Override dark theme if also applied */
+/* Dark mode: phosphor green on black */
.theme-dark {
- --bg-color: #0a0e14;
- --text-color: #b0bec5;
- --sidebar-bg: #0d1117;
- --link-color: #00e5ff;
- --border-color: #1e2a35;
- --accent-color: #00e5ff;
+ --bg-color: #0a0e0a;
+ --text-color: #b0bfb0;
+ --sidebar-bg: #0d110d;
+ --link-color: #4ae54a;
+ --border-color: #1e2a1e;
+ --accent-color: #4ae54a;
+
+ --terminal-accent: #4ae54a;
+ --terminal-glow: rgba(74, 229, 74, 0.08);
+ --terminal-dim: rgba(74, 229, 74, 0.03);
+ --terminal-amber: #ffab00;
+ --terminal-red: #ff5252;
}
/* ---- Typography ---- */
@@ -46,8 +52,8 @@ body {
-webkit-font-smoothing: antialiased;
}
-/* Subtle scanline overlay on the whole page */
-body::after {
+/* Subtle scanline overlay -- only in dark mode */
+.theme-dark body::after {
content: '';
position: fixed;
top: 0;
@@ -82,14 +88,14 @@ body::after {
.sidebar-section h3 {
font-family: inherit;
- color: var(--terminal-cyan);
+ color: var(--terminal-accent);
opacity: 0.6;
font-size: 0.65rem;
letter-spacing: 0.2em;
}
.theme-dark .sidebar-section h3 {
- color: var(--terminal-cyan);
+ color: var(--terminal-accent);
}
.sidebar-section li a {
@@ -105,19 +111,19 @@ body::after {
.sidebar-section li a:hover {
background: var(--terminal-glow);
- color: var(--terminal-cyan);
+ color: var(--terminal-accent);
transform: none;
}
.theme-dark .sidebar-section li a:hover {
background: var(--terminal-glow);
- color: var(--terminal-cyan);
+ color: var(--terminal-accent);
}
.sidebar-section li.active a {
background: var(--terminal-glow);
- color: var(--terminal-cyan);
- box-shadow: inset 2px 0 0 var(--terminal-cyan);
+ color: var(--terminal-accent);
+ box-shadow: inset 2px 0 0 var(--terminal-accent);
border: none;
border-radius: 0;
font-weight: 500;
@@ -125,7 +131,7 @@ body::after {
.theme-dark .sidebar-section li.active a {
background: var(--terminal-glow);
- color: var(--terminal-cyan);
+ color: var(--terminal-accent);
}
.sidebar-footer {
@@ -144,14 +150,14 @@ body::after {
}
.sidebar-footer a:hover {
- color: var(--terminal-cyan);
+ color: var(--terminal-accent);
background: var(--terminal-dim);
opacity: 1;
}
/* Search */
.sidebar-search input {
- background: rgba(0, 229, 255, 0.05);
+ background: var(--terminal-dim);
border: 1px solid var(--border-color);
border-radius: 2px;
color: var(--text-color);
@@ -159,18 +165,22 @@ body::after {
}
.theme-dark .sidebar-search input {
- background: rgba(0, 229, 255, 0.05);
+ background: var(--terminal-dim);
color: var(--text-color);
border-color: var(--border-color);
}
.sidebar-search input:focus {
- border-color: var(--terminal-cyan);
- box-shadow: 0 0 8px rgba(0, 229, 255, 0.15);
+ border-color: var(--terminal-accent);
+ box-shadow: 0 0 8px rgba(74, 229, 74, 0.15);
}
.sidebar-search input::placeholder {
- color: rgba(176, 190, 197, 0.3);
+ color: rgba(0, 0, 0, 0.25);
+}
+
+.theme-dark .sidebar-search input::placeholder {
+ color: rgba(176, 191, 176, 0.3);
}
/* ---- Toggle ---- */
@@ -203,7 +213,7 @@ body::after {
.feed-item.selected {
background-color: var(--terminal-dim);
- box-shadow: inset 3px 0 0 var(--terminal-cyan);
+ box-shadow: inset 3px 0 0 var(--terminal-accent);
border-radius: 0;
}
@@ -215,30 +225,35 @@ body::after {
font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', 'Courier New', monospace;
font-size: 1.4rem;
line-height: 1.35;
- color: var(--terminal-cyan);
+ color: var(--terminal-accent);
font-weight: 600;
letter-spacing: -0.01em;
}
.item-title:hover {
- color: #ffffff;
- text-shadow: 0 0 12px rgba(0, 229, 255, 0.3);
text-decoration: none;
}
+.theme-dark .item-title:hover {
+ color: #ffffff;
+ text-shadow: 0 0 12px rgba(74, 229, 74, 0.3);
+}
+
.dateline {
- color: rgba(176, 190, 197, 0.35);
+ color: var(--text-color);
+ opacity: 0.35;
font-family: inherit;
font-size: 0.75em;
letter-spacing: 0.04em;
}
.dateline a {
- color: rgba(176, 190, 197, 0.35);
+ color: inherit;
}
.dateline a:hover {
- color: var(--terminal-cyan);
+ color: var(--terminal-accent);
+ opacity: 1;
}
.item-description {
@@ -249,15 +264,15 @@ body::after {
}
.item-description a {
- color: var(--terminal-cyan);
+ color: var(--terminal-accent);
}
-.item-description a:hover {
- text-shadow: 0 0 8px rgba(0, 229, 255, 0.2);
+.theme-dark .item-description a:hover {
+ text-shadow: 0 0 8px rgba(74, 229, 74, 0.2);
}
.item-description pre {
- background: rgba(0, 229, 255, 0.04);
+ background: var(--terminal-dim);
border: 1px solid var(--border-color);
border-radius: 2px;
font-family: inherit;
@@ -276,15 +291,18 @@ body::after {
/* Scrape */
.scrape-btn {
font-family: inherit;
- color: var(--terminal-cyan);
+ color: var(--terminal-accent);
border-color: var(--border-color);
background: transparent;
border-radius: 2px;
}
.scrape-btn:hover {
- border-color: var(--terminal-cyan);
- box-shadow: 0 0 6px rgba(0, 229, 255, 0.15);
+ border-color: var(--terminal-accent);
+}
+
+.theme-dark .scrape-btn:hover {
+ box-shadow: 0 0 6px rgba(74, 229, 74, 0.15);
}
/* ---- Buttons ---- */
@@ -303,8 +321,8 @@ button,
button:hover,
.button:hover {
- border-color: var(--terminal-cyan);
- color: var(--terminal-cyan);
+ border-color: var(--terminal-accent);
+ color: var(--terminal-accent);
background: var(--terminal-dim);
}
@@ -317,16 +335,16 @@ button:hover,
.theme-dark button:hover,
.theme-dark .button:hover {
- border-color: var(--terminal-cyan);
- color: var(--terminal-cyan);
+ border-color: var(--terminal-accent);
+ color: var(--terminal-accent);
background: var(--terminal-dim);
}
button.active,
.theme-dark button.active {
- background: var(--terminal-cyan);
+ background: var(--terminal-accent);
color: var(--bg-color);
- border-color: var(--terminal-cyan);
+ border-color: var(--terminal-accent);
}
/* ---- Settings ---- */
@@ -336,7 +354,7 @@ button.active,
}
.settings-view h2 {
- color: var(--terminal-cyan);
+ color: var(--terminal-accent);
font-weight: 600;
letter-spacing: 0.05em;
font-size: 1.5rem;
@@ -364,13 +382,17 @@ button.active,
color: var(--text-color) !important;
}
+.theme-dark .settings-view h2 {
+ color: var(--terminal-accent) !important;
+}
+
/* Inputs */
input[type="text"],
input[type="url"],
input[type="search"],
select {
font-family: inherit;
- background: rgba(0, 229, 255, 0.04);
+ background: var(--terminal-dim);
border: 1px solid var(--border-color);
border-radius: 2px;
color: var(--text-color);
@@ -378,8 +400,8 @@ select {
input:focus,
select:focus {
- border-color: var(--terminal-cyan);
- box-shadow: 0 0 8px rgba(0, 229, 255, 0.15);
+ border-color: var(--terminal-accent);
+ box-shadow: 0 0 8px rgba(74, 229, 74, 0.15);
}
/* Feed list in settings */
@@ -404,12 +426,16 @@ select:focus {
/* Delete button */
.delete-feed-btn {
- color: #ff5252 !important;
- border-color: rgba(255, 82, 82, 0.3) !important;
+ color: var(--terminal-red) !important;
+ border-color: rgba(198, 40, 40, 0.3) !important;
}
.delete-feed-btn:hover {
- border-color: #ff5252 !important;
+ border-color: var(--terminal-red) !important;
+ background: rgba(198, 40, 40, 0.06) !important;
+}
+
+.theme-dark .delete-feed-btn:hover {
box-shadow: 0 0 6px rgba(255, 82, 82, 0.2) !important;
background: rgba(255, 82, 82, 0.08) !important;
}
@@ -425,22 +451,31 @@ select:focus {
}
::-webkit-scrollbar-thumb {
- background: rgba(0, 229, 255, 0.15);
+ background: rgba(74, 229, 74, 0.15);
border-radius: 0;
}
+.theme-dark ::-webkit-scrollbar-thumb {
+ background: rgba(74, 229, 74, 0.15);
+}
+
::-webkit-scrollbar-thumb:hover {
- background: rgba(0, 229, 255, 0.3);
+ background: rgba(74, 229, 74, 0.3);
}
/* ---- Backdrop ---- */
.sidebar-backdrop {
- background: rgba(0, 0, 0, 0.6);
+ background: rgba(240, 242, 240, 0.6);
backdrop-filter: blur(2px);
}
+.theme-dark .sidebar-backdrop {
+ background: rgba(0, 0, 0, 0.6);
+}
+
/* ---- Loading/Empty States ---- */
.loading, .empty {
- color: rgba(176, 190, 197, 0.4);
+ color: var(--text-color);
+ opacity: 0.4;
font-family: inherit;
}
diff --git a/frontend-vanilla/src/main.ts b/frontend-vanilla/src/main.ts
index fa74274..56ae91a 100644
--- a/frontend-vanilla/src/main.ts
+++ b/frontend-vanilla/src/main.ts
@@ -76,6 +76,10 @@ export function renderLayout() {
-->
</div>
<div class="sidebar-footer">
+ <div class="sidebar-quick-controls">
+ <button id="sidebar-theme-toggle" class="sidebar-icon-btn" title="${store.theme === 'light' ? 'Switch to dark mode' : 'Switch to light mode'}">${store.theme === 'light' ? '☽' : '☀'}</button>
+ <button id="sidebar-style-cycle" class="sidebar-icon-btn" title="Style: ${store.styleTheme}">${store.styleTheme === 'default' ? '◯' : '◉'} ${store.styleTheme}</button>
+ </div>
<a href="/v3/settings" data-nav="settings">Settings</a>
<a href="#" id="logout-button">Logout</a>
</div>
@@ -104,6 +108,18 @@ export function attachLayoutListeners() {
logout();
});
+ // Sidebar quick controls: light/dark toggle
+ document.getElementById('sidebar-theme-toggle')?.addEventListener('click', () => {
+ store.setTheme(store.theme === 'light' ? 'dark' : 'light');
+ });
+
+ // Sidebar quick controls: cycle style theme
+ document.getElementById('sidebar-style-cycle')?.addEventListener('click', () => {
+ const idx = STYLE_THEMES.indexOf(store.styleTheme as typeof STYLE_THEMES[number]);
+ const next = STYLE_THEMES[(idx + 1) % STYLE_THEMES.length];
+ store.setStyleTheme(next);
+ });
+
document.getElementById('sidebar-toggle-btn')?.addEventListener('click', () => {
store.toggleSidebar();
});
@@ -864,6 +880,12 @@ store.on('theme-updated', () => {
// Re-apply classes with proper specificity logic
appEl.className = `theme-${store.theme} font-${store.fontTheme} heading-font-${store.headingFontTheme}`;
}
+ // Update sidebar toggle icon
+ const toggleBtn = document.getElementById('sidebar-theme-toggle');
+ if (toggleBtn) {
+ toggleBtn.textContent = store.theme === 'light' ? '☽' : '☀';
+ toggleBtn.title = store.theme === 'light' ? 'Switch to dark mode' : 'Switch to light mode';
+ }
// Also re-render settings if we are on settings page to update active state of buttons
if (router.getCurrentRoute().path === '/settings') {
renderSettings();
@@ -885,6 +907,12 @@ store.on('sidebar-toggle', () => {
store.on('style-theme-updated', () => {
loadStyleTheme(store.styleTheme);
+ // Update sidebar style cycle button
+ const cycleBtn = document.getElementById('sidebar-style-cycle');
+ if (cycleBtn) {
+ cycleBtn.textContent = `${store.styleTheme === 'default' ? '◯' : '◉'} ${store.styleTheme}`;
+ cycleBtn.title = `Style: ${store.styleTheme}`;
+ }
// Re-render settings if on settings page to update active state
if (router.getCurrentRoute().path === '/settings') {
renderSettings();
diff --git a/frontend-vanilla/src/style.css b/frontend-vanilla/src/style.css
index e9512b7..3061948 100644
--- a/frontend-vanilla/src/style.css
+++ b/frontend-vanilla/src/style.css
@@ -215,6 +215,47 @@ html {
opacity: 1;
}
+/* Quick controls row in sidebar footer */
+.sidebar-quick-controls {
+ display: flex;
+ gap: 0.4rem;
+ margin-bottom: 0.25rem;
+}
+
+.sidebar-icon-btn {
+ background: none;
+ border: none;
+ cursor: pointer;
+ font-size: 0.75rem;
+ padding: 0.3rem 0.6rem;
+ border-radius: 6px;
+ color: var(--text-color);
+ opacity: 0.5;
+ transition: opacity 0.15s, background 0.15s;
+ font-family: var(--font-sans);
+ text-transform: none;
+ font-weight: 500;
+ height: auto;
+ line-height: 1.3;
+}
+
+.sidebar-icon-btn:hover {
+ opacity: 1;
+ background: rgba(255, 255, 255, 0.08);
+ border: none;
+}
+
+.theme-dark .sidebar-icon-btn {
+ color: rgba(0, 0, 0, 0.87);
+ border: none;
+ background: none;
+}
+
+.theme-dark .sidebar-icon-btn:hover {
+ background: rgba(0, 0, 0, 0.06);
+ border: none;
+}
+
/* Main Content area - always fills full width (sidebar overlays) */
.main-content {
width: 100%;