openvibers/openvibe.live Commits

Light themes: toasts, the call card and the studio take the theme's card; over-video words stay light (#591)

OP OpenVibers committed 10 days ago · c5df9ffabd · 6 files, +43 −20

* Light themes: toasts, the call card and the studio take the theme's card; over-video words stay light

A Daylight pass (a contrast scan of the main pages plus screenshots) found boxes with a
hard-coded dark background and the theme's text colour, so on a light theme they were
dark text on a dark box: every toast, the incoming-call card, the studio's panel and
modal. They take the theme's own card (--bg-card, --border) now and look as before on
dark themes. Surfaces that cover a video or a picture stay dark in every theme, so their
words are set light: the adult-content gate's heading and text, the paste chip's glyph.
critical-selectors.json regenerated (scripts/perf/critical-css.js).

* Perf budget: js 301 KB brotli (measured 300.1 on main after Live #589 and openvibe-shared 4.107.3)

Changes

ddiff --git a/public/css/broadcast.css b/public/css/broadcast.css
iindex 9819d9e5..bbe276b2 100644
---- a/public/css/broadcast.css
++++ b/public/css/broadcast.css
@@@ -95,8 +95,8 @@
}
.bc-modal-content {
-- background: rgba(22,22,26,0.95);
-- border: 1px solid rgba(255,255,255,0.08);
++ background: var(--bg-card);
++ border: 1px solid var(--border);
border-radius: 16px;
max-width: 1200px;
width: 100%;
ddiff --git a/public/css/critical-selectors.json b/public/css/critical-selectors.json
iindex 83318b9a..f89e623d 100644
---- a/public/css/critical-selectors.json
++++ b/public/css/critical-selectors.json
@@@ -18,6 +18,7 @@
"#app",
"#openvibe-bell-mount",
"#page-home",
++ "#page-home .container > .section-header:first-child",
"#page-home .hero",
"#page-home.page",
"#stream-grid-live .empty-state",
@@@ -85,8 +86,6 @@
".chat-badge-streamer",
".chat-badge[data-tip]::after",
".chat-badge[data-tip]::before",
-- ".chat-conn-status",
-- ".chat-conn-status[data-state=\"connected\"]",
".chat-crossfeed-badge",
".chat-crossfeed-global",
".chat-crossfeed-stream",
@@@ -191,6 +190,7 @@
".hero-float",
".hero-float img",
".hero-float--clip .hero-float-badge",
++ ".hero-float--moment .hero-float-badge",
".hero-float--paste .hero-float-badge",
".hero-float--vod .hero-float-badge",
".hero-float-body",
@@@ -276,6 +276,7 @@
".network-hub-header > i",
".network-hub-header h3",
".network-hub-header p",
++ ".off-cyc-chip.active",
".off-cyc-title i",
".off-top-dur",
".off-top-rank",
@@@ -293,12 +294,6 @@
".openvibe-navbar.navbar .openvibe-navbar-links a.ovnav-link.active",
".openvibe-navbar.navbar.ovnav-top",
".ov-comet",
-- ".ov-conn-pill",
-- ".ov-conn-pill .ov-conn-dot",
-- ".ov-conn-pill.is-shown",
-- ".ov-conn-pill[data-state=\"connected\"] .ov-conn-dot",
-- ".ov-conn-pill[data-state=\"reconnecting\"] .ov-conn-dot",
-- ".ov-conn-pill[data-state=\"updating\"] .ov-conn-dot",
".ov-dot",
".ov-glow",
".ov-orbit",
@@@ -306,6 +301,7 @@
".ov-rail",
".ov-rail > .moments-row",
".ov-rail-bar",
++ ".ov-rail-bar > span",
".ov-rail-bar[hidden]",
".ov-rail-btn",
".ov-rail-btn:disabled",
@@@ -313,6 +309,7 @@
".ov-rail-prev",
".ov-rail-track",
".ov-rail-track > *",
++ ".ov-rail.is-scrollable > .ov-rail-track",
".ov-rail:not(.is-end) > .ov-rail-track",
".ov-rail:not(.is-scrollable) > .ov-rail-btn",
".ov-rail:not(.is-start) > .ov-rail-track",
@@@ -353,6 +350,7 @@
".section-header h2 > i:first-child",
".section-header h2 > i:first-child::before",
".section-header::after",
++ ".sgg-title i",
".stream-card",
".stream-card-avatar",
".stream-card-avatar img",
ddiff --git a/public/css/features/broadcast.css b/public/css/features/broadcast.css
iindex 6a1fa4c2..910dc7af 100644
---- a/public/css/features/broadcast.css
++++ b/public/css/features/broadcast.css
@@@ -411,11 +411,11 @@
min-width: 0;
display: flex;
flex-direction: column;
-- border: 1px solid rgba(255,255,255,0.05);
++ border: 1px solid color-mix(in srgb, var(--text-primary) 6%, transparent);
border-radius: 20px;
overflow-x: hidden;
overflow-y: auto;
-- background: rgba(22,22,26,0.72);
++ background: color-mix(in srgb, var(--bg-card) 78%, transparent);
box-shadow: var(--shadow-soft, 0 12px 40px rgba(0,0,0,0.28));
}
ddiff --git a/public/css/style.css b/public/css/style.css
iindex 97fc48e3..8e3e483d 100644
---- a/public/css/style.css
++++ b/public/css/style.css
@@@ -1745,7 +1745,7 @@ a.pulse-card:hover { border-color: var(--accent); transform: translateY(-2px); }
.home-paste-icon {
width: 52px; height: 52px; border-radius: 14px;
background: rgba(13,13,15,0.58); display: flex; align-items: center; justify-content: center;
-- font-size: 1rem; color: var(--text-primary); flex-shrink: 0;
++ font-size: 1rem; color: #fff; flex-shrink: 0;
border: 1px solid rgba(255,255,255,0.08);
backdrop-filter: blur(6px);
}
@@@ -1829,13 +1829,13 @@ a.pulse-card:hover { border-color: var(--accent); transform: translateY(-2px); }
.stream-nsfw-gate-card h2 {
margin: 0;
font-size: clamp(1.3rem, 2.3vw, 1.95rem);
-- color: var(--text-primary);
++ color: #fff; /* the gate covers the video and is dark in every theme */
}
.stream-nsfw-gate-card p {
margin: 0;
max-width: 52ch;
-- color: var(--text-secondary);
++ color: rgba(255, 255, 255, 0.76);
line-height: 1.5;
}
@@@ -4027,9 +4027,10 @@ body :is(.modal-overlay, .bc-ws-confirm-overlay, .bc-modal, .bc-perm-overlay, .b
cursor: pointer;
padding: 10px 14px;
border-radius: 12px;
-- background: rgba(23, 27, 39, 0.88);
++ /* The theme's own card, so a light theme's toast is light with dark text (was navy with dark text, 11-03). */
++ background: color-mix(in srgb, var(--bg-card) 94%, transparent);
color: var(--text-primary);
-- border: 1px solid rgba(255, 255, 255, 0.08);
++ border: 1px solid var(--border);
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.22);
font-size: 0.84rem;
line-height: 1.35;
@@@ -7167,7 +7168,8 @@ textarea.paste-textarea {
.vc-call-toast-card {
pointer-events: auto;
width: min(360px, calc(100vw - 28px));
-- background: rgba(14, 15, 20, 0.95);
++ background: color-mix(in srgb, var(--bg-card) 96%, transparent);
++ color: var(--text-primary);
border: 1px solid color-mix(in srgb, var(--accent) 28%, transparent);
border-radius: 14px;
box-shadow: 0 16px 36px rgba(0, 0, 0, 0.5);
@@@ -7216,7 +7218,7 @@ textarea.paste-textarea {
align-items: center;
gap: 6px;
}
--.vc-call-toast-action:hover { background: rgba(255, 255, 255, 0.13); }
++.vc-call-toast-action:hover { background: color-mix(in srgb, var(--text-primary) 13%, transparent); }
.vc-call-toast-cancel { color: #ffb4b4; }
/* Error shake for form inputs */
ddiff --git a/scripts/perf/check-budgets.js b/scripts/perf/check-budgets.js
iindex 820368cd..c81987de 100644
---- a/scripts/perf/check-budgets.js
++++ b/scripts/perf/check-budgets.js
@@@ -23,7 +23,7 @@ const BUDGETS = {
htmlBrotliKB: 30,
jsFiles: 26, // measured 23 (incl. route scripts for "/")
jsRawKB: 1290, // 1280.1 (2026-11-03: the chat name card shows at once, the logs give up after ten seconds; headroom for openvibe-shared 4.107.3); 1279.2 (2026-11-03: openvibe-shared 4.107.0, open.<tld> brands; the home's reveal scroll listener hooked once); 1278.3 (2026-11-02: openvibe-shared 4.106.2, the balances stack so the site's name reads whole on a phone); 1277.1 (2026-11-02: the home's money four as one 'None yet' chip while all four are zero, open item 135); 1275.2 (2026-11-02: route placeholders in ov-skeleton.js, L52 step 6: a loading route shows its shape, not an empty box); 1268.4 (2026-11-02: openvibe-shared 4.103.0, the puzzle glyph, two-line sidebar rows, boost's fix and eight solids; the 404 offers the channel for a bare /name); 1266.3 (2026-11-02: openvibe-shared 4.95.0, keyboard-reachable scrollers; the phone Pastes rail); 1262.1 (2026-11-02: openvibe-shared 4.94.0, the Audio chip, the go-live card's labels); 1259.8 (2026-11-02: content labels on cards and the player, L1); 1257.5 (2026-11-01: the Catch up rails load by themselves as you swipe, no Load more on a phone); 1254.2 (2026-11-01: openvibe-shared 4.87.0), about 1255 with #534 (feed and card avatars at their size); 1253.8 (2026-11-01: avatars ask Media for their drawn width, ovImgW); 1252.3 (2026-11-01: Following in the topics row, the picked topic remembered); 1250.2 (2026-11-01: topics live now, readable chat names on light themes); 1247.7 openvibe-shared 4.70.0 (2026-11-01: the app bar, busy(), skeletons, view transitions); 1244.3 with openvibe-shared 4.66.0: the mark with depth and motion, ov-fx loaded on request (2026-10-31); 1243.5 with openvibe-shared 4.64.0: the look travels between sites, the Look panel in the menu (2026-10-31); 1242.7 with openvibe-shared 4.59.0: the Pair mark beside the name, set in the brand face, and the ring on page moves (2026-10-31); 1238.8 with the home's featured stream once and the intro closed on phones (2026-10-31); 1237.4 with the home's two more tab blocks on phones (2026-10-30); 1233.9 with the home's Catch up tabs on phones (2026-10-30); 1230.8 with openvibe-shared 4.53.0: the footer's columns fold on phones (2026-10-30); 1227.8 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 1223.5 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); 1215.4 with openvibe-shared 4.43.0 (room.css carries the kit tokens, 4.39.1; the kit's 4.39.0 rules); measured 1203.9 (2026-10-28: openvibe-shared 4.30.0, the bell center: tabs with counts, the Unread filter, thumbnails, swipe, the phone sheet; 4.31.0's ✦ adds about 3 KB); 1187.2 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0: opaque themed toasts held while a menu is open, grouping, priority, System cards and the rich bell panel); 1158.8 (2026-10-28: openvibe-shared 4.25.0, the menu's orb, messages, the phone sheet and auto-hide in the navbar; the messenger opens from the bar)
-- jsBrotliKB: 300, // 299.3 (2026-11-02: openvibe-shared 4.106.2, the balances stack); 298.4 (2026-11-02: route placeholders, L52 step 6); 296.7 (2026-11-02: openvibe-shared 4.103.0 and the 404's channel offer); 296.2 (2026-11-02: openvibe-shared 4.95.0, keyboard-reachable scrollers; the phone Pastes rail); 295.1 (2026-11-02: openvibe-shared 4.94.0, the Audio chip, the go-live card's labels); 294.6 (2026-11-02: content labels on cards and the player, L1); 294.1 (2026-11-01: the Catch up rails load by themselves as you swipe); 292.6 openvibe-shared 4.70.0 (2026-11-01: the app bar, busy(), skeletons, view transitions); 291.1 with openvibe-shared 4.57.1 (the Dock's async token and scope-aware controls, 4.57.0; the tool frame's facts, 4.56.0) (2026-10-31); 290.6 with the home's two more tab blocks on phones (2026-10-30); 289.8 with the home's Catch up tabs on phones (2026-10-30); 288.2 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 287.4 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); measured 283.2 (2026-10-28: openvibe-shared 4.30.0, the bell center as above); 279.6 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0 as above); 273.1 (2026-10-28: openvibe-shared 4.25.0 as above); 270.5 (2026-10-28: openvibe-shared 4.22.0, the navbar's search magnifier with / and Ctrl+K and the More menu; search.js and loading.js load only when used); 269.6 (2026-10-28: openvibe-shared 4.19.0, the account menu's gear and people-group icons inline; 268 on 2026-10-27: openvibe-shared 4.16.0, the folded balance chip, Across OpenVibe with site marks and the icon preload in the navbar); 265.3 (2026-10-27: openvibe-shared 4.15.0, the compact footer opens into the whole one, and the pulse line); 263.3 on 10-23 (openvibe-shared 4.9.0, status text twins in every theme); 262.5 on 10-17 (openvibe-shared 4.4.0, every site in the launcher)
++ jsBrotliKB: 301, // 300.1 (2026-11-03: every api() read gives up after 20 s, Live #589; openvibe-shared 4.107.3); 299.3 (2026-11-02: openvibe-shared 4.106.2, the balances stack); 298.4 (2026-11-02: route placeholders, L52 step 6); 296.7 (2026-11-02: openvibe-shared 4.103.0 and the 404's channel offer); 296.2 (2026-11-02: openvibe-shared 4.95.0, keyboard-reachable scrollers; the phone Pastes rail); 295.1 (2026-11-02: openvibe-shared 4.94.0, the Audio chip, the go-live card's labels); 294.6 (2026-11-02: content labels on cards and the player, L1); 294.1 (2026-11-01: the Catch up rails load by themselves as you swipe); 292.6 openvibe-shared 4.70.0 (2026-11-01: the app bar, busy(), skeletons, view transitions); 291.1 with openvibe-shared 4.57.1 (the Dock's async token and scope-aware controls, 4.57.0; the tool frame's facts, 4.56.0) (2026-10-31); 290.6 with the home's two more tab blocks on phones (2026-10-30); 289.8 with the home's Catch up tabs on phones (2026-10-30); 288.2 with openvibe-shared 4.52.0: the Dock's loader and its Chats tab (2026-10-30); 287.4 with openvibe-shared 4.48.0 (the site switcher on the mark, the menu's Start tab and quick tools; Kit's touch hit areas and the phone navbar fix, 4.44-4.47.3); measured 283.2 (2026-10-28: openvibe-shared 4.30.0, the bell center as above); 279.6 (2026-10-28: openvibe-shared 4.27.0, Notifications 2.0 as above); 273.1 (2026-10-28: openvibe-shared 4.25.0 as above); 270.5 (2026-10-28: openvibe-shared 4.22.0, the navbar's search magnifier with / and Ctrl+K and the More menu; search.js and loading.js load only when used); 269.6 (2026-10-28: openvibe-shared 4.19.0, the account menu's gear and people-group icons inline; 268 on 2026-10-27: openvibe-shared 4.16.0, the folded balance chip, Across OpenVibe with site marks and the icon preload in the navbar); 265.3 (2026-10-27: openvibe-shared 4.15.0, the compact footer opens into the whole one, and the pulse line); 263.3 on 10-23 (openvibe-shared 4.9.0, status text twins in every theme); 262.5 on 10-17 (openvibe-shared 4.4.0, every site in the launcher)
cssRawKB: 270, // measured ~243 since the first-paint subset (style.core.css) replaced style.css (~717 before)
cssBrotliKB: 55, // measured ~47.5 (was ~130)
};
ddiff --git a/test/daylight-surfaces.test.js b/test/daylight-surfaces.test.js
nnew file mode 100644
iindex 00000000..243243a9
---- /dev/null
++++ b/test/daylight-surfaces.test.js
@@@ -0,0 +1,23 @@
++'use strict';
++// Light themes (Daylight and the other light ones) read every surface (11-03 Daylight pass). A box with a hard-coded
++// dark background and the theme's text colour turned into dark text on a dark box on a light theme: toasts, the
++// incoming-call card, the studio's panel and modal. Those take the theme's own card now. Surfaces that cover a video or
++// a picture stay dark in every theme, so their words are light whatever the theme: the adult-content gate, the paste chip.
++const assert = require('assert');
++const fs = require('fs');
++const path = require('path');
++const css = (f) => fs.readFileSync(path.join(__dirname, '..', 'public', 'css', f), 'utf8');
++const rule = (src, sel) => { const i = src.indexOf(`${sel} {`); assert.ok(i >= 0, `${sel} exists`); return src.slice(i, src.indexOf('}', i)); };
++
++const style = css('style.css');
++const toast = rule(style, '\n.toast');
++assert.match(toast, /background: color-mix\(in srgb, var\(--bg-card\) 94%, transparent\);/);
++assert.match(toast, /border: 1px solid var\(--border\);/);
++assert.ok(!/rgba\(23, 27, 39/.test(toast), 'no navy toast');
++assert.match(rule(style, '.vc-call-toast-card'), /background: color-mix\(in srgb, var\(--bg-card\) 96%, transparent\);/);
++assert.match(rule(style, '.home-paste-icon'), /color: #fff;/, 'the chip over a paste\'s picture keeps a light glyph');
++assert.match(rule(style, '.stream-nsfw-gate-card h2'), /color: #fff;/);
++assert.match(rule(style, '.stream-nsfw-gate-card p'), /color: rgba\(255, 255, 255, 0\.76\);/);
++assert.match(rule(css('broadcast.css'), '.bc-modal-content'), /background: var\(--bg-card\);\s*border: 1px solid var\(--border\);/);
++assert.match(rule(css('features/broadcast.css'), '.broadcast-main'), /background: color-mix\(in srgb, var\(--bg-card\) 78%, transparent\);/);
++console.log('daylight surfaces: all checks passed');