Experience tuning: mood-through-morphs fix, auto-advance, label wrap, binaural candidates #33

Merged
benstull merged 10 commits from feat/experience-tuning into main 2026-07-03 01:00:22 +00:00
2 changed files with 30 additions and 2 deletions
Showing only changes of commit 88ebb07578 - Show all commits
+25
View File
@@ -0,0 +1,25 @@
import { test, expect, Page } from "@playwright/test";
// Guard: the "Video speed" control label must stay on ONE line in the Output panel
// (it was wrapping to two rows at the old panel width).
async function enter(page: Page) {
await page.goto("/");
await page.waitForFunction(() => (window as any).__hefReady === true, null, { timeout: 45_000 });
await page.locator("#welcome-launch").click();
await page.waitForSelector("#welcome", { state: "detached", timeout: 10_000 });
}
test('the "Video speed" label does not wrap to a second line', async ({ page }) => {
await enter(page);
const info = await page.evaluate(() => {
const span = document.querySelector('.panel .play-speed span[data-i18n="speed.label"]') as HTMLElement;
const cs = getComputedStyle(span);
let lh = parseFloat(cs.lineHeight);
if (Number.isNaN(lh)) lh = parseFloat(cs.fontSize) * 1.3; // "normal"
return { text: span.textContent, height: span.getBoundingClientRect().height, lineHeight: lh };
});
expect(info.text).toBe("Video speed");
// A wrapped label is ~2× a single line; allow slack but stay well under two lines.
expect(info.height).toBeLessThan(info.lineHeight * 1.6);
});
+5 -2
View File
@@ -97,7 +97,7 @@ main { display: flex; gap: 1rem; padding: 1rem; flex-wrap: wrap; align-items: fl
.audio-status { margin-top: 0.5rem; font: 11px/1.4 monospace; color: #9ab; }
.audio-status.playing { color: #4e9; }
.audio-status.blocked { color: #f97; }
.panel { flex: 0 0 280px; display: flex; flex-direction: column; gap: 0.8rem;
.panel { flex: 0 0 300px; display: flex; flex-direction: column; gap: 0.8rem;
max-height: calc(100vh - 2rem); overflow-y: auto;
position: sticky; top: 1rem; }
/* The control panel stays hidden behind the welcome screen and appears only once
@@ -151,7 +151,10 @@ input[type=range], select { width: 100%; }
/* Audio level dial (010): label · slider · value on one row, matching the switch look. */
.audio-level { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.45rem;
color: #9af; font-weight: 600; letter-spacing: 0.3px; }
.audio-level input[type=range] { flex: 1; width: auto; }
/* Keep the control label on one line ("Video speed" was wrapping); let the range
shrink (min-width:0) instead of pushing the label to a second row. */
.audio-level > span:first-child { white-space: nowrap; }
.audio-level input[type=range] { flex: 1; width: auto; min-width: 0; }
#audio-level-val { font-variant-numeric: tabular-nums; min-width: 1.2em; text-align: right; }
/* Playback speed (2×…2×) reuses the audio-level row look; wider value field for the sign + decimals. */
#play-speed-val, #welcome-play-speed-val { font-variant-numeric: tabular-nums; min-width: 3.4em; text-align: right; }