openvibers/openvibe.shared Commits

4.88.0: name effects read on light themes (#242)

OP OpenVibers committed 11 days ago · 0e14b071d4 · 6 files, +72 −3

Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex 03a0280..cec3fc1 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -4,6 +4,17 @@ All notable changes to `openvibe-shared`. Versions follow [semver](https://semve
breaking change to any exported module, browser global or served file name is a new major.
A release is the git tag `vX.Y.Z`; consumers pin the tag's tarball (see README).
++## 4.88.0 — 2026-11-01
++
++- **Name effects read on light themes.**
++ - The fifteen name effects in items.css were all drawn on dark pages: bright colour plus glow. On a light theme some
++ names were unreadable: Neon and Glitch at 1.3:1, Ice at 1.6:1, and Divine was mostly white (axe flagged Community's
++ pastes and Pulse).
++ - Under `html[data-theme-mode="light"]`, each effect now has a variant with the same hue and motion, at a depth that
++ reads on white (most stops about 4.6:1 or more).
++ - Fire, Ice and Neon animate their light colours with their own keyframes. Shadow's mist and Void's glow are lighter.
++ - Reduced motion still stops them all.
++
## 4.87.0 — 2026-11-01
- **Share cards for a service's other domains.**
ddiff --git a/README.md b/README.md
iindex b8c99a5..de22e62 100644
---- a/README.md
++++ b/README.md
@@@ -2,7 +2,7 @@
> Versioned UI, the OpenVibe Frame (the navbar, footer and "shipped" views every site sits in), SEO, legal and release-client packages every OpenVibe site renders.
--**Status:** alpha, v4.87.0 (every release is a tag; see [CHANGELOG.md](CHANGELOG.md)). Every deployed
++**Status:** alpha, v4.88.0 (every release is a tag; see [CHANGELOG.md](CHANGELOG.md)). Every deployed
consumer installs a tagged release and none keeps a vendored copy
([docs/migration-plan.md](docs/migration-plan.md) is done); each repository's `package.json` names
the tag it pins.
ddiff --git a/STATUS.json b/STATUS.json
iindex 4738ecb..4064957 100644
---- a/STATUS.json
++++ b/STATUS.json
@@@ -4,7 +4,7 @@
"code": true,
"wave": "W2",
"package": "openvibe-shared",
-- "version": "4.87.0",
++ "version": "4.88.0",
"plan": "OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026)",
"deployed": false,
"deployment": "none of its own: a package released as git tags; OpenVibe.Network serves /shared/* from its pinned tag, and a site can serve its own pinned copy (openvibe-shared/serve)",
ddiff --git a/items.css b/items.css
iindex ceb3dc3..559bdbe 100644
---- a/items.css
++++ b/items.css
@@@ -331,6 +331,46 @@ html[data-ov-motion=reduced] .name-fx-twofat::after { animation: none !important
@keyframes ovHatPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.2); } }
@keyframes ovHatWarp { 0%, 100% { transform: scale(1) rotate(0deg); filter: hue-rotate(0deg); } 50% { transform: scale(1.1) rotate(5deg); filter: hue-rotate(180deg); } }
++/* Light themes (theme-loader sets html[data-theme-mode=light]): every effect above was drawn for a dark page, bright
++ * colour plus glow; on white some were unreadable (Neon and Glitch's #00ff88 at 1.3:1, Ice at 1.6:1, Divine's white).
++ * The same effect, same hue and motion, at a depth that reads on a light page (about 4.6:1 or more, 2026-11-01). Void
++ * (#9900ff) already reads on white and keeps its colour. */
++html[data-theme-mode="light"] .name-fx-rainbow { background-image: linear-gradient(90deg, #dc2626, #c2410c, #a16207, #15803d, #1d4ed8, #7c3aed, #be185d); }
++html[data-theme-mode="light"] .name-fx-fire { color: #c2410c !important; text-shadow: 0 0 6px #fb923c55; animation-name: nameFxFireLight; }
++@keyframes nameFxFireLight {
++ 0% { text-shadow: 0 0 5px #fb923c55; color: #c2410c; }
++ 100% { text-shadow: 0 0 9px #f9731666, 0 0 16px #fdba7444; color: #b45309; }
++}
++html[data-theme-mode="light"] .name-fx-ice { color: #0369a1 !important; text-shadow: 0 0 6px #38bdf855; animation-name: nameFxIceLight; }
++@keyframes nameFxIceLight {
++ 0% { text-shadow: 0 0 4px #38bdf855; color: #0369a1; }
++ 100% { text-shadow: 0 0 9px #7dd3fc88, 0 0 16px #38bdf844; color: #0e7490; }
++}
++html[data-theme-mode="light"] .name-fx-golden { background-image: linear-gradient(90deg, #a16207, #b45309, #a16207, #92400e); }
++html[data-theme-mode="light"] .name-fx-neon { color: #047857 !important; text-shadow: 0 0 5px #34d39966; animation-name: nameFxNeonLight; }
++@keyframes nameFxNeonLight {
++ 0% { text-shadow: 0 0 3px #34d39955; }
++ 100% { text-shadow: 0 0 8px #34d39988, 0 0 14px #6ee7b744; }
++}
++html[data-theme-mode="light"] .name-fx-glitch { color: #047857 !important; }
++html[data-theme-mode="light"] .name-fx-galaxy { background-image: linear-gradient(90deg, #6d28d9, #be185d, #1d4ed8, #6d28d9); }
++html[data-theme-mode="light"] .name-fx-toxic { background-image: linear-gradient(90deg, #15803d, #4d7c0f, #3f6212, #047857); }
++html[data-theme-mode="light"] .name-fx-blood { background-image: linear-gradient(180deg, #dc2626, #7f1d1d, #b91c1c); }
++html[data-theme-mode="light"] .name-fx-shadow { color: #6b4f8a !important; animation-name: nameFxShadowLight; }
++@keyframes nameFxShadowLight {
++ 0%, 100% { text-shadow: 0 0 5px rgba(80, 0, 120, 0.3), 1px 1px 3px rgba(30, 10, 50, 0.3); }
++ 50% { text-shadow: 0 0 10px rgba(80, 0, 120, 0.4), 2px 2px 5px rgba(30, 10, 50, 0.35); }
++}
++html[data-theme-mode="light"] .name-fx-void { text-shadow: 0 0 6px #a855f755; animation-name: nameFxVoidLight; }
++@keyframes nameFxVoidLight {
++ 0%, 100% { text-shadow: 0 0 5px #a855f755, 0 0 10px #c084fc33; transform: scale(1); }
++ 50% { text-shadow: 0 0 9px #a855f777, 0 0 16px #c084fc44; transform: scale(1.03); }
++}
++html[data-theme-mode="light"] .name-fx-hologram { background-image: linear-gradient(90deg, #0f766e, #0369a1, #4f46e5, #047857); }
++html[data-theme-mode="light"] .name-fx-divine { background-image: linear-gradient(90deg, #b45309, #a16207, #92400e, #a16207, #b45309); }
++html[data-theme-mode="light"] .name-fx-vegas { background-image: linear-gradient(90deg, #b45309 0%, #a16207 22%, #c2410c 40%, #be185d 52%, #a16207 66%, #b45309 82%, #a16207 100%); }
++html[data-theme-mode="light"] .name-fx-twofat { background-image: linear-gradient(90deg, #c026d3 0%, #7e22ce 25%, #0e7490 50%, #7e22ce 75%, #c026d3 100%); }
++
/* Particles (live.particle.css@1): characters that float out of the name and fade, Live's colours. They reset the
name effect's text fill, so a gradient name still shows them. */
.ov-px { position: relative; display: inline-block; }
ddiff --git a/package.json b/package.json
iindex 1b2fc1c..dbab1d8 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-shared",
-- "version": "4.87.0",
++ "version": "4.88.0",
"description": "Shared navbar, footer, themes, icons, legal pages, SEO, auth and analytics for every OpenVibe site",
"main": "index.js",
"bin": {
ddiff --git a/test/name-effects-light.test.js b/test/name-effects-light.test.js
nnew file mode 100644
iindex 0000000..f5e1f2d
---- /dev/null
++++ b/test/name-effects-light.test.js
@@@ -0,0 +1,18 @@
++'use strict';
++// Name effects on light themes (4.88.0): each effect was drawn on a dark page, and on white some were unreadable
++// (Neon and Glitch's #00ff88 at 1.3:1, Ice at 1.6:1, Divine's white). Each has a light-theme variant of the same hue.
++const assert = require('assert');
++const fs = require('fs');
++const path = require('path');
++
++const css = fs.readFileSync(path.join(__dirname, '..', 'items.css'), 'utf8');
++const effects = [...new Set([...css.matchAll(/^\.name-fx-([a-z]+) \{/gm)].map((m) => m[1]))];
++assert.ok(effects.length >= 15, `the effects (${effects.length})`);
++effects.forEach((fx) => {
++ assert.match(css, new RegExp(`html\\[data-theme-mode="light"\\] \\.name-fx-${fx}[ ,{]`), `${fx} has a light-theme variant`);
++});
++// The colour-animated ones animate their light colours, so the dark keyframes cannot bring the bright colour back.
++['Fire', 'Ice', 'Neon'].forEach((k) => assert.match(css, new RegExp(`@keyframes nameFx${k}Light \\{`), `${k} has light keyframes`));
++// Reduced motion still stops them all.
++assert.match(css, /@media \(prefers-reduced-motion: reduce\) \{\s*\.ov-fx\[class\*="name-fx-"\], \.ov-hat \{ animation: none !important; \}/);
++console.log('name effects light: all checks passed');