# Light Mode Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Add a persistent light mode theme with a Bitcoin Armory heritage palette (navy sidebar, light content area) toggled by a sun/moon button in the sidebar footer and on the home screen.

**Architecture:** CSS custom properties drive all theming — `[data-theme="light"]` on `<html>` overrides the base palette and adds light-mode semantic tokens. An inline script at the top of `<body>` applies the saved theme before render to prevent flash. The toggle button calls `applyTheme()` in JS which updates `localStorage`, the `data-theme` attribute, and re-renders the icon.

**Tech Stack:** Vanilla CSS custom properties, vanilla JS, Lucide icons (already bundled), `localStorage`.

---

## File map

| File | What changes |
|------|-------------|
| `tauri/src/style.css` | Add `--sidebar-bg` to `:root`, update `.sidebar` background, add `[data-theme="light"]` block and all component overrides |
| `tauri/src/index.html` | Flash-prevention inline script, home screen toggle button, sidebar footer toggle button |
| `tauri/src/app.js` | `applyTheme()`, `toggleTheme()`, call in DOMContentLoaded, add `.tx-amount-sent` class to sent tx rows |
| `ui/static/style.css` | Same CSS changes as tauri (online-only, no offline-specific additions) |
| `ui/static/index.html` | Same HTML changes as tauri |
| `ui/static/app.js` | Same JS changes as tauri |

---

### Task 1: CSS — variables and sidebar token (tauri)

**Files:**
- Modify: `tauri/src/style.css:1-16` (`:root` block)
- Modify: `tauri/src/style.css:687-696` (`.sidebar` rule)
- Modify: `tauri/src/style.css:25` (after `[data-mode="online"]` closing brace)

- [ ] **Step 1: Add `--sidebar-bg` to `:root`**

In `tauri/src/style.css`, add `--sidebar-bg: #2c2c2e;` to the `:root` block. The full block becomes:

```css
:root {
    --bg: #1c1c1e;
    --surface: #242426;
    --border: #30363d;
    --text: #e6edf3;
    --text-dim: #8b949e;
    --accent: #f7931a;
    --accent-dim: #b36a0f;
    --accent-bg-06: rgba(247, 147, 26, 0.06);
    --accent-bg-08: rgba(247, 147, 26, 0.08);
    --accent-bg-10: rgba(247, 147, 26, 0.10);
    --accent-bg-15: rgba(247, 147, 26, 0.15);
    --green: #3fb950;
    --red: #f85149;
    --sidebar-bg: #2c2c2e;
    --mono: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
}
```

- [ ] **Step 2: Update `.sidebar` to use `var(--sidebar-bg)`**

Change `.sidebar`'s `background` from the hardcoded `#2c2c2e` to `var(--sidebar-bg)`:

```css
.sidebar {
    width: 200px;
    flex-shrink: 0;
    background: var(--sidebar-bg);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    height: 100vh;
    overflow: hidden;
}
```

- [ ] **Step 3: Add `[data-theme="light"]` block**

After the `[data-mode="online"]` closing brace (after line 25), insert:

```css
[data-theme="light"] {
    --bg: #f8f9fc;
    --surface: #ffffff;
    --border: #e2e8f0;
    --text: #1e293b;
    --text-dim: #64748b;
    --sidebar-bg: #1a2744;
    --sidebar-border: #2d3f6b;
    --amount-sent: #dc2626;
    --info-fg: #1d4ed8;
    --info-bg: rgba(37, 99, 235, 0.08);
    --info-border: #3b82f6;
    --change-badge-bg: rgba(37, 99, 235, 0.12);
    --change-badge-text: #2563eb;
}
```

- [ ] **Step 4: Verify dark mode unchanged**

