diff --git a/.agents/skills/impeccable/scripts/live-browser.js b/.agents/skills/impeccable/scripts/live-browser.js index 71ec5ab75..109d0d58e 100644 --- a/.agents/skills/impeccable/scripts/live-browser.js +++ b/.agents/skills/impeccable/scripts/live-browser.js @@ -121,15 +121,23 @@ } // Pre-empt the browser: apply manual scroll restoration and jump to the - // saved scrollY at script-parse time (before DOMContentLoaded). If we - // wait until init(), the browser has already begun animating its own - // restore — especially bad when `scroll-behavior: smooth` is set on html. + // saved scrollY at script-parse time. Retries on fonts.ready and load + // are essential: scrollTo(y) clamps to the current document.scrollHeight, + // which is often hundreds of pixels short of the final value until + // async-loaded fonts swap in and reflow. try { history.scrollRestoration = 'manual'; const savedY = readScrollY(); - if (savedY != null && Math.abs(window.scrollY - savedY) > 0.5) { - console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); - window.scrollTo({ top: savedY, left: 0, behavior: 'instant' }); + if (savedY != null) { + const apply = () => { + if (Math.abs(window.scrollY - savedY) > 0.5) { + console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); + window.scrollTo(0, savedY); + } + }; + apply(); + if (document.fonts?.ready) document.fonts.ready.then(apply).catch(() => {}); + window.addEventListener('load', apply, { once: true }); } } catch {} diff --git a/.agents/skills/impeccable/scripts/live-inject.mjs b/.agents/skills/impeccable/scripts/live-inject.mjs index 37a16f1ea..9bbc345ac 100644 --- a/.agents/skills/impeccable/scripts/live-inject.mjs +++ b/.agents/skills/impeccable/scripts/live-inject.mjs @@ -137,27 +137,8 @@ function commentClose(syntax) { return syntax === 'jsx' ? '*/}' : '-->'; } function buildTagBlock(syntax, port) { const open = commentOpen(syntax); const close = commentClose(syntax); - // Inline pre-restore: runs before the external live.js is fetched. Sets - // scrollRestoration='manual' and jumps to the saved scrollY synchronously - // during HTML parse, beating the browser's animated reload-restore. - // - // Retries on fonts.ready and load are essential: scrollTo(y) clamps to - // the document's current scrollHeight, which is often hundreds of - // pixels short of the final value until async-loaded fonts swap in. - // Hardcoded key matches live-browser.js: PREFIX ('impeccable-live') + - // LS_KEY suffix ('-session') + SCROLL_KEY_SUFFIX ('-scroll'). - const preRestore = - ''; return ( open + ' ' + MARKER_OPEN_TEXT + ' ' + close + '\n' + - preRestore + '\n' + '\n' + open + ' ' + MARKER_CLOSE_TEXT + ' ' + close + '\n' ); diff --git a/.claude/skills/impeccable/scripts/live-browser.js b/.claude/skills/impeccable/scripts/live-browser.js index 71ec5ab75..109d0d58e 100644 --- a/.claude/skills/impeccable/scripts/live-browser.js +++ b/.claude/skills/impeccable/scripts/live-browser.js @@ -121,15 +121,23 @@ } // Pre-empt the browser: apply manual scroll restoration and jump to the - // saved scrollY at script-parse time (before DOMContentLoaded). If we - // wait until init(), the browser has already begun animating its own - // restore — especially bad when `scroll-behavior: smooth` is set on html. + // saved scrollY at script-parse time. Retries on fonts.ready and load + // are essential: scrollTo(y) clamps to the current document.scrollHeight, + // which is often hundreds of pixels short of the final value until + // async-loaded fonts swap in and reflow. try { history.scrollRestoration = 'manual'; const savedY = readScrollY(); - if (savedY != null && Math.abs(window.scrollY - savedY) > 0.5) { - console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); - window.scrollTo({ top: savedY, left: 0, behavior: 'instant' }); + if (savedY != null) { + const apply = () => { + if (Math.abs(window.scrollY - savedY) > 0.5) { + console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); + window.scrollTo(0, savedY); + } + }; + apply(); + if (document.fonts?.ready) document.fonts.ready.then(apply).catch(() => {}); + window.addEventListener('load', apply, { once: true }); } } catch {} diff --git a/.claude/skills/impeccable/scripts/live-inject.mjs b/.claude/skills/impeccable/scripts/live-inject.mjs index 37a16f1ea..9bbc345ac 100644 --- a/.claude/skills/impeccable/scripts/live-inject.mjs +++ b/.claude/skills/impeccable/scripts/live-inject.mjs @@ -137,27 +137,8 @@ function commentClose(syntax) { return syntax === 'jsx' ? '*/}' : '-->'; } function buildTagBlock(syntax, port) { const open = commentOpen(syntax); const close = commentClose(syntax); - // Inline pre-restore: runs before the external live.js is fetched. Sets - // scrollRestoration='manual' and jumps to the saved scrollY synchronously - // during HTML parse, beating the browser's animated reload-restore. - // - // Retries on fonts.ready and load are essential: scrollTo(y) clamps to - // the document's current scrollHeight, which is often hundreds of - // pixels short of the final value until async-loaded fonts swap in. - // Hardcoded key matches live-browser.js: PREFIX ('impeccable-live') + - // LS_KEY suffix ('-session') + SCROLL_KEY_SUFFIX ('-scroll'). - const preRestore = - ''; return ( open + ' ' + MARKER_OPEN_TEXT + ' ' + close + '\n' + - preRestore + '\n' + '\n' + open + ' ' + MARKER_CLOSE_TEXT + ' ' + close + '\n' ); diff --git a/.cursor/skills/impeccable/scripts/live-browser.js b/.cursor/skills/impeccable/scripts/live-browser.js index 71ec5ab75..109d0d58e 100644 --- a/.cursor/skills/impeccable/scripts/live-browser.js +++ b/.cursor/skills/impeccable/scripts/live-browser.js @@ -121,15 +121,23 @@ } // Pre-empt the browser: apply manual scroll restoration and jump to the - // saved scrollY at script-parse time (before DOMContentLoaded). If we - // wait until init(), the browser has already begun animating its own - // restore — especially bad when `scroll-behavior: smooth` is set on html. + // saved scrollY at script-parse time. Retries on fonts.ready and load + // are essential: scrollTo(y) clamps to the current document.scrollHeight, + // which is often hundreds of pixels short of the final value until + // async-loaded fonts swap in and reflow. try { history.scrollRestoration = 'manual'; const savedY = readScrollY(); - if (savedY != null && Math.abs(window.scrollY - savedY) > 0.5) { - console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); - window.scrollTo({ top: savedY, left: 0, behavior: 'instant' }); + if (savedY != null) { + const apply = () => { + if (Math.abs(window.scrollY - savedY) > 0.5) { + console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); + window.scrollTo(0, savedY); + } + }; + apply(); + if (document.fonts?.ready) document.fonts.ready.then(apply).catch(() => {}); + window.addEventListener('load', apply, { once: true }); } } catch {} diff --git a/.cursor/skills/impeccable/scripts/live-inject.mjs b/.cursor/skills/impeccable/scripts/live-inject.mjs index 37a16f1ea..9bbc345ac 100644 --- a/.cursor/skills/impeccable/scripts/live-inject.mjs +++ b/.cursor/skills/impeccable/scripts/live-inject.mjs @@ -137,27 +137,8 @@ function commentClose(syntax) { return syntax === 'jsx' ? '*/}' : '-->'; } function buildTagBlock(syntax, port) { const open = commentOpen(syntax); const close = commentClose(syntax); - // Inline pre-restore: runs before the external live.js is fetched. Sets - // scrollRestoration='manual' and jumps to the saved scrollY synchronously - // during HTML parse, beating the browser's animated reload-restore. - // - // Retries on fonts.ready and load are essential: scrollTo(y) clamps to - // the document's current scrollHeight, which is often hundreds of - // pixels short of the final value until async-loaded fonts swap in. - // Hardcoded key matches live-browser.js: PREFIX ('impeccable-live') + - // LS_KEY suffix ('-session') + SCROLL_KEY_SUFFIX ('-scroll'). - const preRestore = - ''; return ( open + ' ' + MARKER_OPEN_TEXT + ' ' + close + '\n' + - preRestore + '\n' + '\n' + open + ' ' + MARKER_CLOSE_TEXT + ' ' + close + '\n' ); diff --git a/.gemini/skills/impeccable/scripts/live-browser.js b/.gemini/skills/impeccable/scripts/live-browser.js index 71ec5ab75..109d0d58e 100644 --- a/.gemini/skills/impeccable/scripts/live-browser.js +++ b/.gemini/skills/impeccable/scripts/live-browser.js @@ -121,15 +121,23 @@ } // Pre-empt the browser: apply manual scroll restoration and jump to the - // saved scrollY at script-parse time (before DOMContentLoaded). If we - // wait until init(), the browser has already begun animating its own - // restore — especially bad when `scroll-behavior: smooth` is set on html. + // saved scrollY at script-parse time. Retries on fonts.ready and load + // are essential: scrollTo(y) clamps to the current document.scrollHeight, + // which is often hundreds of pixels short of the final value until + // async-loaded fonts swap in and reflow. try { history.scrollRestoration = 'manual'; const savedY = readScrollY(); - if (savedY != null && Math.abs(window.scrollY - savedY) > 0.5) { - console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); - window.scrollTo({ top: savedY, left: 0, behavior: 'instant' }); + if (savedY != null) { + const apply = () => { + if (Math.abs(window.scrollY - savedY) > 0.5) { + console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); + window.scrollTo(0, savedY); + } + }; + apply(); + if (document.fonts?.ready) document.fonts.ready.then(apply).catch(() => {}); + window.addEventListener('load', apply, { once: true }); } } catch {} diff --git a/.gemini/skills/impeccable/scripts/live-inject.mjs b/.gemini/skills/impeccable/scripts/live-inject.mjs index 37a16f1ea..9bbc345ac 100644 --- a/.gemini/skills/impeccable/scripts/live-inject.mjs +++ b/.gemini/skills/impeccable/scripts/live-inject.mjs @@ -137,27 +137,8 @@ function commentClose(syntax) { return syntax === 'jsx' ? '*/}' : '-->'; } function buildTagBlock(syntax, port) { const open = commentOpen(syntax); const close = commentClose(syntax); - // Inline pre-restore: runs before the external live.js is fetched. Sets - // scrollRestoration='manual' and jumps to the saved scrollY synchronously - // during HTML parse, beating the browser's animated reload-restore. - // - // Retries on fonts.ready and load are essential: scrollTo(y) clamps to - // the document's current scrollHeight, which is often hundreds of - // pixels short of the final value until async-loaded fonts swap in. - // Hardcoded key matches live-browser.js: PREFIX ('impeccable-live') + - // LS_KEY suffix ('-session') + SCROLL_KEY_SUFFIX ('-scroll'). - const preRestore = - ''; return ( open + ' ' + MARKER_OPEN_TEXT + ' ' + close + '\n' + - preRestore + '\n' + '\n' + open + ' ' + MARKER_CLOSE_TEXT + ' ' + close + '\n' ); diff --git a/.github/skills/impeccable/scripts/live-browser.js b/.github/skills/impeccable/scripts/live-browser.js index 71ec5ab75..109d0d58e 100644 --- a/.github/skills/impeccable/scripts/live-browser.js +++ b/.github/skills/impeccable/scripts/live-browser.js @@ -121,15 +121,23 @@ } // Pre-empt the browser: apply manual scroll restoration and jump to the - // saved scrollY at script-parse time (before DOMContentLoaded). If we - // wait until init(), the browser has already begun animating its own - // restore — especially bad when `scroll-behavior: smooth` is set on html. + // saved scrollY at script-parse time. Retries on fonts.ready and load + // are essential: scrollTo(y) clamps to the current document.scrollHeight, + // which is often hundreds of pixels short of the final value until + // async-loaded fonts swap in and reflow. try { history.scrollRestoration = 'manual'; const savedY = readScrollY(); - if (savedY != null && Math.abs(window.scrollY - savedY) > 0.5) { - console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); - window.scrollTo({ top: savedY, left: 0, behavior: 'instant' }); + if (savedY != null) { + const apply = () => { + if (Math.abs(window.scrollY - savedY) > 0.5) { + console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); + window.scrollTo(0, savedY); + } + }; + apply(); + if (document.fonts?.ready) document.fonts.ready.then(apply).catch(() => {}); + window.addEventListener('load', apply, { once: true }); } } catch {} diff --git a/.github/skills/impeccable/scripts/live-inject.mjs b/.github/skills/impeccable/scripts/live-inject.mjs index 37a16f1ea..9bbc345ac 100644 --- a/.github/skills/impeccable/scripts/live-inject.mjs +++ b/.github/skills/impeccable/scripts/live-inject.mjs @@ -137,27 +137,8 @@ function commentClose(syntax) { return syntax === 'jsx' ? '*/}' : '-->'; } function buildTagBlock(syntax, port) { const open = commentOpen(syntax); const close = commentClose(syntax); - // Inline pre-restore: runs before the external live.js is fetched. Sets - // scrollRestoration='manual' and jumps to the saved scrollY synchronously - // during HTML parse, beating the browser's animated reload-restore. - // - // Retries on fonts.ready and load are essential: scrollTo(y) clamps to - // the document's current scrollHeight, which is often hundreds of - // pixels short of the final value until async-loaded fonts swap in. - // Hardcoded key matches live-browser.js: PREFIX ('impeccable-live') + - // LS_KEY suffix ('-session') + SCROLL_KEY_SUFFIX ('-scroll'). - const preRestore = - ''; return ( open + ' ' + MARKER_OPEN_TEXT + ' ' + close + '\n' + - preRestore + '\n' + '\n' + open + ' ' + MARKER_CLOSE_TEXT + ' ' + close + '\n' ); diff --git a/.kiro/skills/impeccable/scripts/live-browser.js b/.kiro/skills/impeccable/scripts/live-browser.js index 71ec5ab75..109d0d58e 100644 --- a/.kiro/skills/impeccable/scripts/live-browser.js +++ b/.kiro/skills/impeccable/scripts/live-browser.js @@ -121,15 +121,23 @@ } // Pre-empt the browser: apply manual scroll restoration and jump to the - // saved scrollY at script-parse time (before DOMContentLoaded). If we - // wait until init(), the browser has already begun animating its own - // restore — especially bad when `scroll-behavior: smooth` is set on html. + // saved scrollY at script-parse time. Retries on fonts.ready and load + // are essential: scrollTo(y) clamps to the current document.scrollHeight, + // which is often hundreds of pixels short of the final value until + // async-loaded fonts swap in and reflow. try { history.scrollRestoration = 'manual'; const savedY = readScrollY(); - if (savedY != null && Math.abs(window.scrollY - savedY) > 0.5) { - console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); - window.scrollTo({ top: savedY, left: 0, behavior: 'instant' }); + if (savedY != null) { + const apply = () => { + if (Math.abs(window.scrollY - savedY) > 0.5) { + console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); + window.scrollTo(0, savedY); + } + }; + apply(); + if (document.fonts?.ready) document.fonts.ready.then(apply).catch(() => {}); + window.addEventListener('load', apply, { once: true }); } } catch {} diff --git a/.kiro/skills/impeccable/scripts/live-inject.mjs b/.kiro/skills/impeccable/scripts/live-inject.mjs index 37a16f1ea..9bbc345ac 100644 --- a/.kiro/skills/impeccable/scripts/live-inject.mjs +++ b/.kiro/skills/impeccable/scripts/live-inject.mjs @@ -137,27 +137,8 @@ function commentClose(syntax) { return syntax === 'jsx' ? '*/}' : '-->'; } function buildTagBlock(syntax, port) { const open = commentOpen(syntax); const close = commentClose(syntax); - // Inline pre-restore: runs before the external live.js is fetched. Sets - // scrollRestoration='manual' and jumps to the saved scrollY synchronously - // during HTML parse, beating the browser's animated reload-restore. - // - // Retries on fonts.ready and load are essential: scrollTo(y) clamps to - // the document's current scrollHeight, which is often hundreds of - // pixels short of the final value until async-loaded fonts swap in. - // Hardcoded key matches live-browser.js: PREFIX ('impeccable-live') + - // LS_KEY suffix ('-session') + SCROLL_KEY_SUFFIX ('-scroll'). - const preRestore = - ''; return ( open + ' ' + MARKER_OPEN_TEXT + ' ' + close + '\n' + - preRestore + '\n' + '\n' + open + ' ' + MARKER_CLOSE_TEXT + ' ' + close + '\n' ); diff --git a/.opencode/skills/impeccable/scripts/live-browser.js b/.opencode/skills/impeccable/scripts/live-browser.js index 71ec5ab75..109d0d58e 100644 --- a/.opencode/skills/impeccable/scripts/live-browser.js +++ b/.opencode/skills/impeccable/scripts/live-browser.js @@ -121,15 +121,23 @@ } // Pre-empt the browser: apply manual scroll restoration and jump to the - // saved scrollY at script-parse time (before DOMContentLoaded). If we - // wait until init(), the browser has already begun animating its own - // restore — especially bad when `scroll-behavior: smooth` is set on html. + // saved scrollY at script-parse time. Retries on fonts.ready and load + // are essential: scrollTo(y) clamps to the current document.scrollHeight, + // which is often hundreds of pixels short of the final value until + // async-loaded fonts swap in and reflow. try { history.scrollRestoration = 'manual'; const savedY = readScrollY(); - if (savedY != null && Math.abs(window.scrollY - savedY) > 0.5) { - console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); - window.scrollTo({ top: savedY, left: 0, behavior: 'instant' }); + if (savedY != null) { + const apply = () => { + if (Math.abs(window.scrollY - savedY) > 0.5) { + console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); + window.scrollTo(0, savedY); + } + }; + apply(); + if (document.fonts?.ready) document.fonts.ready.then(apply).catch(() => {}); + window.addEventListener('load', apply, { once: true }); } } catch {} diff --git a/.opencode/skills/impeccable/scripts/live-inject.mjs b/.opencode/skills/impeccable/scripts/live-inject.mjs index 37a16f1ea..9bbc345ac 100644 --- a/.opencode/skills/impeccable/scripts/live-inject.mjs +++ b/.opencode/skills/impeccable/scripts/live-inject.mjs @@ -137,27 +137,8 @@ function commentClose(syntax) { return syntax === 'jsx' ? '*/}' : '-->'; } function buildTagBlock(syntax, port) { const open = commentOpen(syntax); const close = commentClose(syntax); - // Inline pre-restore: runs before the external live.js is fetched. Sets - // scrollRestoration='manual' and jumps to the saved scrollY synchronously - // during HTML parse, beating the browser's animated reload-restore. - // - // Retries on fonts.ready and load are essential: scrollTo(y) clamps to - // the document's current scrollHeight, which is often hundreds of - // pixels short of the final value until async-loaded fonts swap in. - // Hardcoded key matches live-browser.js: PREFIX ('impeccable-live') + - // LS_KEY suffix ('-session') + SCROLL_KEY_SUFFIX ('-scroll'). - const preRestore = - ''; return ( open + ' ' + MARKER_OPEN_TEXT + ' ' + close + '\n' + - preRestore + '\n' + '\n' + open + ' ' + MARKER_CLOSE_TEXT + ' ' + close + '\n' ); diff --git a/.pi/skills/impeccable/scripts/live-browser.js b/.pi/skills/impeccable/scripts/live-browser.js index 71ec5ab75..109d0d58e 100644 --- a/.pi/skills/impeccable/scripts/live-browser.js +++ b/.pi/skills/impeccable/scripts/live-browser.js @@ -121,15 +121,23 @@ } // Pre-empt the browser: apply manual scroll restoration and jump to the - // saved scrollY at script-parse time (before DOMContentLoaded). If we - // wait until init(), the browser has already begun animating its own - // restore — especially bad when `scroll-behavior: smooth` is set on html. + // saved scrollY at script-parse time. Retries on fonts.ready and load + // are essential: scrollTo(y) clamps to the current document.scrollHeight, + // which is often hundreds of pixels short of the final value until + // async-loaded fonts swap in and reflow. try { history.scrollRestoration = 'manual'; const savedY = readScrollY(); - if (savedY != null && Math.abs(window.scrollY - savedY) > 0.5) { - console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); - window.scrollTo({ top: savedY, left: 0, behavior: 'instant' }); + if (savedY != null) { + const apply = () => { + if (Math.abs(window.scrollY - savedY) > 0.5) { + console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); + window.scrollTo(0, savedY); + } + }; + apply(); + if (document.fonts?.ready) document.fonts.ready.then(apply).catch(() => {}); + window.addEventListener('load', apply, { once: true }); } } catch {} diff --git a/.pi/skills/impeccable/scripts/live-inject.mjs b/.pi/skills/impeccable/scripts/live-inject.mjs index 37a16f1ea..9bbc345ac 100644 --- a/.pi/skills/impeccable/scripts/live-inject.mjs +++ b/.pi/skills/impeccable/scripts/live-inject.mjs @@ -137,27 +137,8 @@ function commentClose(syntax) { return syntax === 'jsx' ? '*/}' : '-->'; } function buildTagBlock(syntax, port) { const open = commentOpen(syntax); const close = commentClose(syntax); - // Inline pre-restore: runs before the external live.js is fetched. Sets - // scrollRestoration='manual' and jumps to the saved scrollY synchronously - // during HTML parse, beating the browser's animated reload-restore. - // - // Retries on fonts.ready and load are essential: scrollTo(y) clamps to - // the document's current scrollHeight, which is often hundreds of - // pixels short of the final value until async-loaded fonts swap in. - // Hardcoded key matches live-browser.js: PREFIX ('impeccable-live') + - // LS_KEY suffix ('-session') + SCROLL_KEY_SUFFIX ('-scroll'). - const preRestore = - ''; return ( open + ' ' + MARKER_OPEN_TEXT + ' ' + close + '\n' + - preRestore + '\n' + '\n' + open + ' ' + MARKER_CLOSE_TEXT + ' ' + close + '\n' ); diff --git a/.rovodev/skills/impeccable/scripts/live-browser.js b/.rovodev/skills/impeccable/scripts/live-browser.js index 71ec5ab75..109d0d58e 100644 --- a/.rovodev/skills/impeccable/scripts/live-browser.js +++ b/.rovodev/skills/impeccable/scripts/live-browser.js @@ -121,15 +121,23 @@ } // Pre-empt the browser: apply manual scroll restoration and jump to the - // saved scrollY at script-parse time (before DOMContentLoaded). If we - // wait until init(), the browser has already begun animating its own - // restore — especially bad when `scroll-behavior: smooth` is set on html. + // saved scrollY at script-parse time. Retries on fonts.ready and load + // are essential: scrollTo(y) clamps to the current document.scrollHeight, + // which is often hundreds of pixels short of the final value until + // async-loaded fonts swap in and reflow. try { history.scrollRestoration = 'manual'; const savedY = readScrollY(); - if (savedY != null && Math.abs(window.scrollY - savedY) > 0.5) { - console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); - window.scrollTo({ top: savedY, left: 0, behavior: 'instant' }); + if (savedY != null) { + const apply = () => { + if (Math.abs(window.scrollY - savedY) > 0.5) { + console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); + window.scrollTo(0, savedY); + } + }; + apply(); + if (document.fonts?.ready) document.fonts.ready.then(apply).catch(() => {}); + window.addEventListener('load', apply, { once: true }); } } catch {} diff --git a/.rovodev/skills/impeccable/scripts/live-inject.mjs b/.rovodev/skills/impeccable/scripts/live-inject.mjs index 37a16f1ea..9bbc345ac 100644 --- a/.rovodev/skills/impeccable/scripts/live-inject.mjs +++ b/.rovodev/skills/impeccable/scripts/live-inject.mjs @@ -137,27 +137,8 @@ function commentClose(syntax) { return syntax === 'jsx' ? '*/}' : '-->'; } function buildTagBlock(syntax, port) { const open = commentOpen(syntax); const close = commentClose(syntax); - // Inline pre-restore: runs before the external live.js is fetched. Sets - // scrollRestoration='manual' and jumps to the saved scrollY synchronously - // during HTML parse, beating the browser's animated reload-restore. - // - // Retries on fonts.ready and load are essential: scrollTo(y) clamps to - // the document's current scrollHeight, which is often hundreds of - // pixels short of the final value until async-loaded fonts swap in. - // Hardcoded key matches live-browser.js: PREFIX ('impeccable-live') + - // LS_KEY suffix ('-session') + SCROLL_KEY_SUFFIX ('-scroll'). - const preRestore = - ''; return ( open + ' ' + MARKER_OPEN_TEXT + ' ' + close + '\n' + - preRestore + '\n' + '\n' + open + ' ' + MARKER_CLOSE_TEXT + ' ' + close + '\n' ); diff --git a/.trae-cn/skills/impeccable/scripts/live-browser.js b/.trae-cn/skills/impeccable/scripts/live-browser.js index 71ec5ab75..109d0d58e 100644 --- a/.trae-cn/skills/impeccable/scripts/live-browser.js +++ b/.trae-cn/skills/impeccable/scripts/live-browser.js @@ -121,15 +121,23 @@ } // Pre-empt the browser: apply manual scroll restoration and jump to the - // saved scrollY at script-parse time (before DOMContentLoaded). If we - // wait until init(), the browser has already begun animating its own - // restore — especially bad when `scroll-behavior: smooth` is set on html. + // saved scrollY at script-parse time. Retries on fonts.ready and load + // are essential: scrollTo(y) clamps to the current document.scrollHeight, + // which is often hundreds of pixels short of the final value until + // async-loaded fonts swap in and reflow. try { history.scrollRestoration = 'manual'; const savedY = readScrollY(); - if (savedY != null && Math.abs(window.scrollY - savedY) > 0.5) { - console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); - window.scrollTo({ top: savedY, left: 0, behavior: 'instant' }); + if (savedY != null) { + const apply = () => { + if (Math.abs(window.scrollY - savedY) > 0.5) { + console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); + window.scrollTo(0, savedY); + } + }; + apply(); + if (document.fonts?.ready) document.fonts.ready.then(apply).catch(() => {}); + window.addEventListener('load', apply, { once: true }); } } catch {} diff --git a/.trae-cn/skills/impeccable/scripts/live-inject.mjs b/.trae-cn/skills/impeccable/scripts/live-inject.mjs index 37a16f1ea..9bbc345ac 100644 --- a/.trae-cn/skills/impeccable/scripts/live-inject.mjs +++ b/.trae-cn/skills/impeccable/scripts/live-inject.mjs @@ -137,27 +137,8 @@ function commentClose(syntax) { return syntax === 'jsx' ? '*/}' : '-->'; } function buildTagBlock(syntax, port) { const open = commentOpen(syntax); const close = commentClose(syntax); - // Inline pre-restore: runs before the external live.js is fetched. Sets - // scrollRestoration='manual' and jumps to the saved scrollY synchronously - // during HTML parse, beating the browser's animated reload-restore. - // - // Retries on fonts.ready and load are essential: scrollTo(y) clamps to - // the document's current scrollHeight, which is often hundreds of - // pixels short of the final value until async-loaded fonts swap in. - // Hardcoded key matches live-browser.js: PREFIX ('impeccable-live') + - // LS_KEY suffix ('-session') + SCROLL_KEY_SUFFIX ('-scroll'). - const preRestore = - ''; return ( open + ' ' + MARKER_OPEN_TEXT + ' ' + close + '\n' + - preRestore + '\n' + '\n' + open + ' ' + MARKER_CLOSE_TEXT + ' ' + close + '\n' ); diff --git a/.trae/skills/impeccable/scripts/live-browser.js b/.trae/skills/impeccable/scripts/live-browser.js index 71ec5ab75..109d0d58e 100644 --- a/.trae/skills/impeccable/scripts/live-browser.js +++ b/.trae/skills/impeccable/scripts/live-browser.js @@ -121,15 +121,23 @@ } // Pre-empt the browser: apply manual scroll restoration and jump to the - // saved scrollY at script-parse time (before DOMContentLoaded). If we - // wait until init(), the browser has already begun animating its own - // restore — especially bad when `scroll-behavior: smooth` is set on html. + // saved scrollY at script-parse time. Retries on fonts.ready and load + // are essential: scrollTo(y) clamps to the current document.scrollHeight, + // which is often hundreds of pixels short of the final value until + // async-loaded fonts swap in and reflow. try { history.scrollRestoration = 'manual'; const savedY = readScrollY(); - if (savedY != null && Math.abs(window.scrollY - savedY) > 0.5) { - console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); - window.scrollTo({ top: savedY, left: 0, behavior: 'instant' }); + if (savedY != null) { + const apply = () => { + if (Math.abs(window.scrollY - savedY) > 0.5) { + console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); + window.scrollTo(0, savedY); + } + }; + apply(); + if (document.fonts?.ready) document.fonts.ready.then(apply).catch(() => {}); + window.addEventListener('load', apply, { once: true }); } } catch {} diff --git a/.trae/skills/impeccable/scripts/live-inject.mjs b/.trae/skills/impeccable/scripts/live-inject.mjs index 37a16f1ea..9bbc345ac 100644 --- a/.trae/skills/impeccable/scripts/live-inject.mjs +++ b/.trae/skills/impeccable/scripts/live-inject.mjs @@ -137,27 +137,8 @@ function commentClose(syntax) { return syntax === 'jsx' ? '*/}' : '-->'; } function buildTagBlock(syntax, port) { const open = commentOpen(syntax); const close = commentClose(syntax); - // Inline pre-restore: runs before the external live.js is fetched. Sets - // scrollRestoration='manual' and jumps to the saved scrollY synchronously - // during HTML parse, beating the browser's animated reload-restore. - // - // Retries on fonts.ready and load are essential: scrollTo(y) clamps to - // the document's current scrollHeight, which is often hundreds of - // pixels short of the final value until async-loaded fonts swap in. - // Hardcoded key matches live-browser.js: PREFIX ('impeccable-live') + - // LS_KEY suffix ('-session') + SCROLL_KEY_SUFFIX ('-scroll'). - const preRestore = - ''; return ( open + ' ' + MARKER_OPEN_TEXT + ' ' + close + '\n' + - preRestore + '\n' + '\n' + open + ' ' + MARKER_CLOSE_TEXT + ' ' + close + '\n' ); diff --git a/public/index.html b/public/index.html index 06423fd5f..68f4a7283 100644 --- a/public/index.html +++ b/public/index.html @@ -726,63 +726,14 @@ - -
- -
-
-

