// Make a refresh land back where you were — accurately. // // Turbo Drive is off site-wide (see app.js), so a refresh is a full browser // load. The browser restores the scroll position early in that load — before // the Manrope web fonts swap in and reflow the header,

and result count // above the product grid — so it settles a bit too low. We record the position // ourselves and re-apply it once the layout has actually stopped moving. // // Separately: drop focus on the way out. Otherwise the browser re-focuses // whatever filter control was active and scrolls it into view on reload, and // that sidebar stacks below the grid on narrow screens — hence the jump to the // bottom. // // The real fix for the drift is preloading the above-the-fold font weights so // there's no reflow to chase; this keeps the restore correct until then, and // harmless after. const key = 'scrollY:' + location.pathname + location.search let frame = 0 window.addEventListener( 'scroll', () => { if (frame) return frame = requestAnimationFrame(() => { frame = 0 try { sessionStorage.setItem(key, String(Math.round(window.scrollY))) } catch {} }) }, { passive: true }, ) window.addEventListener('pagehide', () => { const el = document.activeElement if (el && el !== document.body) el.blur() }) // Only reloads and back/forward should resume a position; a fresh visit to the // page starts where it naturally would. const [nav] = performance.getEntriesByType('navigation') if (nav && (nav.type === 'reload' || nav.type === 'back_forward')) { let saved = null try { saved = sessionStorage.getItem(key) } catch {} if (saved !== null) { const y = Number(saved) const apply = () => window.scrollTo(0, y) window.addEventListener( 'load', () => { apply() // Fonts (and any late above-the-fold image) can still nudge // layout a frame or two after load — re-apply once they settle. document.fonts?.ready.then(() => requestAnimationFrame(apply)) }, { once: true }, ) } }