Open `tauri/src/index.html` directly in a browser (file:// or via the Flask server). Confirm:
- Background is dark (`#1c1c1e`)
- `<html>` element has no `data-theme` attribute
- Sidebar is `#2c2c2e` (same as before — `var(--sidebar-bg)` resolves to it)

- [ ] **Step 5: Commit**

```bash
git add tauri/src/style.css
git commit -m "feat: add light mode CSS variable foundation"
```

---

### Task 2: CSS — light mode overrides (tauri)

**Files:**
- Modify: `tauri/src/style.css` (append to end of file)

- [ ] **Step 1: Append all light mode override rules to the end of `tauri/src/style.css`**

```css
/* ── Light mode overrides ───────────────────────────────────────────────── */

[data-theme="light"] tr:hover { background: rgba(0, 0, 0, 0.03); }
[data-theme="light"] .file-chooser-btn:hover { background: #d4d4d8; }

[data-theme="light"] .nav-item { color: #8fa3c4; }
[data-theme="light"] .nav-item:hover { color: #e8eaf0; }
[data-theme="light"] .sidebar-title { color: #e8eaf0; }
[data-theme="light"] .sidebar-status-detail { color: #8fa3c4; }
[data-theme="light"] .sidebar { border-right-color: var(--sidebar-border); }
[data-theme="light"] .sidebar-header { border-bottom-color: var(--sidebar-border); }
[data-theme="light"] .sidebar-footer { border-top-color: var(--sidebar-border); }

[data-theme="light"] .alert.info {
    background: var(--info-bg);
    border: 1px solid var(--info-border);
    color: var(--info-fg);
}

[data-theme="light"] .badge.change {
    background: var(--change-badge-bg);
    color: var(--change-badge-text);
}

.tx-amount-sent { color: var(--text); }
[data-theme="light"] .tx-amount-sent { color: var(--amount-sent); }

.theme-toggle-btn {
    background: none;
    border: none;
    color: var(--text-dim);
    cursor: pointer;
    padding: 6px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    flex-shrink: 0;
}
.theme-toggle-btn:hover { color: var(--text); }
[data-theme="light"] .theme-toggle-btn { color: #8fa3c4; }
[data-theme="light"] .theme-toggle-btn:hover { color: #e8eaf0; }

.theme-toggle-home {
    position: fixed;
    top: 12px;
    right: 16px;
    z-index: 10;
}
```

- [ ] **Step 2: Manually test dark mode is unaffected**

Open the app in a browser. Confirm:
- `.alert.info` still shows in orange (no `data-theme="light"` attribute present)
- `.badge.change` still shows gray
- Table row hover still shows the faint white highlight

- [ ] **Step 3: Manually test light mode CSS**

In the browser console, run:
```javascript
document.documentElement.setAttribute('data-theme', 'light')
```
Confirm:
- Page background changes to `#f8f9fc`
- Sidebar remains navy (`#1a2744`)
- `.alert.info` banner (on the wallet overview panel) switches to blue

Run `document.documentElement.removeAttribute('data-theme')` to restore dark mode.

- [ ] **Step 4: Commit**

```bash
git add tauri/src/style.css
git commit -m "feat: add light mode CSS overrides and toggle button styles"
```

---

### Task 3: HTML — flash prevention + toggle buttons (tauri)

**Files:**
- Modify: `tauri/src/index.html`

The HTML currently has `<body>` on line 9. The home container starts at line 10. The sidebar footer is at lines 184–189.

- [ ] **Step 1: Add flash-prevention script immediately after `<body>`**

Replace:
```html
<body>
    <div class="container" id="home-container">
```

With:
```html
<body>
<script>(function(){var t=localStorage.getItem('theme');if(t==='light')document.documentElement.setAttribute('data-theme','light');})()</script>
    <div class="container" id="home-container">
```

- [ ] **Step 2: Add home screen toggle button as first child of `#home-container`**

Replace:
```html
    <div class="container" id="home-container">
        <div id="home-app-title" class="home-app-title">Armory</div>
```

With:
```html
    <div class="container" id="home-container">
        <button class="theme-toggle-btn theme-toggle-home" onclick="toggleTheme()"><i data-lucide="sun" class="nav-icon"></i></button>
        <div id="home-app-title" class="home-app-title">Armory</div>
```

- [ ] **Step 3: Add theme toggle button to sidebar footer**

Replace the sidebar footer block:
```html
            <div class="sidebar-footer">
                <button class="nav-item" onclick="showTab('settings', this)">
                    <i data-lucide="settings" class="nav-icon"></i> Settings
                </button>
                <button id="logout-btn" class="secondary" onclick="logoutCurrentWallet()" style="display:none; width:100%; margin-top:4px; font-size:12px; padding:5px 9px;">Log Out</button>
            </div>
```

With:
```html
            <div class="sidebar-footer">
                <div style="display:flex; align-items:center;">
                    <button class="nav-item" style="flex:1" onclick="showTab('settings', this)">
                        <i data-lucide="settings" class="nav-icon"></i> Settings
                    </button>
                    <button class="theme-toggle-btn" onclick="toggleTheme()"><i data-lucide="sun" class="nav-icon"></i></button>
                </div>
                <button id="logout-btn" class="secondary" onclick="logoutCurrentWallet()" style="display:none; width:100%; margin-top:4px; font-size:12px; padding:5px 9px;">Log Out</button>
            </div>
```

- [ ] **Step 4: Verify HTML renders correctly**

Open the app in a browser. Confirm:
- Settings button and a sun icon appear in the sidebar footer side by side
- A sun icon appears in the top-right corner on the home screen
- The icons are visible and correctly sized
- Logout button still appears when logged in (it's below the settings row)

- [ ] **Step 5: Commit**

```bash
git add tauri/src/index.html
git commit -m "feat: add theme toggle buttons and flash prevention"
```

---

### Task 4: JS — theme functions + DOMContentLoaded + tx class (tauri)

**Files:**
- Modify: `tauri/src/app.js`

The JS currently has `document.addEventListener('DOMContentLoaded', ...)` starting at line 82. The `buildNav()` function is at line 141. The transaction rendering is around line 900–933 (the `<td>` for the amount is at line 927).

- [ ] **Step 1: Add `applyTheme` and `toggleTheme` functions**

Add these two functions near the top of `app.js`, after the variable declarations block (after line 16, before the `invoke` function at line 22):

```javascript
function applyTheme(theme) {
    if (theme === 'light') {
        document.documentElement.setAttribute('data-theme', 'light');
    } else {
        document.documentElement.removeAttribute('data-theme');
    }
    localStorage.setItem('theme', theme);
    document.querySelectorAll('.theme-toggle-btn').forEach(btn => {
        btn.innerHTML = `<i data-lucide="${theme === 'light' ? 'moon' : 'sun'}" class="nav-icon"></i>`;
        lucide.createIcons({ nodes: [btn], attrs: { 'stroke-width': '1.5' } });
    });
}

function toggleTheme() {
    applyTheme(document.documentElement.getAttribute('data-theme') === 'light' ? 'dark' : 'light');
}
```

- [ ] **Step 2: Call `applyTheme` in `DOMContentLoaded`**

In the `DOMContentLoaded` handler, after the `lucide.createIcons` call for the sidebar footer (currently line 114), add:

```javascript
    lucide.createIcons({ nodes: [document.querySelector('.sidebar-footer')], attrs: { 'stroke-width': '1.5' } });
    applyTheme(localStorage.getItem('theme') || 'dark');
```

The full DOMContentLoaded handler should look like:
```javascript
document.addEventListener('DOMContentLoaded', async () => {
    if (IS_TAURI) {
        try { MODE = await invoke('get_app_mode'); } catch { MODE = 'online'; }
    }
    const params = new URLSearchParams(window.location.search);
    if (params.get('mode') === 'offline') MODE = 'offline';

    document.documentElement.setAttribute('data-mode', MODE);
    const appTitle = MODE === 'offline' ? 'Armory Offline' : 'Armory Online';
    document.title = appTitle;
    const sidebarTitleEl = document.getElementById('sidebar-title');
    if (sidebarTitleEl) sidebarTitleEl.textContent = appTitle;
    const homeTitleEl = document.getElementById('home-app-title');
    if (homeTitleEl) homeTitleEl.textContent = appTitle;

    document.querySelectorAll('.online-only').forEach(el => {
        el.style.display = MODE === 'online' ? '' : 'none';
    });
    document.querySelectorAll('.offline-only').forEach(el => {
        el.style.display = MODE === 'offline' ? '' : 'none';
    });

    buildNav();
    lucide.createIcons({ nodes: [document.querySelector('.sidebar-footer')], attrs: { 'stroke-width': '1.5' } });
    applyTheme(localStorage.getItem('theme') || 'dark');

    if (MODE === 'online') {
        initOnline();
    } else {
        initOffline();
    }
});
```

- [ ] **Step 3: Add `.tx-amount-sent` class to sent transaction amounts**

Find the transaction amount `<td>` in the `buildTxList` function (around line 927). Change:
```javascript
                    <td style="font-family:var(--mono)">${sign}${amount.toLocaleString()} sats</td>
```
To:
```javascript
                    <td class="${tx.category === 'send' ? 'tx-amount-sent' : ''}" style="font-family:var(--mono)">${sign}${amount.toLocaleString()} sats</td>
```

- [ ] **Step 4: Verify toggle works end-to-end**

Open the app in a browser. Then:
1. Click the sun icon in the sidebar footer — page switches to light mode, icon becomes moon
2. Click moon icon — page switches back to dark mode, icon becomes sun
3. Switch to light mode, reload the page — page opens in light mode (no flash)
4. Click the sun icon on the home screen (before logging in) — same toggle behavior
5. Load a wallet and open Transactions — confirm sent amounts appear in red in light mode

- [ ] **Step 5: Commit**

```bash
git add tauri/src/app.js
git commit -m "feat: implement theme toggle with localStorage persistence"
```

---

### Task 5: Mirror CSS to web UI

**Files:**
- Modify: `ui/static/style.css`

The web UI's `style.css` mirrors the Tauri one but does not have the macOS-specific `user-select` rules. Apply the same three groups of changes.

- [ ] **Step 1: Add `--sidebar-bg` to `:root` in `ui/static/style.css`**

The `:root` block in `ui/static/style.css` ends with `--mono: ...`. Add `--sidebar-bg: #2c2c2e;` as the last item before the closing brace.

- [ ] **Step 2: Change `.sidebar` background in `ui/static/style.css`**

Find `.sidebar { ... background: #2c2c2e; ... }` and change `background: #2c2c2e` to `background: var(--sidebar-bg)`.

- [ ] **Step 3: Add `[data-theme="light"]` block after `[data-mode="online"]` in `ui/static/style.css`**

Insert the same block as in Task 1 Step 3:

```css
[data-theme="light"] {
    --bg: #f8f9fc;
    --surface: #ffffff;
    --border: #e2e8f0;
    --text: #1e293b;
    --text-dim: #64748b;
    --sidebar-bg: #1a2744;
    --sidebar-border: #2d3f6b;
    --amount-sent: #dc2626;
    --info-fg: #1d4ed8;
    --info-bg: rgba(37, 99, 235, 0.08);
    --info-border: #3b82f6;
    --change-badge-bg: rgba(37, 99, 235, 0.12);
    --change-badge-text: #2563eb;
}
```

- [ ] **Step 4: Append override rules to end of `ui/static/style.css`**

Append the same block as in Task 2 Step 1 (the full `/* ── Light mode overrides */` section).

- [ ] **Step 5: Commit**

```bash
git add ui/static/style.css
git commit -m "feat: mirror light mode CSS to web UI"
```

---

### Task 6: Mirror HTML to web UI

**Files:**
- Modify: `ui/static/index.html`

The web UI HTML is online-only. It has a static nav (no `buildNav()`), but the sidebar footer and home container structure are the same.

- [ ] **Step 1: Add flash-prevention script after `<body>` in `ui/static/index.html`**

Find `<body>` and insert immediately after it (before the next element):
```html
<script>(function(){var t=localStorage.getItem('theme');if(t==='light')document.documentElement.setAttribute('data-theme','light');})()</script>
```

- [ ] **Step 2: Add home screen toggle button in `ui/static/index.html`**

Find `<div class="container" id="home-container">` and add the toggle button as its first child:
```html
<button class="theme-toggle-btn theme-toggle-home" onclick="toggleTheme()"><i data-lucide="sun" class="nav-icon"></i></button>
```

- [ ] **Step 3: Add toggle button to sidebar footer in `ui/static/index.html`**

Find the sidebar footer block. It currently contains:
```html
            <div class="sidebar-footer">
                <button class="nav-item" onclick="showTab('settings', this)"><i data-lucide="settings" class="nav-icon"></i> Settings</button>
            </div>
```

Replace with:
```html
            <div class="sidebar-footer">
                <div style="display:flex; align-items:center;">
                    <button class="nav-item" style="flex:1" onclick="showTab('settings', this)"><i data-lucide="settings" class="nav-icon"></i> Settings</button>
                    <button class="theme-toggle-btn" onclick="toggleTheme()"><i data-lucide="sun" class="nav-icon"></i></button>
                </div>
            </div>
```

- [ ] **Step 4: Verify**

Start the web server: `cd /Users/jennasmith/Desktop/bitcoinarmory && python3 ui/app.py`

Open `http://localhost:5000` in a browser. Confirm:
- Sun icon visible in sidebar footer
- Sun icon visible in top-right corner on home screen
- Both icons are present and correctly sized

- [ ] **Step 5: Commit**

```bash
git add ui/static/index.html
git commit -m "feat: mirror theme toggle HTML to web UI"
```

---

### Task 7: Mirror JS to web UI

**Files:**
- Modify: `ui/static/app.js`

The web UI `app.js` has its own `DOMContentLoaded` at line 14 and its own transaction rendering around line 800–843. The structure differs slightly from the Tauri version.

- [ ] **Step 1: Add `applyTheme` and `toggleTheme` to `ui/static/app.js`**

Add after the opening variable declarations (near the top, before `document.addEventListener('DOMContentLoaded', ...)`):

```javascript
function applyTheme(theme) {
    if (theme === 'light') {
        document.documentElement.setAttribute('data-theme', 'light');
    } else {
        document.documentElement.removeAttribute('data-theme');
    }
    localStorage.setItem('theme', theme);
    document.querySelectorAll('.theme-toggle-btn').forEach(btn => {
        btn.innerHTML = `<i data-lucide="${theme === 'light' ? 'moon' : 'sun'}" class="nav-icon"></i>`;
        lucide.createIcons({ nodes: [btn], attrs: { 'stroke-width': '1.5' } });
    });
}

function toggleTheme() {
    applyTheme(document.documentElement.getAttribute('data-theme') === 'light' ? 'dark' : 'light');
}
```

- [ ] **Step 2: Call `applyTheme` in `DOMContentLoaded` in `ui/static/app.js`**

The current `DOMContentLoaded` at line 14 is:
```javascript
document.addEventListener('DOMContentLoaded', () => {
    lucide.createIcons({ attrs: { 'stroke-width': '1.5' } });
    const firstPanel = document.querySelector('.panel.active');
    const pt = document.getElementById('page-title');
    if (pt && firstPanel) {
        const h2 = firstPanel.querySelector('h2');
        if (h2) pt.textContent = h2.textContent;
    }
    checkStatus();
    setInterval(checkStatus, 30000);
    showOnlineHome();
});
```

Add `applyTheme(localStorage.getItem('theme') || 'dark');` after `lucide.createIcons(...)`:

```javascript
document.addEventListener('DOMContentLoaded', () => {
    lucide.createIcons({ attrs: { 'stroke-width': '1.5' } });
    applyTheme(localStorage.getItem('theme') || 'dark');
    const firstPanel = document.querySelector('.panel.active');
    const pt = document.getElementById('page-title');
    if (pt && firstPanel) {
        const h2 = firstPanel.querySelector('h2');
        if (h2) pt.textContent = h2.textContent;
    }
    checkStatus();
    setInterval(checkStatus, 30000);
    showOnlineHome();
});
```

- [ ] **Step 3: Add `.tx-amount-sent` class to sent amounts in `ui/static/app.js`**

Find the transaction amount `<td>` around line 838:
```javascript
                    <td style="font-family:var(--mono)">${sign}${amount.toLocaleString()} sats</td>
```

Change to:
```javascript
                    <td class="${tx.category === 'send' ? 'tx-amount-sent' : ''}" style="font-family:var(--mono)">${sign}${amount.toLocaleString()} sats</td>
```

- [ ] **Step 4: Full end-to-end test of web UI**

Run: `python3 ui/app.py`

Open `http://localhost:5000`. Verify:
1. Toggle on home screen switches theme — page goes light, icon becomes moon
2. Reload in light mode — opens directly in light mode (no dark flash)
3. Log into a wallet and toggle in the sidebar footer — switches theme
4. Navigate to Transactions — sent amounts appear in red in light mode
5. Navigate to Addresses — change badge appears in blue in light mode
6. Open the Watch-only info panel — the info alert shows in blue in light mode

- [ ] **Step 5: Commit**

```bash
git add ui/static/app.js
git commit -m "feat: mirror theme toggle JS to web UI"
```
