openvibers/openvibe.host Commits

Front page: nothing hidden on a phone, counted doors, readable warning words (#249)

OP OpenVibers committed 11 days ago · 815914821b · 6 files, +34 −12

Changes

ddiff --git a/public/css/catalog.css b/public/css/catalog.css
iindex 70c622a..eb06ec1 100644
---- a/public/css/catalog.css
++++ b/public/css/catalog.css
@@@ -189,8 +189,7 @@
.hd-table td.hd-go { grid-column: 1 / -1; text-align: left; }
.hd-table td.hd-go::before { display: none; }
.hd-table td[data-label="Checked"] { grid-column: 1 / -1; }
-- /* The list of endings stays short on a phone: the first year, the renewal and five years; the rest is on each ending's page. */
-- .hd-list td[data-label="Transfer"], .hd-list td[data-label="Registrars"], .hd-list td[data-label="Checked"] { display: none; }
++ /* Every column shows on a phone too (2026-11-02: nothing is hidden to shorten a page); the list is five rows. */
}
/* Benchmarks (server/render/benchmarks.js). */
ddiff --git a/public/css/host.css b/public/css/host.css
iindex cbb3795..c31447f 100644
---- a/public/css/host.css
++++ b/public/css/host.css
@@@ -1,7 +1,7 @@
/* OpenVibe.Host dashboard. Colours follow the shared theme tokens when theme-loader.js has run. */
:root { --hs-bg: var(--bg-primary, #0a0f1c); --hs-fg: var(--text-primary, #e6edf7); --hs-muted: var(--text-secondary, #9aa7bd);
--hs-card: var(--bg-secondary, #111a2c); --hs-line: var(--border, rgba(255,255,255,.12)); --hs-accent: var(--accent, #60a5fa);
-- --hs-ok: var(--success-text, #34d399); --hs-warn: var(--warning-text, #fbbf24); --hs-bad: var(--danger-text, #f87171); }
++ --hs-ok: var(--success-text, #34d399); --hs-warn: color-mix(in srgb, var(--warning-text, #fbbf24) 80%, var(--text-primary, #e6edf7)); --hs-bad: var(--danger-text, #f87171); }
/* Status words and lines use the theme's readable status colours; the fixed light green, amber and red were for dark
themes only (axe on Daylight: 1.8:1, 2026-11-01). Buttons wear the theme's strong accent and its own text colour. */
body { margin: 0; background: var(--hs-bg); color: var(--hs-fg); font: 15px/1.55 system-ui, -apple-system, "Segoe UI", sans-serif; }
@@@ -36,10 +36,10 @@ ul.domains { padding-left: 1.2rem; } ul.domains li { margin-bottom: 1rem; }
.intro { max-width: 44rem; }
@media (max-width: 40rem) { table { display: block; overflow-x: auto; } .account-bar { text-align: left; } }
--/* Phones (2026-10-29): a taste and a door. The front page's plan and domain lists show four rows each (every plan
-- and every ending are a link away), and the numbers are one strip that scrolls sideways. */
++/* Phones (2026-10-29): a taste and a door. The front page renders five rows per list at every width (2026-11-02:
++ rows are never hidden on a phone; every plan and every ending are a counted link away), and the numbers are one
++ strip that scrolls sideways. */
@media (max-width: 599px) {
-- .hh-short .hc-table tbody tr:nth-child(n+5) { display: none; }
.hh-stats { display: flex; overflow-x: auto; scrollbar-width: none; gap: 8px; margin-left: -16px; margin-right: -16px; padding: 0 16px 2px; }
.hh-stats::-webkit-scrollbar { display: none; }
.hh-stats li { flex: 0 0 auto; min-width: 128px; }
ddiff --git a/server/render/catalog.js b/server/render/catalog.js
iindex 0a2976a..c80ba7a 100644
---- a/server/render/catalog.js
++++ b/server/render/catalog.js
@@@ -477,8 +477,8 @@ function front({ plans, providers, promos: live, stats, offers: recent = [], dom
actions: [{ label: 'Compare plans', href: '/catalog', primary: true }, { label: 'Domain prices', href: '/catalog/domains' }],
note: stats.plans ? `${stats.plans} plans from ${stats.providers} provider${stats.providers === 1 ? '' : 's'} so far. More providers join as their sources are checked.` : 'The catalog is filling up: providers join as their official sources are checked and enabled.',
aside: aside ? { html: aside } : undefined,
-- }) + extra.stats + changeRail + `<section class="sc-sec hh-short" aria-labelledby="hh-cheapest"><h2 id="hh-cheapest">The lowest monthly prices</h2>${planTable(plans.slice(0, 8), { caption: 'Lowest price first', now })}
--<p class="hc-more">${link('/catalog', 'Filter and sort every plan →', 'button')}</p></section>`
++ }) + extra.stats + changeRail + `<section class="sc-sec hh-short" aria-labelledby="hh-cheapest"><h2 id="hh-cheapest">The lowest monthly prices</h2>${planTable(plans.slice(0, 5), { caption: 'Lowest price first', now })}
++<p class="hc-more">${link('/catalog', stats.plans > 5 ? `Filter and sort all ${Number(stats.plans).toLocaleString('en')} plans →` : 'Filter and sort every plan →', 'button')}</p></section>`
+ extra.sizes + extra.value + extra.providers
+ domainSection
+ '<section class="sc-sec" id="why" aria-labelledby="hh-why"><details class="hh-fold"><summary><h2 id="hh-why">Why this comparison is different</h2><span>sourced, dated, ranked by you</span></summary>'
ddiff --git a/server/render/domains.js b/server/render/domains.js
iindex 9ce7641..e08a0bd 100644
---- a/server/render/domains.js
++++ b/server/render/domains.js
@@@ -162,9 +162,9 @@ function frontSection({ popular = [], cheap = [], stats }) {
return `<section class="sc-sec hd-front" aria-labelledby="hd-front-h"><h2 id="hd-front-h">Domain names, compared too</h2>
<p class="hc-dim">${stats.tlds ? `${stats.tlds.toLocaleString('en')} endings${registrars > 1 ? ` from ${registrars} registrars (${stats.registrars.map(esc).join(', ')})` : ''}, with the first year, the renewal and five years side by side. ` : ''}Check a name at its registry, then register it where it costs least.</p>
${checkForm({})}
--<div class="hh-short">${tldTable(popular.slice(0, 6), { caption: 'Popular endings: the cheapest price at any registrar' })}</div>
--${cheap.length ? '<div class="hh-short">' + tldTable(cheap.slice(0, 6), { caption: 'The cheapest first year right now: check what it renews at' }) + '</div>' : ''}
--${stats.tlds ? `<p class="hc-more">${link('/catalog/domains', 'Every ending, by price →', 'button')}</p>` : ''}</section>`;
++<div class="hh-short">${tldTable(popular.slice(0, 5), { caption: 'Popular endings: the cheapest price at any registrar' })}</div>
++${cheap.length ? '<div class="hh-short">' + tldTable(cheap.slice(0, 5), { caption: 'The cheapest first year right now: check what it renews at' }) + '</div>' : ''}
++${stats.tlds ? `<p class="hc-more">${link('/catalog/domains', `All ${Number(stats.tlds).toLocaleString('en')} endings, by price →`, 'button')}</p>` : ''}</section>`;
}
const jsonLd = {
ddiff --git a/test/front-unhidden.test.js b/test/front-unhidden.test.js
nnew file mode 100644
iindex 0000000..cf2fec6
---- /dev/null
++++ b/test/front-unhidden.test.js
@@@ -0,0 +1,22 @@
++'use strict';
++
++/**
++ * Nothing is hidden to shorten a page (owner, 2026-10-31): the front page's short lists render the same rows at every
++ * width and end in a counted link, and the endings list keeps every column on a phone.
++ */
++const assert = require('assert');
++const fs = require('fs');
++const path = require('path');
++
++const css = (f) => fs.readFileSync(path.join(__dirname, '..', 'public', 'css', f), 'utf8');
++
++assert.ok(!/tr:nth-child\(n\+\d+\)\s*\{\s*display:\s*none/.test(css('host.css')), 'no row of a short list is hidden on a phone');
++assert.ok(!/\.hd-list td\[data-label=[^\]]+\][^{]*\{\s*display:\s*none/.test(css('catalog.css')), 'no column of the endings list is hidden on a phone');
++
++const catalog = fs.readFileSync(path.join(__dirname, '..', 'server', 'render', 'catalog.js'), 'utf8');
++assert.ok(catalog.includes('planTable(plans.slice(0, 5)'), 'the front page renders the five rows it shows');
++assert.ok(catalog.includes('Filter and sort all ${'), 'the door to every plan is counted');
++const domains = fs.readFileSync(path.join(__dirname, '..', 'server', 'render', 'domains.js'), 'utf8');
++assert.ok(domains.includes('All ${Number(stats.tlds)'), 'the door to every ending is counted');
++
++console.log('front-unhidden: all passed');
ddiff --git a/test/theme-status.test.js b/test/theme-status.test.js
iindex 1868960..9e7ca5b 100644
---- a/test/theme-status.test.js
++++ b/test/theme-status.test.js
@@@ -8,7 +8,8 @@ const path = require('path');
const css = fs.readFileSync(path.join(__dirname, '..', 'public', 'css', 'host.css'), 'utf8');
assert.match(css, /--hs-ok: var\(--success-text, #34d399\)/);
--assert.match(css, /--hs-warn: var\(--warning-text, #fbbf24\)/);
++// Mixed toward the text colour so a warning word also reads on a tinted row (Daylight, 2026-11-02).
++assert.match(css, /--hs-warn: color-mix\(in srgb, var\(--warning-text, #fbbf24\) 80%, var\(--text-primary, #e6edf7\)\)/);
assert.match(css, /--hs-bad: var\(--danger-text, #f87171\)/);
assert.match(css, /--hs-line: var\(--border, rgba\(255,255,255,\.12\)\)/);
assert.match(css, /button, \.button \{[^}]*background: var\(--accent-strong, var\(--hs-accent\)\); color: var\(--on-accent-strong, #0a0f1c\)/);