openvibers/openvibe.work Commits
Home: every pane shows on a phone; the chips are links, not a picker (#168)
Changes
@@@ -47,25 +47,21 @@.home-fold > summary span { display: none; }}--/* Pick (the owner's short-pages rule, 2026-10-30): on a phone the sections below the search are one at a time,-- picked with a row of chips. Radio inputs and :has(), no script: the chips and the one-section rule live under-- 640 px and only where :has() is understood, so a wider screen, or an older browser, shows every section and no-- chips. Every section stays in the page for the crawlers. */++/* Pick: on a phone every pane is shown, stacked, each with its own heading; the chips are a row of links that++ jump to a pane (the owner's rule, 2026-10-31: never hide content to shorten). A wide screen shows the panes as++ before, with no chips. */.pick-head, .pick-row { display: none; }--@supports selector(:has(*)) {-- @media (max-width: 640px) {-- .pick-head { display: block; }-- .pick-head h2 { margin: 0 0 4px; font: 700 clamp(20px, 2.4vw, 28px)/1.2 var(--ov-font, 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif); letter-spacing: -.02em; }-- .pick-row { display: flex; gap: 8px; overflow-x: auto; margin: 10px -16px 0; padding: 2px 16px 4px; scrollbar-width: none; overscroll-behavior-x: contain; }-- .pick-row::-webkit-scrollbar { display: none; }-- .pick-row input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }-- .pick-row label { display: inline-flex; align-items: center; flex: none; min-height: 44px; padding: 0 15px; border-radius: 999px; border: 1px solid var(--border, #1f2d47); color: var(--text-secondary, #96a7c2); font-size: .9rem; font-weight: 650; white-space: nowrap; cursor: pointer; }-- .pick-row input:checked + label { color: var(--text-primary, #e6edf7); border-color: var(--accent, #3b82f6); background: color-mix(in srgb, var(--accent, #3b82f6) 12%, transparent); }-- .pick-row input:focus-visible + label { outline: 2px solid var(--accent, #3b82f6); outline-offset: 2px; }-- .pick-pane { display: none; }-- /* The chip names the section, so the section's own heading gives way to it. */-- .pick-pane > .sc-sec > h2 { display: none; }-- }++@media (max-width: 640px) {++ .pick-bar { margin-top: 30px; }++ .pick-head { display: block; }++ .pick-head h2 { margin: 0 0 4px; font: 700 clamp(20px, 2.4vw, 28px)/1.2 var(--ov-font, 'Inter', system-ui, sans-serif); letter-spacing: -.02em; }++ .pick-row { display: flex; gap: 8px; overflow-x: auto; margin: 10px -16px 0; padding: 2px 16px 4px; scrollbar-width: none; overscroll-behavior-x: contain; }++ .pick-row::-webkit-scrollbar { display: none; }++ .pick-chip { display: inline-flex; align-items: center; flex: none; min-height: 44px; padding: 0 15px; border-radius: 999px; border: 1px solid var(--border, #1f2d47); color: var(--text-secondary, #96a7c2); font-size: .9rem; font-weight: 650; white-space: nowrap; text-decoration: none; }++ .pick-chip:hover, .pick-chip:focus-visible { color: var(--text-primary, #e6edf7); border-color: var(--accent, #3b82f6); }++ .pick-chip:focus-visible { outline: 2px solid var(--accent, #3b82f6); outline-offset: 2px; }++ .pick .pick-pane { scroll-margin-top: 72px; }++ .pick .pick-pane + .pick-pane { margin-top: 26px; }}/* The fold (the owner's short-pages rule, 2026-10-30): a part a reader rarely needs. On a phone it is closed — the@@@ -19,7 +19,7 @@ const { asyncRouter } = require('./router');const { createDiscoveryRoutes, homeJsonLd } = require('./discovery');const { sameOrigin } = require('./principal');const { html, raw, table, notice, time } = require('../render/html');--const { foldBlock, pickBlock, pickRules } = require('../render/short');++const { foldBlock, pickBlock } = require('../render/short');const { send } = require('../render/layout');const listing = require('../render/listing');const store = require('../jobs/store');@@@ -198,7 +198,6 @@ ${listing.listingList(salaried, { sourceOf, empty: '' })}</section>`) });styles: [showcase.STYLESHEET], localStyles: ['css/home.css'],// The rule that shows the picked section of the browse block is written for the page, because there is one// per section (CSS cannot pair a radio with a pane by index).-- inlineStyles: ['@supports selector(:has(*)){@media (max-width:640px){' + pickRules('browse', panes.map((p) => p.id)) + '}}'],body: html`${raw(hero)}${stats.length ? html`<ul class="home-stats" aria-label="${SITE_NAME} in numbers">${stats.map((x) => html`<li><a href="${x.href}"><b>${n(x.value)}</b><span>${x.label}</span></a></li>`)}</ul>` : ''}<section class="sc-sec" id="search" aria-labelledby="h-search"><h2 id="h-search">Search the listings</h2>@@@ -42,19 +42,11 @@ function foldBlock({ id, head, html, bare = false }) {function pickBlock({ key, label, head = '', panes, checked = '' }) {if (!panes.length) return '';const first = panes.find((p) => p.id === checked) ? checked : panes[0].id;-- const chips = panes.map((p) => `<input type="radio" name="pick-${esc(key)}" id="pk-${esc(key)}-${esc(p.id)}" value="${esc(p.id)}"${p.id === first ? ' checked' : ''}><label for="pk-${esc(key)}-${esc(p.id)}">${esc(p.label)}</label>`).join('');++ const chips = panes.map((p) => `<a class="pick-chip" href="#pp-${esc(key)}-${esc(p.id)}">${esc(p.label)}</a>`).join('');const body = panes.map((p) => `<div class="pick-pane" id="pp-${esc(key)}-${esc(p.id)}">${str(p.html)}</div>`).join('');-- return `<div class="pick" id="pick-${esc(key)}"><div class="pick-bar"><div class="pick-head"><h2>${esc(head || label)}</h2></div><div class="pick-row" role="radiogroup" aria-label="${esc(label)}">${chips}</div></div><div class="pick-body">${body}</div></div>`;++ return `<div class="pick" id="pick-${esc(key)}"><div class="pick-bar"><div class="pick-head"><h2>${esc(head || label)}</h2></div><nav class="pick-row" aria-label="${esc(label)}">${chips}</nav></div><div class="pick-body">${body}</div></div>`;}--/** The rule that shows the picked block of a pick block: one per block, so the CSS is written for the page. */--function pickRule(key, id) {-- return `.pick:has(#pk-${key}-${id}:checked) #pp-${key}-${id}{display:block}`;--}--/** The rules for every block of a pick block, in the order they appear. */--function pickRules(key, ids) {-- return ids.map((id) => pickRule(key, id)).join('');--}--module.exports = { foldBlock, pickBlock, pickRule, pickRules };++module.exports = { foldBlock, pickBlock };@@@ -1,6 +1,5 @@'use strict';// The home on a phone (the owner's short-pages rule, 2026-10-30): the sections below the search are one at a time,--// picked with a row of chips, and the parts a reader rarely needs fold closed. Radio inputs and :has() for the chips// and a checkbox and a label for the folds, no script: every section and every part stays in the page for the// crawlers, and a wider screen shows them all and no chips.const assert = require('assert');@@@ -30,13 +29,13 @@ const { boot, check, done } = require('./helpers/boot');assert.strictEqual(r.status, 200, r.text.slice(0, 300));const home = r.text;assert.match(home, /<div class="pick" id="pick-browse">/, 'the browse block is on the home');-- assert.match(home, /<div class="pick-row" role="radiogroup" aria-label="Browse the listings">/, 'the chips are on the home');++ assert.match(home, /<nav class="pick-row" aria-label="Browse the listings">/, 'the chips are on the home');// One chip per section, in the order the sections have, and the newest listings are the one a phone shows.-- const chips = [...home.matchAll(/<input type="radio" name="pick-browse" id="pk-browse-([a-z]+)" value="\1"( checked)?><label for="pk-browse-\1">[^<]+<\/label>/g)];++ const chips = [...home.matchAll(/<a class="pick-chip" href="#(?:pp-browse-)?([a-z]+)">()[^<]+<\/a>/g)];const panes = [...home.matchAll(/<div class="pick-pane" id="pp-browse-([a-z]+)">/g)].map((m) => m[1]);assert.ok(panes.length >= 3, `the sections are all in the page (${panes.length})`);assert.deepStrictEqual(chips.map((m) => m[1]), panes, 'one chip per section, in the same order');-- assert.deepStrictEqual(chips.filter((m) => m[2]).map((m) => m[1]), ['latest'], 'the newest listings are picked first');++ assert.ok(!/type="radio"/.test(home), 'no chip is a radio: nothing is picked, every pane shows');// The sections themselves are in the page, not removed.for (const h of ['Browse by field', 'Jobs by city', 'Latest remote jobs', 'Newest jobs that state the pay', 'Companies with the most openings']) {assert.ok(home.includes(`>${h}</h2>`), `${h} is in the page`);@@@ -59,20 +58,14 @@ const { boot, check, done } = require('./helpers/boot');assert.match(home, /<div class="home-faq">/, 'the questions are in the page');assert.match(home, /class="sc-net"/, 'the rest of OpenVibe is in the page');assert.match(home, /data-ov-shipped="list"/, 'what shipped is in the page');-- // The CSS: the chips and their rule under 640 px and only with :has(); the fold closed on a phone, open where// there is room.const css = fs.readFileSync(path.join(__dirname, '..', 'public', 'css', 'home.css'), 'utf8');-- const pick = css.slice(css.indexOf('/* Pick (the owner'));++ const pick = css.slice(css.indexOf('/* Pick: on a phone every pane is shown'));assert.ok(pick.length > 0, 'the pick rules are in home.css');-- assert.match(pick, /\.pick-head, \.pick-row \{ display: none; \}/, 'the chips are hidden by default');-- assert.match(pick, /@supports selector\(:has\(\*\)\) \{\n @media \(max-width: 640px\) \{/, 'the chips are only under 640 px and only with :has()');-- assert.match(pick, /\.pick-pane \{ display: none; \}/, 'one section at a time');-- const head = home.slice(home.indexOf('<style>@supports selector(:has(*))'));-- assert.ok(head.startsWith('<style>@supports selector(:has(*))'), 'the rule that shows the picked section is on the page');-- for (const id of panes) assert.ok(head.includes(`.pick:has(#pk-browse-${id}:checked) #pp-browse-${id}{display:block}`), `${id} shows when its chip is picked`);++ assert.match(pick, /\.pick-head, \.pick-row \{ display: none; \}/, 'no chips where there is room');++ assert.doesNotMatch(css, /\.pick-pane[^{]*\{[^}]*display: none/, 'no pane is ever hidden (the owner, 2026-10-31)');const fold = css.slice(css.indexOf('/* The fold (the owner'));assert.match(fold, /\.fold-body \{ display: none; \}/, 'the fold body is closed by default');-- assert.match(fold, /\.fold-toggle:checked ~ \.fold-body \{ display: block; \}/, 'the title row opens it');assert.match(fold, /\.fold-toggle \{ display: none; \}/, 'the toggle is hidden where there is room');assert.match(fold, /\.fold-body \{ display: block; \}/, 'the body is open where there is room');});
@@ -47,25 +47,21 @@
@@ -47,25 +47,21 @@
.home-fold > summary span { display: none; }
.home-fold > summary span { display: none; }
}
}
-/* Pick (the owner's short-pages rule, 2026-10-30): on a phone the sections below the search are one at a time,
- picked with a row of chips. Radio inputs and :has(), no script: the chips and the one-section rule live under
- 640 px and only where :has() is understood, so a wider screen, or an older browser, shows every section and no
- chips. Every section stays in the page for the crawlers. */
+/* Pick: on a phone every pane is shown, stacked, each with its own heading; the chips are a row of links that
+ jump to a pane (the owner's rule, 2026-10-31: never hide content to shorten). A wide screen shows the panes as
+ before, with no chips. */
.pick-head, .pick-row { display: none; }
.pick-head, .pick-row { display: none; }
-@supports selector(:has(*)) {
- @media (max-width: 640px) {
- .pick-head { display: block; }
- .pick-head h2 { margin: 0 0 4px; font: 700 clamp(20px, 2.4vw, 28px)/1.2 var(--ov-font, 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif); letter-spacing: -.02em; }
- .pick-row { display: flex; gap: 8px; overflow-x: auto; margin: 10px -16px 0; padding: 2px 16px 4px; scrollbar-width: none; overscroll-behavior-x: contain; }
- .pick-row::-webkit-scrollbar { display: none; }
- .pick-row input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
- .pick-row label { display: inline-flex; align-items: center; flex: none; min-height: 44px; padding: 0 15px; border-radius: 999px; border: 1px solid var(--border, #1f2d47); color: var(--text-secondary, #96a7c2); font-size: .9rem; font-weight: 650; white-space: nowrap; cursor: pointer; }
- .pick-row input:checked + label { color: var(--text-primary, #e6edf7); border-color: var(--accent, #3b82f6); background: color-mix(in srgb, var(--accent, #3b82f6) 12%, transparent); }
- .pick-row input:focus-visible + label { outline: 2px solid var(--accent, #3b82f6); outline-offset: 2px; }
- .pick-pane { display: none; }
- /* The chip names the section, so the section's own heading gives way to it. */
- .pick-pane > .sc-sec > h2 { display: none; }
- }
+@media (max-width: 640px) {
+ .pick-bar { margin-top: 30px; }
+ .pick-head { display: block; }
+ .pick-head h2 { margin: 0 0 4px; font: 700 clamp(20px, 2.4vw, 28px)/1.2 var(--ov-font, 'Inter', system-ui, sans-serif); letter-spacing: -.02em; }
+ .pick-row { display: flex; gap: 8px; overflow-x: auto; margin: 10px -16px 0; padding: 2px 16px 4px; scrollbar-width: none; overscroll-behavior-x: contain; }
+ .pick-row::-webkit-scrollbar { display: none; }
+ .pick-chip { display: inline-flex; align-items: center; flex: none; min-height: 44px; padding: 0 15px; border-radius: 999px; border: 1px solid var(--border, #1f2d47); color: var(--text-secondary, #96a7c2); font-size: .9rem; font-weight: 650; white-space: nowrap; text-decoration: none; }
+ .pick-chip:hover, .pick-chip:focus-visible { color: var(--text-primary, #e6edf7); border-color: var(--accent, #3b82f6); }
+ .pick-chip:focus-visible { outline: 2px solid var(--accent, #3b82f6); outline-offset: 2px; }
+ .pick .pick-pane { scroll-margin-top: 72px; }
+ .pick .pick-pane + .pick-pane { margin-top: 26px; }
}
}
/* The fold (the owner's short-pages rule, 2026-10-30): a part a reader rarely needs. On a phone it is closed — the
/* The fold (the owner's short-pages rule, 2026-10-30): a part a reader rarely needs. On a phone it is closed — the
@@ -19,7 +19,7 @@ const { asyncRouter } = require('./router');
@@ -19,7 +19,7 @@ const { asyncRouter } = require('./router');
const { createDiscoveryRoutes, homeJsonLd } = require('./discovery');
const { createDiscoveryRoutes, homeJsonLd } = require('./discovery');
const { sameOrigin } = require('./principal');
const { sameOrigin } = require('./principal');
const { html, raw, table, notice, time } = require('../render/html');
const { html, raw, table, notice, time } = require('../render/html');
-const { foldBlock, pickBlock, pickRules } = require('../render/short');
+const { foldBlock, pickBlock } = require('../render/short');
const { send } = require('../render/layout');
const { send } = require('../render/layout');
const listing = require('../render/listing');
const listing = require('../render/listing');
const store = require('../jobs/store');
const store = require('../jobs/store');
@@ -198,7 +198,6 @@ ${listing.listingList(salaried, { sourceOf, empty: '' })}</section>`) });
@@ -198,7 +198,6 @@ ${listing.listingList(salaried, { sourceOf, empty: '' })}</section>`) });
styles: [showcase.STYLESHEET], localStyles: ['css/home.css'],
styles: [showcase.STYLESHEET], localStyles: ['css/home.css'],
// The rule that shows the picked section of the browse block is written for the page, because there is one
// The rule that shows the picked section of the browse block is written for the page, because there is one
// per section (CSS cannot pair a radio with a pane by index).
// per section (CSS cannot pair a radio with a pane by index).
- inlineStyles: ['@supports selector(:has(*)){@media (max-width:640px){' + pickRules('browse', panes.map((p) => p.id)) + '}}'],
body: html`${raw(hero)}
body: html`${raw(hero)}
${stats.length ? html`<ul class="home-stats" aria-label="${SITE_NAME} in numbers">${stats.map((x) => html`<li><a href="${x.href}"><b>${n(x.value)}</b><span>${x.label}</span></a></li>`)}</ul>` : ''}
${stats.length ? html`<ul class="home-stats" aria-label="${SITE_NAME} in numbers">${stats.map((x) => html`<li><a href="${x.href}"><b>${n(x.value)}</b><span>${x.label}</span></a></li>`)}</ul>` : ''}
<section class="sc-sec" id="search" aria-labelledby="h-search"><h2 id="h-search">Search the listings</h2>
<section class="sc-sec" id="search" aria-labelledby="h-search"><h2 id="h-search">Search the listings</h2>
@@ -42,19 +42,11 @@ function foldBlock({ id, head, html, bare = false }) {
@@ -42,19 +42,11 @@ function foldBlock({ id, head, html, bare = false }) {
function pickBlock({ key, label, head = '', panes, checked = '' }) {
function pickBlock({ key, label, head = '', panes, checked = '' }) {
if (!panes.length) return '';
if (!panes.length) return '';
const first = panes.find((p) => p.id === checked) ? checked : panes[0].id;
const first = panes.find((p) => p.id === checked) ? checked : panes[0].id;
- const chips = panes.map((p) => `<input type="radio" name="pick-${esc(key)}" id="pk-${esc(key)}-${esc(p.id)}" value="${esc(p.id)}"${p.id === first ? ' checked' : ''}><label for="pk-${esc(key)}-${esc(p.id)}">${esc(p.label)}</label>`).join('');
+ const chips = panes.map((p) => `<a class="pick-chip" href="#pp-${esc(key)}-${esc(p.id)}">${esc(p.label)}</a>`).join('');
const body = panes.map((p) => `<div class="pick-pane" id="pp-${esc(key)}-${esc(p.id)}">${str(p.html)}</div>`).join('');
const body = panes.map((p) => `<div class="pick-pane" id="pp-${esc(key)}-${esc(p.id)}">${str(p.html)}</div>`).join('');
- return `<div class="pick" id="pick-${esc(key)}"><div class="pick-bar"><div class="pick-head"><h2>${esc(head || label)}</h2></div><div class="pick-row" role="radiogroup" aria-label="${esc(label)}">${chips}</div></div><div class="pick-body">${body}</div></div>`;
+ return `<div class="pick" id="pick-${esc(key)}"><div class="pick-bar"><div class="pick-head"><h2>${esc(head || label)}</h2></div><nav class="pick-row" aria-label="${esc(label)}">${chips}</nav></div><div class="pick-body">${body}</div></div>`;
}
}
-/** The rule that shows the picked block of a pick block: one per block, so the CSS is written for the page. */
-function pickRule(key, id) {
- return `.pick:has(#pk-${key}-${id}:checked) #pp-${key}-${id}{display:block}`;
-}
-/** The rules for every block of a pick block, in the order they appear. */
-function pickRules(key, ids) {
- return ids.map((id) => pickRule(key, id)).join('');
-}
-module.exports = { foldBlock, pickBlock, pickRule, pickRules };
+module.exports = { foldBlock, pickBlock };
@@ -1,6 +1,5 @@
@@ -1,6 +1,5 @@
'use strict';
'use strict';
// The home on a phone (the owner's short-pages rule, 2026-10-30): the sections below the search are one at a time,
// The home on a phone (the owner's short-pages rule, 2026-10-30): the sections below the search are one at a time,
-// picked with a row of chips, and the parts a reader rarely needs fold closed. Radio inputs and :has() for the chips
// and a checkbox and a label for the folds, no script: every section and every part stays in the page for the
// and a checkbox and a label for the folds, no script: every section and every part stays in the page for the
// crawlers, and a wider screen shows them all and no chips.
// crawlers, and a wider screen shows them all and no chips.
const assert = require('assert');
const assert = require('assert');
@@ -30,13 +29,13 @@ const { boot, check, done } = require('./helpers/boot');
@@ -30,13 +29,13 @@ const { boot, check, done } = require('./helpers/boot');
assert.strictEqual(r.status, 200, r.text.slice(0, 300));
assert.strictEqual(r.status, 200, r.text.slice(0, 300));
const home = r.text;
const home = r.text;
assert.match(home, /<div class="pick" id="pick-browse">/, 'the browse block is on the home');
assert.match(home, /<div class="pick" id="pick-browse">/, 'the browse block is on the home');
- assert.match(home, /<div class="pick-row" role="radiogroup" aria-label="Browse the listings">/, 'the chips are on the home');
+ assert.match(home, /<nav class="pick-row" aria-label="Browse the listings">/, 'the chips are on the home');
// One chip per section, in the order the sections have, and the newest listings are the one a phone shows.
// One chip per section, in the order the sections have, and the newest listings are the one a phone shows.
- const chips = [...home.matchAll(/<input type="radio" name="pick-browse" id="pk-browse-([a-z]+)" value="\1"( checked)?><label for="pk-browse-\1">[^<]+<\/label>/g)];
+ const chips = [...home.matchAll(/<a class="pick-chip" href="#(?:pp-browse-)?([a-z]+)">()[^<]+<\/a>/g)];
const panes = [...home.matchAll(/<div class="pick-pane" id="pp-browse-([a-z]+)">/g)].map((m) => m[1]);
const panes = [...home.matchAll(/<div class="pick-pane" id="pp-browse-([a-z]+)">/g)].map((m) => m[1]);
assert.ok(panes.length >= 3, `the sections are all in the page (${panes.length})`);
assert.ok(panes.length >= 3, `the sections are all in the page (${panes.length})`);
assert.deepStrictEqual(chips.map((m) => m[1]), panes, 'one chip per section, in the same order');
assert.deepStrictEqual(chips.map((m) => m[1]), panes, 'one chip per section, in the same order');
- assert.deepStrictEqual(chips.filter((m) => m[2]).map((m) => m[1]), ['latest'], 'the newest listings are picked first');
+ assert.ok(!/type="radio"/.test(home), 'no chip is a radio: nothing is picked, every pane shows');
// The sections themselves are in the page, not removed.
// The sections themselves are in the page, not removed.
for (const h of ['Browse by field', 'Jobs by city', 'Latest remote jobs', 'Newest jobs that state the pay', 'Companies with the most openings']) {
for (const h of ['Browse by field', 'Jobs by city', 'Latest remote jobs', 'Newest jobs that state the pay', 'Companies with the most openings']) {
assert.ok(home.includes(`>${h}</h2>`), `${h} is in the page`);
assert.ok(home.includes(`>${h}</h2>`), `${h} is in the page`);
@@ -59,20 +58,14 @@ const { boot, check, done } = require('./helpers/boot');
@@ -59,20 +58,14 @@ const { boot, check, done } = require('./helpers/boot');
assert.match(home, /<div class="home-faq">/, 'the questions are in the page');
assert.match(home, /<div class="home-faq">/, 'the questions are in the page');
assert.match(home, /class="sc-net"/, 'the rest of OpenVibe is in the page');
assert.match(home, /class="sc-net"/, 'the rest of OpenVibe is in the page');
assert.match(home, /data-ov-shipped="list"/, 'what shipped is in the page');
assert.match(home, /data-ov-shipped="list"/, 'what shipped is in the page');
- // The CSS: the chips and their rule under 640 px and only with :has(); the fold closed on a phone, open where
// there is room.
// there is room.
const css = fs.readFileSync(path.join(__dirname, '..', 'public', 'css', 'home.css'), 'utf8');
const css = fs.readFileSync(path.join(__dirname, '..', 'public', 'css', 'home.css'), 'utf8');
- const pick = css.slice(css.indexOf('/* Pick (the owner'));
+ const pick = css.slice(css.indexOf('/* Pick: on a phone every pane is shown'));
assert.ok(pick.length > 0, 'the pick rules are in home.css');
assert.ok(pick.length > 0, 'the pick rules are in home.css');
- assert.match(pick, /\.pick-head, \.pick-row \{ display: none; \}/, 'the chips are hidden by default');
- assert.match(pick, /@supports selector\(:has\(\*\)\) \{\n @media \(max-width: 640px\) \{/, 'the chips are only under 640 px and only with :has()');
- assert.match(pick, /\.pick-pane \{ display: none; \}/, 'one section at a time');
- const head = home.slice(home.indexOf('<style>@supports selector(:has(*))'));
- assert.ok(head.startsWith('<style>@supports selector(:has(*))'), 'the rule that shows the picked section is on the page');
- for (const id of panes) assert.ok(head.includes(`.pick:has(#pk-browse-${id}:checked) #pp-browse-${id}{display:block}`), `${id} shows when its chip is picked`);
+ assert.match(pick, /\.pick-head, \.pick-row \{ display: none; \}/, 'no chips where there is room');
+ assert.doesNotMatch(css, /\.pick-pane[^{]*\{[^}]*display: none/, 'no pane is ever hidden (the owner, 2026-10-31)');
const fold = css.slice(css.indexOf('/* The fold (the owner'));
const fold = css.slice(css.indexOf('/* The fold (the owner'));
assert.match(fold, /\.fold-body \{ display: none; \}/, 'the fold body is closed by default');
assert.match(fold, /\.fold-body \{ display: none; \}/, 'the fold body is closed by default');
- assert.match(fold, /\.fold-toggle:checked ~ \.fold-body \{ display: block; \}/, 'the title row opens it');
assert.match(fold, /\.fold-toggle \{ display: none; \}/, 'the toggle is hidden where there is room');
assert.match(fold, /\.fold-toggle \{ display: none; \}/, 'the toggle is hidden where there is room');
assert.match(fold, /\.fold-body \{ display: block; \}/, 'the body is open where there is room');
assert.match(fold, /\.fold-body \{ display: block; \}/, 'the body is open where there is room');
});
});