Work with me

-

Impeccable is built by Renaissance Geek. I work with enterprise teams on large-scale rollouts, custom integrations, and training for designers and developers. If you're a frontier lab, design tool company, or enterprise looking to raise the bar on AI-generated design, let's talk.

-
-
- - -
-
- Renaissance Geek · Consulting -

Work with me.

-

Enterprise rollouts, custom integrations, and training for designers and developers. Get in touch.

-
-
-
-
- -
-

Work with me.

-

Impeccable is built by Renaissance Geek. Rollouts, integrations, training.

-
-
-
-
-
-

Work
with me.

-

Impeccable is built by Renaissance Geek. Large-scale rollouts, custom integrations, and training for teams raising the bar on AI-generated design.

-
-
+ + +
+

Work with me

+

Impeccable is built by Renaissance Geek. I work with enterprise teams on large-scale rollouts, custom integrations, and training for designers and developers. If you're a frontier lab, design tool company, or enterprise looking to raise the bar on AI-generated design, let's talk.

- + + @@ -834,7 +785,6 @@ - diff --git a/public/privacy.html b/public/privacy.html index 817b152e4..4139e711e 100644 --- a/public/privacy.html +++ b/public/privacy.html @@ -78,7 +78,6 @@

Questions about this policy? Open an issue on GitHub or reach out to @pbakaus.

