import {createContext, useContext, useEffect, useState} from 'react'; import type {ReactNode} from 'react'; const MotionContext = createContext({enabled:true, reduced:false, paused:false, toggle:()=>{}}); /** A single preference governs ambient movement, tours and archived playback. */ export function MotionProvider({children}:{children:ReactNode}) { const [hidden,setHidden]=useState(document.hidden); const [reduced,setReduced]=useState(()=>window.matchMedia('(prefers-reduced-motion: reduce)').matches); const [paused,setPaused]=useState(()=>{try{return sessionStorage.getItem('ouroboros-motion-paused')==='true';}catch{return false;}}); useEffect(()=>{ const visibility=()=>setHidden(document.hidden); document.addEventListener('visibilitychange',visibility); return()=>document.removeEventListener('visibilitychange',visibility); },[]); useEffect(()=>{ const query=window.matchMedia('(prefers-reduced-motion: reduce)'); const update=()=>setReduced(query.matches); query.addEventListener('change',update); return()=>query.removeEventListener('change',update); },[]); useEffect(()=>{ document.documentElement.dataset.motion=paused||reduced||hidden?'paused':'running'; try{sessionStorage.setItem('ouroboros-motion-paused',String(paused));}catch{/* Preferences still work when storage is unavailable. */} },[paused,reduced,hidden]); return setPaused(value=>!value)}}>{children}; } export function useMotion(){return useContext(MotionContext);} export function MotionControl(){ const {enabled,reduced,toggle}=useMotion(); return ; }