---
title: Supermail email rendering — instant open + dark mode
---
# Supermail email rendering — instant open + dark mode

## What it is

How Supermail (the Superhuman-style email client built into Omniscio) turns a message
into pixels: opening an email is near-instant, and in dark mode the emails themselves
render dark instead of blasting a white rectangle at you.

### What you see

- **Opening an email is instant.** Clicking a message in the list paints the email
  immediately — no spinner, no "loading" flash — because the app does the heavy work
  (cleaning + parsing the email's HTML) **ahead of time**, in the background, for the
  messages you're likely to open next.
- **Dark mode for emails (Carbon theme).** When Supermail is in its dark theme
  ("Carbon"), emails render dark:
  - **Simple emails** (plain notes, basic replies) already inherit the dark theme — dark
    background, light text.
  - **Designed emails** (newsletters, marketing, branded HTML) are shown dark with a
    smart color-invert that keeps photos, logos, and signatures true-color (they're not
    turned into negatives).
  - **Emails that would look wrong inverted** — ones the sender already designed on a
    dark background — are **auto-detected and left on their original canvas**, so they
    don't get flipped to a glaring light block.
  - Every inverted email has a small **"Show original (light)"** link at the bottom of
    the message; click it to see that email exactly as the sender built it (and "Show in
    dark" to flip back). It resets when you collapse the message.
- **Light mode ("Snow") is unchanged** — emails render exactly as before. The dark
  treatment only applies when the app is in dark mode.
- **A broken image shows its caption, not a blank.** If a remote image in an email can't
  be loaded — the sender's image URL was deleted, moved, rate-limited, or blocked — the
  reading pane shows a small "_caption_ · View original" chip where the image would be,
  instead of a mysterious empty gap, so you know something was there and can open the
  original in your browser. Invisible tracking pixels and embedded (attachment) images
  are unaffected — they keep their clean, hidden-on-failure behavior.

## Where to find it

Nothing to open: this is how Supermail's reading pane paints a message. Supermail itself is the **Supermail** sidebar entry.

## How it behaves

### Why it's fast (the mechanism)

An email body has to be **security-cleaned** (DOMPurify strips scripts / dangerous
markup), **parsed**, and have its quoted-reply section detected before it can render.
Doing all that on the click was the lag. Two changes remove it:

1. **Precompute off the click path.** Each message's cleaned/parsed result — the
   sanitized HTML for the frame, the sanitized inline HTML, the quote detection, and the
   dark-invert decision — is computed **once** and cached, keyed to that exact message
   (by id, validated by the body text so it can never serve the wrong email's content).
   The compute is warmed while the app is idle for the messages you hover, the
   previous/next message in a thread, and the first handful of visible inbox rows — so by
   the time you click, it's usually already done and the open is just a paint.
2. **No double-cleaning.** The email frame used to re-clean the HTML a second time on its
   own; now it receives the already-cleaned HTML and only frames + optionally
   dark-inverts it. That removes a whole redundant sanitize per open.

Warming is **bounded** (a capped number of rows, only each thread's newest message),
**deduplicated** (already-cached emails are skipped), and **idle-scheduled**, so it
speeds you up without ever competing with what you're doing — Omniscio's rule is to slow
the background work, never the user.

### How dark mode works (the technique)

Email HTML assumes a light background, so you can't just drop it on a dark canvas — black
text would vanish. Instead the designed email is rendered as the sender built it (light)
and the **final pixels are inverted**: `invert(1)` swaps light↔dark and
`hue-rotate(180deg)` brings colors back to roughly their original tone. Images, video,
SVG, and background-image elements are then **re-inverted** so photos and logos stay
true-color. It's pure CSS, so it works inside the email's locked-down (script-less)
sandbox. This is the same "smart invert" the Omniscio **Gmail** viewer already uses.

The auto-skip heuristic is deliberately conservative: it only leaves an email light when
that email clearly declares a **dark canvas** (a dark background on the body or its
full-width wrapper). For everything else it inverts, and the per-email "Show original"
toggle is the escape hatch for the subjective cases a rule can't judge.

Supermail is its own isolated app bundle, so it reads dark from its **own** theme (the
`theme-carbon` class), not Omniscio's main `.dark` class, and the invert CSS is copied
into the plugin rather than imported across the bundle boundary.

### Scope & limits

- Applies to the Supermail reading pane only.
- Designed emails render inside a sandboxed iframe; their _first_ open snaps to the right
  size with a fast content fill, and re-opens are instant (a height cache). Simple emails
  are synchronous and effectively instant once warmed.
- The dark-invert is best-effort: an email with an unusual background (a CSS gradient, or
  a mixed dark/light design) can look slightly off — that's what the auto-skip + the
  manual toggle are for.

## For agents

### Code / contract

- Behavior lock: `.claude/memory/contracts/supermail-email-render-contract.md` (its first seven
  invariants, `light-mode-byte-identical` through `security-boundary-preserved`).
- Broken remote images (inline reading pane): `conversation/broken-image-fallback.ts` renders
  the caption + "View original" chip on load failure; behavior lock in
  `.claude/memory/contracts/supermail-inline-images-contract.md` (`failed-image-sweep-fallback`).
- Key files (under `src/plugins/supermail/ui/src/features/`): `conversation/email-render-cache.ts`
  (precompute + cache + idle warm), `conversation/email-dark.ts` (invert CSS + auto-skip
  heuristic), `conversation/email-body-frame.tsx` (the sandboxed frame), `conversation/message-view.tsx`
  (wires it together + the toggle), `theme/use-is-carbon.ts` (the dark signal).

## Related

Supermail itself covers the client this rendering serves, and the reading-view page covers the focus mode and toolbar around the message.
