zebra-spaces: real dark mode — explicit overrides, pure black bg, low light emission

Replaced the filter:invert approach (which produced muddy mid-tones and
left the html canvas + scrollbar areas flashing white) with explicit
.theme-dark overrides for every painted surface:

- bg pure #000 on html + body — no light emission outside content
- text #ccc (dim, easy on eyes; not glaring #fff)
- borders #222-#444 (visible but not loud)
- inputs/textarea #0a0a0a — sit a hair above pure black
- buttons inverted: button.invert (primary) is #ccc-on-black,
  regular buttons are #000-with-#ccc-text-and-#444-border
- badges, dots, meters re-coloured for dark contrast
- latency green/yellow/red shifted toward higher-luminance variants
  so they stay readable on black
- log + notice banners get dark-tinted backgrounds matching their kind
- video/camera tiles unchanged — they were already dark and look fine

Video pixels never get filtered now, so screen-share + camera streams
render their actual colours instead of being inverted.
This commit is contained in:
Russell Ballestrini 2026-06-01 21:58:01 -04:00
parent b32661ce50
commit 54c03beec3
No known key found for this signature in database

View file

@ -16,17 +16,73 @@
font-family: monospace; background: #fff; color: #000;
padding: 1rem 1.5rem; max-width: none; margin: 0 auto;
}
/* Dark mode = literal invert. CSS filter flips every painted colour on
* the page in one shot, then hue-rotate corrects what would otherwise
* read as cyan instead of orange / magenta instead of green. Re-invert
* the things we want to look RIGHT instead of merely opposite: video
* tiles, the QR canvas, and any inline raster. */
html.theme-dark body { filter: invert(1) hue-rotate(180deg); background: #fff; }
html.theme-dark video,
html.theme-dark canvas,
html.theme-dark img { filter: invert(1) hue-rotate(180deg); }
/* the theme toggle button itself sits inside the inverted area, so
* its own colours flip automatically — no extra rule needed */
/* Dark mode = pure black canvas, dim text, low total light emission.
* Explicit overrides instead of filter:invert so the page looks
* intentional in both modes rather than mathematically flipped. */
html.theme-dark { background: #000; }
html.theme-dark body { background: #000; color: #ccc; }
html.theme-dark a { color: #9cf; }
html.theme-dark .sub, html.theme-dark .sub a, html.theme-dark .note,
html.theme-dark .status-line { color: #888; }
html.theme-dark .timeline { border-right-color: #222; }
html.theme-dark .timeline-frame { background: #000; border-color: #222; }
/* buttons + inputs */
html.theme-dark button,
html.theme-dark .game-tabs button,
html.theme-dark .theme-toggle {
background: #000; color: #ccc; border-color: #444;
}
html.theme-dark button:hover:not(:disabled),
html.theme-dark .game-tabs button:hover:not(.active),
html.theme-dark .theme-toggle:hover { background: #1a1a1a; }
html.theme-dark button.invert { background: #ccc; color: #000; border-color: #ccc; }
html.theme-dark button.invert:hover:not(:disabled) { background: #999; }
html.theme-dark .game-tabs button.active { background: #ccc; color: #000; border-color: #ccc; }
html.theme-dark input[type=text],
html.theme-dark input[type=password],
html.theme-dark textarea,
html.theme-dark select {
background: #0a0a0a; color: #ccc; border-color: #333;
}
html.theme-dark .dot { background: #000; border-color: #444; }
html.theme-dark .dot.ok { background: #0a0; border-color: #0a0; }
html.theme-dark .meter { background: #000; border-color: #444; }
html.theme-dark .meter-fill { background: #ccc; }
/* badges */
html.theme-dark .badge.host { background: #ccc; color: #000; border-color: #ccc; }
html.theme-dark .badge.cohost { background: #666; color: #000; border-color: #666; }
html.theme-dark .badge.speaker { background: #000; color: #ccc; border-color: #ccc; }
html.theme-dark .badge.listener{ background: #000; color: #888; border-color: #444; }
html.theme-dark .pub-short { color: #777; }
html.theme-dark .handle .me { color: #6c6; }
html.theme-dark .raised { color: #f66; }
/* log */
html.theme-dark .log { background: #050505; border-color: #333; }
html.theme-dark .log-line .ts { color: #666; }
html.theme-dark .log-line.err { color: #f66; }
html.theme-dark .status-line.ok { color: #6c6; }
html.theme-dark .status-line.err { color: #f66; }
/* notice banners */
html.theme-dark .notice-banner { background: #1a1a00; border-color: #553; color: #ccc; }
html.theme-dark .notice-banner.warn { background: #1a0000; border-color: #500; color: #f66; }
html.theme-dark .notice-banner.info { background: #001a00; border-color: #050; color: #6c6; }
/* latency rows */
html.theme-dark .lat-row { border-bottom-color: #1a1a1a; }
html.theme-dark .lat-row .lat-name { color: #aaa; }
html.theme-dark .lat-row .lat-loss::before,
html.theme-dark .lat-row .lat-jit::before { color: #666; }
html.theme-dark .lat-row .lat-path { color: #666; }
html.theme-dark .lat-row.lat-good .lat-rtt, html.theme-dark .lat-row.lat-good .lat-loss, html.theme-dark .lat-row.lat-good .lat-jit { color: #6c6; }
html.theme-dark .lat-row.lat-mid .lat-rtt, html.theme-dark .lat-row.lat-mid .lat-loss, html.theme-dark .lat-row.lat-mid .lat-jit { color: #ec0; }
html.theme-dark .lat-row.lat-bad .lat-rtt, html.theme-dark .lat-row.lat-bad .lat-loss, html.theme-dark .lat-row.lat-bad .lat-jit { color: #f66; }
html.theme-dark .lat-row.lat-na .lat-rtt, html.theme-dark .lat-row.lat-na .lat-loss, html.theme-dark .lat-row.lat-na .lat-jit { color: #555; }
/* vault */
html.theme-dark .vault-panel { border-color: #444; }
/* page-integrity footer */
html.theme-dark footer { color: #555 !important; }
html.theme-dark footer span { color: #555 !important; }
html.theme-dark footer a { color: #777 !important; }
.theme-toggle {
position: fixed; top: 0.6rem; right: 0.8rem; z-index: 9999;
background: #fff; color: #000; border: 1px solid #000;
@ -2118,8 +2174,8 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');
<footer style="margin:2.2rem auto 0;font-size:0.65rem;color:#999;line-height:1.7;word-break:break-all;font-family:monospace">
<span id="pi-seal" style="color:#777;cursor:default;user-select:none" title="">page integrity</span> &nbsp;·&nbsp; built <span class="stamp-date">2026-06-02</span><br>
md5 <span class="stamp-md5">c0f614a2ac3011c2c843104ec7d7cb4c</span><br>
sha256 <span class="stamp-sha">d75b0a8a21dcd9d1b3d8b5353283edd1a901b3712e318b9d3b6c8a0dd0cfc30a</span><br>
md5 <span class="stamp-md5">4eb2aa5b98de772e0982dce36a4e84a1</span><br>
sha256 <span class="stamp-sha">149cc312ddf22b2cc2963de39bbfd3e6413e42073b31acd759b73dddd19451dc</span><br>
<span style="color:#bbb">hashes are of this page with these two fields zeroed — to verify, blank them and re-hash</span><br>
<span style="color:#bbb">one self-contained file — <strong>save a copy</strong> and verify against these hashes; point at your own servers with ?signal= and ?turncred=, or <a href="host-your-own.html" style="color:#999">host your own community</a></span>
</footer>