- diff --git a/source/skills/impeccable/scripts/live-browser.js b/source/skills/impeccable/scripts/live-browser.js index 71ec5ab75..109d0d58e 100644 --- a/source/skills/impeccable/scripts/live-browser.js +++ b/source/skills/impeccable/scripts/live-browser.js @@ -121,15 +121,23 @@ } // Pre-empt the browser: apply manual scroll restoration and jump to the - // saved scrollY at script-parse time (before DOMContentLoaded). If we - // wait until init(), the browser has already begun animating its own - // restore — especially bad when `scroll-behavior: smooth` is set on html. + // saved scrollY at script-parse time. Retries on fonts.ready and load + // are essential: scrollTo(y) clamps to the current document.scrollHeight, + // which is often hundreds of pixels short of the final value until + // async-loaded fonts swap in and reflow. try { history.scrollRestoration = 'manual'; const savedY = readScrollY(); - if (savedY != null && Math.abs(window.scrollY - savedY) > 0.5) { - console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); - window.scrollTo({ top: savedY, left: 0, behavior: 'instant' }); + if (savedY != null) { + const apply = () => { + if (Math.abs(window.scrollY - savedY) > 0.5) { + console.log('[impeccable.scroll] early restore', { from: window.scrollY, to: savedY }); + window.scrollTo(0, savedY); + } + }; + apply(); + if (document.fonts?.ready) document.fonts.ready.then(apply).catch(() => {}); + window.addEventListener('load', apply, { once: true }); } } catch {} diff --git a/source/skills/impeccable/scripts/live-inject.mjs b/source/skills/impeccable/scripts/live-inject.mjs index 37a16f1ea..9bbc345ac 100644 --- a/source/skills/impeccable/scripts/live-inject.mjs +++ b/source/skills/impeccable/scripts/live-inject.mjs @@ -137,27 +137,8 @@ function commentClose(syntax) { return syntax === 'jsx' ? '*/}' : '-->'; } function buildTagBlock(syntax, port) { const open = commentOpen(syntax); const close = commentClose(syntax); - // Inline pre-restore: runs before the external live.js is fetched. Sets - // scrollRestoration='manual' and jumps to the saved scrollY synchronously - // during HTML parse, beating the browser's animated reload-restore. - // - // Retries on fonts.ready and load are essential: scrollTo(y) clamps to - // the document's current scrollHeight, which is often hundreds of - // pixels short of the final value until async-loaded fonts swap in. - // Hardcoded key matches live-browser.js: PREFIX ('impeccable-live') + - // LS_KEY suffix ('-session') + SCROLL_KEY_SUFFIX ('-scroll'). - const preRestore = - ''; return ( open + ' ' + MARKER_OPEN_TEXT + ' ' + close + '\n' + - preRestore + '\n' + '\n' + open + ' ' + MARKER_CLOSE_TEXT + ' ' + close + '\n' );