From 54c03beec37efa162ffd232f506edbe7714ebb14 Mon Sep 17 00:00:00 2001 From: Russell Ballestrini Date: Mon, 1 Jun 2026 21:58:01 -0400 Subject: [PATCH] =?UTF-8?q?zebra-spaces:=20real=20dark=20mode=20=E2=80=94?= =?UTF-8?q?=20explicit=20overrides,=20pure=20black=20bg,=20low=20light=20e?= =?UTF-8?q?mission?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- web/zebra-spaces.html | 82 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 13 deletions(-) diff --git a/web/zebra-spaces.html b/web/zebra-spaces.html index 170dfc7..401c837 100644 --- a/web/zebra-spaces.html +++ b/web/zebra-spaces.html @@ -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');