Skip to content

Feature: nine themes that imitate a physical medium, plus a readability floor for every theme - #67

Merged
DevMando merged 1 commit into
mainfrom
feature/media-themes-and-readability
Sep 10, 2026
Merged

DevMando merged 1 commit into
mainfrom
feature/media-themes-and-readability

Conversation

@DevMando

Copy link
Copy Markdown
Owner

Summary

Adds nine themes that imitate a physical display or printing process, fixes secondary text that was too faint to read in half the existing themes, and gives the MandoCode wordmark its own typeface. The theme count goes from sixteen to twenty-five.

Why this matters

Faint text was a real accessibility problem, not a taste one. Timestamps, file paths, status lines and the explanatory text under headings were below the standard contrast threshold in eight of sixteen themes — in the worst cases at roughly half the required contrast. Anyone reading those themes in bright light, on a laptop screen, or with less than perfect vision was losing that text entirely.

The novelty themes had proven popular but were only skin deep. The existing e-ink and CRT themes were the two most distinctive things in the picker, and both worked because they reproduced how their medium actually behaves rather than only borrowing its colours. This extends that idea to seven more media and one that had never been covered.

What changed

Readability

  • Secondary text now clears the accessibility floor in every theme. The palettes are untouched — several are faithful to well-known upstream schemes whose comment colours are famously faint — and the value is lifted only at the point of use, only when it falls short, and only as far as it needs to go. It blends toward each theme's own text colour, so a corrected palette still looks like itself rather than drifting toward grey. Themes that were already readable come through byte for byte identical.
  • Themes viewed through an overlay are held to a higher bar. Every other contrast figure in the app compares a colour against what sits behind it. The CRT's scanlines are painted in front of the text, so its palette's own numbers overstate what a reader actually gets. Body text there has enormous headroom and never notices; the faintest text does.
  • The CRT glow follows the colour of the text it surrounds. It was fixed to one blue, so red error text carried a blue halo. On a real tube the glow is the phosphor being excited, so errors now glow red and successful output green. Code blocks keep a tighter glow, since a full halo turns syntax highlighting into a smear.

New themes

Nine, each built around what its medium physically does rather than what it looks like:

  • Monochrome amber terminal — one phosphor, so syntax highlighting has to carry meaning through brightness and weight instead of colour.
  • Vacuum-fluorescent panel — emissive like a tube but with no beam, so the glow has a hard edge rather than a halo, behind smoked glass.
  • Vector scope — a steered beam, so no scanlines at all, just the fading trace of where it has already been.
  • Passive-matrix LCD — liquid crystal twists light rather than emitting it, so nothing glows; it ghosts instead, and nothing is ever truly black.
  • Split-flap departure board — a flap carries one printed character, so the board can only show uppercase, with the hinge seam running through every letter.
  • Cyanotype blueprint — a negative, so emphasis is a whiter stroke rather than a heavier one.
  • Two-ink risograph — two drums, one pass each, misregistered by a pixel.
  • Continuous-feed printer paper — bands locked to the text's own line grid, sprocket margins down both edges.
  • Microfiche — dust and scratches sit on the reader's glass rather than the film, so they hold still while the page scrolls underneath.

The list is also reordered so that neighbouring themes share a mechanism rather than merely a colour, which keeps the picker skimmable at twenty-five entries.

Background images

Themes that imitate a medium now also process a chat background image the way that medium would have reproduced it. On by default, with a switch in Settings → Appearance to keep the picture in full colour.

The default is deliberate: someone who would enjoy the effect would never go hunting for a switch to turn it on, whereas someone who wants their picture untouched finds the toggle immediately. It affects only those themes and only when a background is set, so for most users it does nothing at all. Backgrounds deliberately do not glow — on real hardware the display elements emit light and the glass behind them does not, and a glowing photograph is the one thing that would break the illusion rather than deepen it.

Wordmark

The name in the top-left is now set in Permanent Marker, bundled with the app rather than fetched from a font service, so it renders identically offline and its licence ships alongside it. It takes each theme's accent colour, so it re-inks itself as themes change.

Its size is a contrast decision more than a typographic one. The wordmark paints in each theme's brand accent, four of which fall below the normal-text contrast threshold. At its current size it qualifies as large text, where the threshold is lower and every shipped theme clears it comfortably. Correcting the accents themselves was the alternative and the wrong one — one of those four is the exact Visual Studio blue that theme exists to reproduce.

