openvibers/openvibe.trade Commits

Home: a taste and a door on phones (#138)

OP OpenVibers committed 15 days ago · 84c54267f1 · 3 files, +23 −6

The briefs, reports and euro rates are one row each that scrolls sideways on a
phone (every card is still there), the form chips show eight, the newest filings
five and the companies table eight rows (each list is a link away), the figures
are one strip, what is here folds, and the hero has two actions. CSS budgets
raw 38 -> 39 and brotli 8 -> 8.5 (measured 38.4 and 8.3).

Changes

ddiff --git a/public/css/trade.css b/public/css/trade.css
iindex 208f0f5..13a77ec 100644
---- a/public/css/trade.css
++++ b/public/css/trade.css
@@@ -106,6 +106,24 @@ form.inline button { margin: 0; padding: 2px 10px; font-size: .85rem; }
.tr-faq p { margin: 0 0 14px; color: var(--text-secondary, #96a7c2); }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
@media (max-width: 600px) { .tr-search { flex-wrap: wrap; } .tr-search button { width: 100%; } .tr-stats b { font-size: 1.3rem; } .tr-stats a { padding: 12px; } .tr-cards > li:nth-child(n+5) { display: none; } }
++/* Phones (2026-10-29): a taste and a door. The briefs, reports and euro rates are one row each that scrolls sideways
++ (every card is still there), the lists show their first rows (each is a link away), the figures are one strip. */
++.tr-fold { font-family: var(--ov-font, 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif); border: 1px solid var(--border, #1f2d47); border-radius: 14px; background: var(--bg-card, #131c2e); }
++.tr-fold > summary { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 48px; padding: 0 16px; cursor: pointer; font-weight: 700; list-style: none; }
++.tr-fold > summary::-webkit-details-marker { display: none; }
++.tr-fold > summary span { color: var(--text-muted, #7386a3); font-weight: 600; font-size: .86rem; text-align: right; }
++.tr-fold > summary:focus-visible { outline: 2px solid var(--accent, #3b82f6); outline-offset: -2px; border-radius: 14px; }
++.tr-fold .sc-sec { margin: 0; max-width: none; padding: 0 16px 16px; }
++@media (max-width: 600px) {
++ .tr-cards, .tr-rates, .tr-stats { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: 16px; scrollbar-width: none; gap: 10px; margin-left: -16px; margin-right: -16px; padding: 0 16px 4px; }
++ .tr-cards::-webkit-scrollbar, .tr-rates::-webkit-scrollbar, .tr-stats::-webkit-scrollbar { display: none; }
++ .tr-cards > li { flex: 0 0 84%; scroll-snap-align: start; }
++ .tr-rates > li { flex: 0 0 46%; scroll-snap-align: start; }
++ .tr-stats > li { flex: 0 0 auto; width: 132px; scroll-snap-align: start; }
++ .tr-sec .tr-chips > li:nth-child(n+9), .tr-sec > .docs > li:nth-child(n+6) { display: none; }
++ .tr-sec[aria-labelledby="movers"] tbody tr:nth-child(n+9) { display: none; }
++ .tr-fold > summary span { display: none; }
++}
@media (prefers-reduced-motion: reduce) { .tr-stats a { transition: none; } }
.home .disclaimer { max-width: 1048px; }
.tr-more-rates { margin-top: 8px; }
ddiff --git a/server/render/home.js b/server/render/home.js
iindex d8d13fc..dba590f 100644
---- a/server/render/home.js
++++ b/server/render/home.js
@@@ -124,7 +124,7 @@ function homePage(d, urls) {
<h1>Market information that shows<span class="sc-accent"> its source</span></h1>
<p class="sc-hero-lede">US-listed companies from the SEC's own list, their filings as they arrive, the key numbers in those filings, euro reference rates and short AI briefs that cite every figure. Every value says when it was observed and which source stated it.</p>
<form class="search tr-search" id="find" method="get" action="/resolve" role="search"><label class="sr-only" for="q">Find a company by ticker, CIK or name</label><input id="q" name="q" type="search" maxlength="200" required placeholder="Ticker, CIK or company name, like AAPL"><button type="submit">Find</button></form>
--<div class="sc-actions"><a class="sc-btn sc-primary" href="/filings">Latest filings</a><a class="sc-btn" href="#briefs">AI briefs</a><a class="sc-btn" href="/watchlists">Watchlists and alerts</a></div>
++<div class="sc-actions"><a class="sc-btn sc-primary" href="/filings">Latest filings</a><a class="sc-btn" href="#briefs">AI briefs</a></div>
</div>
<div class="sc-hero-aside">${stats([
{ n: s.companies, label: 'companies on the SEC\'s list', href: '/instruments' },
@@@ -143,8 +143,7 @@ ${section({ id: 'reports', title: 'New annual and quarterly reports', lede: 'The
${section({ id: 'forms', title: 'Filed in the last 7 days', lede: 'Filings by form type, the most first.', more: { href: '/filings', label: 'Every filing' }, body: formChips(d.forms) })}
${section({ id: 'recent', title: 'Newest filings', lede: 'As they arrive from the SEC, each with when it was published and when it was retrieved.', more: { href: '/filings', label: 'More filings' }, body: d.recent.length ? html`<ul class="docs">${d.recent.map((r) => filingLine(r, urls))}</ul>` : '' })}
${section({ id: 'movers', title: 'Companies with something new', lede: 'The newest filing or figure first.', more: { href: '/instruments', label: `All ${count(s.instruments)} companies and currencies` }, body: d.movers.instruments.length ? instrumentsTable({ instruments: d.movers.instruments, latest: d.movers.latest, latestDocs: d.movers.latestDocs, urls }) : '' })}
--${raw(showcase.features({
-- title: 'What is here',
++<div class="tr-sec"><details class="tr-fold"><summary>What is here<span>companies, numbers, briefs, filings, alerts</span></summary>${raw(showcase.features({
items: [
{ icon: 'ov:search', title: 'Find a company', text: 'By ticker, SEC CIK or company name. One match takes you straight there; several are listed, never guessed between.', href: '/instruments' },
{ icon: 'ov:history', title: 'The numbers from the filings', text: 'Revenue, net income, EPS, cash flow and the balance sheet, exactly as each company filed them with the SEC, each with its period and filing.' },
@@@ -153,7 +152,7 @@ ${raw(showcase.features({
{ icon: 'ov:bell', title: 'Watchlists and alert rules', text: 'Private to you when signed in: an alert for a new filing or a number crossing a line.', href: '/watchlists' },
{ icon: 'ov:check', title: 'Source freshness', text: 'Every source with when it last answered; a source that falls behind marks its values stale.', href: '/sources' },
],
-- }))}
++ }))}</details></div>
<section class="tr-sec" aria-labelledby="faq"><div class="tr-head"><h2 id="faq">Questions and answers</h2></div>
<div class="tr-faq">${d.faq.map((x) => html`<details><summary>${x.q}</summary><p>${x.a}</p></details>`)}</div></section>
<p>Feeds of recent documents: <a href="/feed.xml">RSS</a> · <a href="/atom.xml">Atom</a> · <a href="/feed.json">JSON Feed</a>. Source freshness: <a href="/sources">sources</a>.${d.sync && d.sync.last_ok_at ? html` Last synchronised with OpenVibe.Sources ${when(d.sync.last_ok_at)}.` : ''}</p>`;
ddiff --git a/test/perf-budget.test.js b/test/perf-budget.test.js
iindex 56f25f3..350ca5a 100644
---- a/test/perf-budget.test.js
++++ b/test/perf-budget.test.js
@@@ -18,8 +18,8 @@ const BUDGETS = {
jsRawKB: 305, // 300.5 openvibe-shared 4.25.0: the menu's orb beside the brand, both balances on phones, messages, the account sheet on phones and the bar stepping away on phones; 293 openvibe-shared 4.22.0: the navbar's magnifier search button and More dropdown (search.js and loading.js load only when used); 287.2 Shared 4.17.0: OpenCoins and Vibes chips (wallet: true) in the navbar; 273.2 openvibe-shared 4.15 footer: the compact footer opens into the whole one, and the pulse line; 263.4 with shared 4.11.0's seasonal navbar; 254.1 with openvibe-shared 4.9.0 (status text twins in every theme, 2026-10-23); 246.2 with openvibe-shared 4.2.x (Ask Actor in the navbar, 2026-10-15); 239.1 (212.2 before openvibe-shared/shell's web-runtime.js)
jsBrotliKB: 76, // 74.2 openvibe-shared 4.25.0: the menu's orb beside the brand, both balances on phones, messages, the account sheet on phones and the bar stepping away on phones; 70.5 Shared 4.17.0: OpenCoins and Vibes chips (wallet: true) in the navbar; 67.9 openvibe-shared 4.15 footer: the compact footer opens into the whole one, and the pulse line; 65.3 Shared 4.12.0: the light/dark switch, the seasonal mark and the theme pairs; 61.7 with shared 4.11.0's seasonal navbar; 59.1 with openvibe-shared 4.4.0 (every site in the launcher, 2026-10-17); 56.3 (49.9 before web-runtime.js)
cssFiles: 2, // 2 (trade.css, openvibe-shared showcase.css)
-- cssRawKB: 38, // 34 openvibe-shared 4.26.1 (hero visual); 28.5 with Shared 4.13.0 (2026-10-26: account links); ~23 with the front page's numbers, cards, rate cards, chips and questions (2026-10-22); 18.0 before (4.7 before showcase.css)
-- cssBrotliKB: 8, // 6.3 with Shared 4.13.0 (2026-10-26: account links); ~5.3 with the front page (2026-10-22); 4.5 with the tablet table rule (1.3 before showcase.css)
++ cssRawKB: 39, // 38.4 the home's phone rows and fold (2026-10-29); 34 openvibe-shared 4.26.1 (hero visual); 28.5 with Shared 4.13.0 (2026-10-26: account links); ~23 with the front page's numbers, cards, rate cards, chips and questions (2026-10-22); 18.0 before (4.7 before showcase.css)
++ cssBrotliKB: 8.5, // 8.3 the home's phone rows and fold (2026-10-29); 6.3 with Shared 4.13.0 (2026-10-26: account links); ~5.3 with the front page (2026-10-22); 4.5 with the tablet table rule (1.3 before showcase.css)
externalFiles: 1, // 0
};