openvibers/openvibe.deals Commits

The editors' pick band reads on light themes (WCAG AA) (#183)

OP OpenVibers committed 12 days ago · 27deb54e14 · 2 files, +22 −0

Changes

ddiff --git a/public/css/deal-cards.css b/public/css/deal-cards.css
iindex 0ccc76c..ba458e5 100644
---- a/public/css/deal-cards.css
++++ b/public/css/deal-cards.css
@@@ -26,6 +26,9 @@
.dl-band { padding: 2px 8px; border-radius: 999px; font-size: .7rem; font-weight: 800; letter-spacing: .02em; white-space: nowrap; }
/* Half the hue, half the theme's text: it held on dark themes only (Daylight contrast probe, 2026-11-01). */
.dl-band--pick { color: color-mix(in srgb, #f5b301 55%, var(--text-primary, #e8eef8)); background: color-mix(in srgb, #f5b301 16%, transparent); }
++/* On light themes that mix lands on #926e15 (4.24:1 on the band). A deeper gold reads 5.7:1; dark themes keep the
++ mix above, so their look is unchanged. */
++[data-theme-mode="light"] .dl-band--pick { color: #7c5a0f; }
.dl-band--popular { color: var(--accent-light, #60a5fa); background: color-mix(in srgb, var(--accent, #3b82f6) 16%, transparent); }
.dl-band--new { color: var(--text-secondary, #96a7c2); background: color-mix(in srgb, var(--text-primary, #e8eef8) 7%, transparent); }
@media (max-width: 600px) {
ddiff --git a/test/deal-cards.test.js b/test/deal-cards.test.js
iindex c1efb2b..6ef0e90 100644
---- a/test/deal-cards.test.js
++++ b/test/deal-cards.test.js
@@@ -6,8 +6,20 @@
* own line: active deals, prices seen in 24 hours, and an alert prefilled for it.
*/
const assert = require('assert');
++const fs = require('fs');
++const path = require('path');
const { boot, check, done, HOUR } = require('./helpers/boot');
++const css = fs.readFileSync(path.join(__dirname, '..', 'public', 'css', 'deal-cards.css'), 'utf8');
++const lum = (hex) => [1, 3, 5]
++ .map((i) => parseInt(hex.slice(i, i + 2), 16) / 255)
++ .map((c) => (c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4))
++ .reduce((sum, c, i) => sum + [0.2126, 0.7152, 0.0722][i] * c, 0);
++const ratio = (a, b) => {
++ const [hi, lo] = [lum(a), lum(b)].sort((x, y) => y - x);
++ return (hi + 0.05) / (lo + 0.05);
++};
++
(async () => {
const t = await boot();
const [alice, bob, cara] = ['alice', 'bob', 'cara'].map((n) => t.network.addUser(n));
@@@ -60,6 +72,13 @@ const { boot, check, done, HOUR } = require('./helpers/boot');
assert.match(card((await t.get('/s/shop.example')).text, 'Desk lamp'), /dl-band--pick">Editors&#39; pick|dl-band--pick">Editors' pick/);
});
++ await check('the pick band reads on light themes; dark themes keep the mix', async () => {
++ assert.ok(css.includes('[data-theme-mode="light"] .dl-band--pick { color: #7c5a0f; }'), 'light themes use the deeper gold');
++ assert.ok(css.includes('.dl-band--pick { color: color-mix(in srgb, #f5b301 55%, var(--text-primary, #e8eef8));'), 'dark themes keep the mix');
++ const r = ratio('#7c5a0f', '#fdf3d6');
++ assert.ok(r >= 4.5, `#7c5a0f on #fdf3d6 is ${r.toFixed(2)}:1`);
++ });
++
await check('the shop: its line, its active deals, prices seen in 24 hours, an alert prefilled for it', async () => {
const r = await t.get('/s/shop.example');
assert.match(r.text, /<header class="dl-shop">/);