From eb672bd664fd389200aae44a8d060387778c62c6 Mon Sep 17 00:00:00 2001 From: LucaP Date: Wed, 2 Sep 2026 06:09:44 +0300 Subject: [PATCH] fix: keep portfolio panels above journey world --- src/styles/world.css | 4 +++ tests/browser/scene-controls.spec.ts | 37 ++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/styles/world.css b/src/styles/world.css index 8680949..6234207 100644 --- a/src/styles/world.css +++ b/src/styles/world.css @@ -49,6 +49,10 @@ background: rgb(7 13 23 / 96%); } +.portfolio-main { + isolation: isolate; +} + .portfolio-section { background: rgb(16 23 34 / 94%); } diff --git a/tests/browser/scene-controls.spec.ts b/tests/browser/scene-controls.spec.ts index b1b1b0c..0900a4f 100644 --- a/tests/browser/scene-controls.spec.ts +++ b/tests/browser/scene-controls.spec.ts @@ -41,6 +41,43 @@ test('keeps the desktop identity and navigation in a paint layer above the world expect(layers.headerOpacity).toBeGreaterThanOrEqual(0.94); }); +test('keeps a scrolled content panel in a geometry-safe paint layer above the world', async ({ page, distUrl }) => { + await page.setViewportSize({ width: 1440, height: 900 }); + await page.goto(distUrl, { waitUntil: 'domcontentloaded' }); + await page.locator('nav a[href="#profile"]').click(); + + const layers = await page.evaluate(() => { + const world = document.querySelector('.journey-world'); + const main = document.querySelector('.portfolio-main'); + const panel = document.querySelector('#profile'); + const heading = document.querySelector('#profile-heading'); + if (!world || !main || !panel || !heading) throw new Error('Missing scrolled panel structure'); + const mainStyle = getComputedStyle(main); + const panelStyle = getComputedStyle(panel); + const headingRect = heading.getBoundingClientRect(); + return { + worldZ: Number(getComputedStyle(world).zIndex), + mainIsolation: mainStyle.isolation, + mainPosition: mainStyle.position, + headingVisible: + headingRect.width > 0 + && headingRect.height > 0 + && headingRect.bottom > 0 + && headingRect.top < window.innerHeight, + panelOpacity: Number.parseFloat(panelStyle.backgroundColor.match(/[\d.]+(?=\))/gu)?.at(-1) ?? '1'), + }; + }); + + expect(layers).toMatchObject({ + worldZ: 0, + mainIsolation: 'isolate', + mainPosition: 'static', + headingVisible: true, + }); + expect(layers.panelOpacity).toBeGreaterThanOrEqual(0.94); + await expect(page).toHaveURL(`${distUrl}/#profile`); +}); + test('provides native motion and quality controls with visible state', async ({ page, distUrl }) => { await page.goto(distUrl, { waitUntil: 'domcontentloaded' });