import { useSyncExternalStore } from 'react' /** * SSR-safe CSS media-query hook. Returns the current match boolean and * re-renders on viewport changes. Used by /pilot to swap the task lane * between side panel (≥1200px) and bottom drawer (<1200px) per Phase 7. * * Implemented with useSyncExternalStore to subscribe to the MediaQueryList * without an effect — this is the React-idiomatic shape for external-state * subscriptions and avoids the setState-in-effect cascade lint rule. */ export function useMediaQuery(query: string): boolean { return useSyncExternalStore( (onChange) => { if (typeof window === 'undefined') return () => {} const mql = window.matchMedia(query) mql.addEventListener('change', onChange) return () => mql.removeEventListener('change', onChange) }, () => { if (typeof window === 'undefined') return false return window.matchMedia(query).matches }, () => false, // server snapshot — match initial false ) } export default useMediaQuery