Scope and risk

Medium, and almost entirely visual.

  • Every theme is repainted in the sense that secondary text is now computed rather than read straight from the palette. Eight themes change; eight are provably unchanged, with a test asserting exactly that.
  • Nine new CSS surfaces are each scoped to their own attribute, so a theme without that attribute cannot be affected. Everything they draw is static — fixed gradients, one paint, no animation — following the existing rule in that file about never introducing a continuous repaint.
  • A binary asset now ships. .gitattributes is added and scoped to fonts only. A repo-wide line-ending policy would rewrite every existing file and deserves its own change; this guarantees only the thing that would silently corrupt a font.
  • The submodule pin is deliberately untouched by this branch.

Verification

Builds clean, 0 warnings and 0 errors. Full Desktop suite passes — 423 of 423, including a per-theme sweep that fails by name if any shipped theme's secondary text falls below the floor, and asserts that already-readable palettes are returned unmodified.

All nine themes, the background toggle, and the wordmark were exercised by hand during development, and three issues found that way are fixed in this branch: printer-paper sprocket holes that were filling the whole pane instead of the margins, a vector-scope glow that was genuinely painful to read, and the CRT's fixed-colour bloom.

Not covered by tests: the CSS surfaces and the wordmark are rendered in a WebView and in XAML respectively, neither reachable from the test project. A reviewer wanting to spot-check should look at Solarized Light and Visual Studio Dark, which have the lowest wordmark contrast of the twenty-five, and at Dracula or One Dark Pro, where the readability lift is most visible.

Three strands, all in the theme system.

READABILITY. Secondary text sat below the WCAG AA floor in half the shipped
themes. Most of those are faithful — Dracula and One Dark ship famously
faint comment colours upstream — so the palettes stay as authored and
UiTheme.ReadableDim lifts the value instead, blending toward that theme's own
text so a nudged palette stays its own colour rather than drifting grey. It
takes the FIRST step that clears, because a palette should be nudged into
legibility, not flattened into it. A theme already above the floor comes back
byte-identical.

Themes read through an overlay are held higher. Every other contrast figure
in the app compares a colour against what is BEHIND it; the CRT's scanlines
are painted in FRONT, so a tube palette's measured contrast is not what a
reader gets. Body text there has huge headroom and never notices, dim text
does.

UiTheme moves to its own file so the shipped palettes are reachable from
tests without dragging WinUI along, and the contrast arithmetic moves to
ColorMath so there is one implementation. The sweep asserts every theme by
name, which is what stops the NEXT theme landing below the floor.

NINE MEDIUM THEMES. Each reproduces how its medium actually made an image
rather than borrowing its colours: the LCD ghosts rather than glows because
liquid crystal twists light instead of emitting it; the split-flap board can
only show uppercase because a flap carries one printed character; the
cyanotype is a negative, so emphasis is a whiter stroke, not a heavier one.
The CRT's bloom now takes the glyph's own colour — it was hardcoded blue, so
red errors carried a blue halo, the one place that overlay disobeyed its own
physics.

Background images get the same treatment behind an Appearance toggle,
defaulted on: someone who would enjoy the effect would never go looking for a
switch to enable it, while someone who wants their picture untouched finds
the toggle immediately. Deliberately no glow on the background — on real
hardware the segments emit, the glass behind them does not.

WORDMARK. Permanent Marker, bundled rather than fetched, for the same reason
the web assets are: a CDN font puts a network dependency on the app's own
branding. 24px is a contrast decision, not a typographic one — the mark
paints in each theme's accent, four of which fall under 4.5:1, and at 24px
the bar drops to the large-text 3:1 that every theme clears. Lifting those
accents was the other fix and the wrong one: #007ACC IS the Visual Studio
blue.

.gitattributes is scoped to fonts only. A repo-wide eol policy would rewrite
every existing file, which is its own change; this guarantees the one thing
that would silently corrupt an asset.
@DevMando
DevMando merged commit f207940 into main Sep 10, 2026
1 check passed
@DevMando
DevMando deleted the feature/media-themes-and-readability branch September 11, 2026 03:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant