A dark theme carrying ihasmail.org's palette — teal-navy rather than the blue-slate of the plain dark theme, with the orange the logo's cat is drawn in doing the work of the star and the warning colour.
The values are the site's own, read out of its stylesheet rather than picked by eye:
A theme, not an accent — it changes backgrounds, borders and text, which an accent can't.
It rides on data-theme="dark" and adds data-palette="ihasmail", so the eleven dark-only rules further down the stylesheet keep applying without being duplicated for a second dark theme.
Specificity then does deliberate work: the palette block is 0,2,0, the accent variants are 0,3,0, so a chosen accent still wins over it — and because the default accent (teal) has no rule of its own, ihasmail.org's accent is what shows until someone picks another. Verified: with accent=blue, --accent became #60a5fa while --bg stayed #0d2430.
Default
It's what a new account starts on. Only a default — a stored theme always wins, which leaves everyone already using ihasmail exactly where they are, since the theme is saved whether or not they deliberately picked it. Tested specifically.
The toggle now remembers
The top-bar toggle went to light from anything dark, and back to plain dark — quietly moving an ihasmail user onto a theme they never chose, in two clicks, with nothing to say what happened. It did the same to match system, which it couldn't restore at all; the comment above it conceded as much and sent people to Settings.
lastDarkTheme now holds whichever non-light theme was last chosen, and the toggle returns to that. The remembering lives in update() — the single path every way of setting a theme goes through, so a fourth way to choose one can't forget to record it. Light never overwrites it, being the side toggled away from. The label follows too: "Switch to the ihasmail theme", "Switch to your system theme".
A bug found on the way
theme-color had two meta tags, both with media attributes, while applyTheme selects :not([media]) — so it matched neither and the browser chrome had never followed the chosen theme at all, only what the OS preferred. One tag now, updated from JS, starting at the default theme's background so the first paint is right too.
Verified in a browser, not just built
check
result
applied palette
every variable exactly ihasmail.org's
accent override
#60a5fa accent, #0d2430 background
switching away
data-palette removed for light and dark
theme-color
#0d2430 / #ffffff / #0b1220 per theme
fresh profile
boots straight into ihasmail
toggle round trip
ihasmail → light → ihasmail
toggle round trip
system → light → system
contrast, measured
text 14.5:1, muted 8.6:1, faint 6.4:1, accent 8.0:1, link 9.8:1, star 7.9:1 — all AA or better
241 web + 75 server tests, typecheck and build clean.
A dark theme carrying ihasmail.org's palette — teal-navy rather than the blue-slate of the plain dark theme, with the orange the logo's cat is drawn in doing the work of the star and the warning colour.
The values are the site's own, **read out of its stylesheet** rather than picked by eye:
| ihasmail.org | → | ihasmail |
|---|---|---|
| `--bg #0d2430` | | `--bg` |
| `--surface #12303e` / `--surface-raised #163a4a` | | `--bg-elev` / `--unread-bg` |
| `--text #eaf6f6` / `--text-muted #a3c3cb` / `--text-faint #86aab4` | | `--fg` / `--fg-muted` / `--fg-faint` |
| `--accent #46cac3` / `--accent-hot #6fdcd6` / `--on-accent #062028` | | `--accent` / `--link` / `--accent-fg` |
| `--warm #f9a34b` | | `--star`, `--warn` |
## How it composes
A **theme**, not an accent — it changes backgrounds, borders and text, which an accent can't.
It rides on `data-theme="dark"` and adds `data-palette="ihasmail"`, so the eleven dark-only rules further down the stylesheet keep applying without being duplicated for a second dark theme.
Specificity then does deliberate work: the palette block is `0,2,0`, the accent variants are `0,3,0`, so **a chosen accent still wins over it** — and because the default accent (`teal`) has no rule of its own, ihasmail.org's accent is what shows until someone picks another. Verified: with `accent=blue`, `--accent` became `#60a5fa` while `--bg` stayed `#0d2430`.
## Default
It's what a new account starts on. Only a default — a stored theme always wins, which leaves **everyone already using ihasmail exactly where they are**, since the theme is saved whether or not they deliberately picked it. Tested specifically.
## The toggle now remembers
The top-bar toggle went to light from anything dark, and back to plain `dark` — quietly moving an ihasmail user onto a theme they never chose, in two clicks, with nothing to say what happened. It did the same to `match system`, which it couldn't restore at all; the comment above it conceded as much and sent people to Settings.
`lastDarkTheme` now holds whichever non-light theme was last chosen, and the toggle returns to that. The remembering lives in `update()` — the single path every way of setting a theme goes through, so a fourth way to choose one can't forget to record it. Light never overwrites it, being the side toggled away from. The label follows too: *"Switch to the ihasmail theme"*, *"Switch to your system theme"*.
## A bug found on the way
`theme-color` had **two** meta tags, both with `media` attributes, while `applyTheme` selects `:not([media])` — so it matched neither and the browser chrome had never followed the chosen theme at all, only what the OS preferred. One tag now, updated from JS, starting at the default theme's background so the first paint is right too.
## Verified in a browser, not just built
| check | result |
|---|---|
| applied palette | every variable exactly ihasmail.org's |
| accent override | `#60a5fa` accent, `#0d2430` background |
| switching away | `data-palette` removed for light and dark |
| `theme-color` | `#0d2430` / `#ffffff` / `#0b1220` per theme |
| fresh profile | boots straight into ihasmail |
| toggle round trip | ihasmail → light → **ihasmail** |
| toggle round trip | system → light → **system** |
| contrast, measured | text 14.5:1, muted 8.6:1, faint 6.4:1, accent 8.0:1, link 9.8:1, star 7.9:1 — all AA or better |
241 web + 75 server tests, typecheck and build clean.
**Merged** 2026-08-26 as coffey-labs/ihasmail@34eedfa9afe9
<sub>Rebuilt from: git history, session transcript.</sub>
This repo is archived. You cannot comment on issues.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
A dark theme carrying ihasmail.org's palette — teal-navy rather than the blue-slate of the plain dark theme, with the orange the logo's cat is drawn in doing the work of the star and the warning colour.
The values are the site's own, read out of its stylesheet rather than picked by eye:
--bg #0d2430--bg--surface #12303e/--surface-raised #163a4a--bg-elev/--unread-bg--text #eaf6f6/--text-muted #a3c3cb/--text-faint #86aab4--fg/--fg-muted/--fg-faint--accent #46cac3/--accent-hot #6fdcd6/--on-accent #062028--accent/--link/--accent-fg--warm #f9a34b--star,--warnHow it composes
A theme, not an accent — it changes backgrounds, borders and text, which an accent can't.
It rides on
data-theme="dark"and addsdata-palette="ihasmail", so the eleven dark-only rules further down the stylesheet keep applying without being duplicated for a second dark theme.Specificity then does deliberate work: the palette block is
0,2,0, the accent variants are0,3,0, so a chosen accent still wins over it — and because the default accent (teal) has no rule of its own, ihasmail.org's accent is what shows until someone picks another. Verified: withaccent=blue,--accentbecame#60a5fawhile--bgstayed#0d2430.Default
It's what a new account starts on. Only a default — a stored theme always wins, which leaves everyone already using ihasmail exactly where they are, since the theme is saved whether or not they deliberately picked it. Tested specifically.
The toggle now remembers
The top-bar toggle went to light from anything dark, and back to plain
dark— quietly moving an ihasmail user onto a theme they never chose, in two clicks, with nothing to say what happened. It did the same tomatch system, which it couldn't restore at all; the comment above it conceded as much and sent people to Settings.lastDarkThemenow holds whichever non-light theme was last chosen, and the toggle returns to that. The remembering lives inupdate()— the single path every way of setting a theme goes through, so a fourth way to choose one can't forget to record it. Light never overwrites it, being the side toggled away from. The label follows too: "Switch to the ihasmail theme", "Switch to your system theme".A bug found on the way
theme-colorhad two meta tags, both withmediaattributes, whileapplyThemeselects:not([media])— so it matched neither and the browser chrome had never followed the chosen theme at all, only what the OS preferred. One tag now, updated from JS, starting at the default theme's background so the first paint is right too.Verified in a browser, not just built
#60a5faaccent,#0d2430backgrounddata-paletteremoved for light and darktheme-color#0d2430/#ffffff/#0b1220per theme241 web + 75 server tests, typecheck and build clean.
Merged 2026-08-26 as coffey-labs/ihasmail@34eedfa9af
Rebuilt from: git history, session transcript.