// Helpers to keep heavy WebGL scene setup off the page's critical path. // Runs fn once the main thread is idle (falling back to a short timeout), // returning a cancel handle so an early unmount never leaks a scheduled init. export const scheduleIdle = (fn: () => void, timeout = 1500): (() => void) => { const ric = (window as any).requestIdleCallback as | ((cb: () => void, opts?: { timeout: number }) => number) | undefined if (typeof ric === 'function') { const id = ric(fn, { timeout }) return () => (window as any).cancelIdleCallback?.(id) } const id = setTimeout(fn, 200) return () => clearTimeout(id) } // Calls cb whenever tab visibility changes, returning an unsubscribe function. export const onVisibility = (cb: (hidden: boolean) => void): (() => void) => { const handler = () => cb(document.hidden) document.addEventListener('visibilitychange', handler) return () => document.removeEventListener('visibilitychange', handler) }