gsap.registerPlugin(); const q=selector=>document.querySelector(selector),qa=selector=>Array.from(document.querySelectorAll(selector)); const studyAbort=new AbortController(),studyCleanup=[]; const listen=(target,type,handler)=>target.addEventListener(type,handler,{signal:studyAbort.signal}); const preference=matchMedia('(prefers-reduced-motion: reduce)'),staticControl=q('#static-mode'); staticControl.checked=preference.matches;staticControl.disabled=preference.matches; const isStatic=()=>staticControl.checked||preference.matches; let applyMode=()=>{}; listen(staticControl,'change',()=>applyMode()); listen(preference,'change',()=>{staticControl.checked=preference.matches;staticControl.disabled=preference.matches;applyMode();}); listen(window,'pagehide',()=>{studyCleanup.forEach(cleanup=>cleanup());studyAbort.abort();}); const reading=text=>q('#reading').textContent=text; const wrapper=q('#height-wrapper'),content=q('#height-content'),toggle=q('#toggle'); const shortText='
움직임은 구조를 이해하도록 돕습니다. 내용이 길어지면 상자는 정해 둔 숫자 대신 그 내용의 자연 높이에 맞춥니다.
'; const longText=shortText+'새 입력이 오면 진행 중인 높이 전환을 정리하고 마지막 요청을 따릅니다. 이전 열기의 완료가 최신 닫힘을 덮어쓰지 않도록 상태를 함께 확인합니다.
화면 폭이 달라져 줄이 다시 나뉘면 측정한 끝점도 달라집니다. 이 연구는 그 순간 전환을 끝내고 현재 요청에 맞는 자연 높이 또는 닫힌 높이로 정착합니다.
'; let desiredOpen=true,heightTween=null,generation=0; function reflect(){toggle.disabled=isStatic();toggle.textContent=isStatic()?'전체 내용 표시':desiredOpen?'닫기':'열기';toggle.setAttribute('aria-expanded',String(isStatic()||desiredOpen));toggle.setAttribute('aria-controls','height-wrapper');wrapper.setAttribute('aria-hidden',String(!isStatic()&&!desiredOpen));reading(isStatic()?'정적 보기 · 전체 내용 표시':desiredOpen?'열림 · 자연 높이로 정착':'닫힘 · 높이 0');} function settle(){if(isStatic())desiredOpen=true;generation++;heightTween?.kill();gsap.set(wrapper,{height:desiredOpen?'auto':0});reflect();} function changeOpen(){desiredOpen=!desiredOpen;const token=++generation;heightTween?.kill();reflect();if(isStatic()){settle();return;} heightTween=gsap.to(wrapper,{height:desiredOpen?'auto':0,duration:.4,ease:'power2.inOut',overwrite:true,onComplete:()=>{if(token===generation&&desiredOpen)gsap.set(wrapper,{height:'auto'});}});} listen(toggle,'click',changeOpen);listen(q('#length'),'change',e=>{content.innerHTML=e.target.value==='길게'?longText:shortText;settle();}); let previousWidth=wrapper.clientWidth;const heightObserver=new ResizeObserver(()=>{const width=wrapper.clientWidth;if(width!==previousWidth){previousWidth=width;settle();}});heightObserver.observe(wrapper); applyMode=settle;studyCleanup.push(()=>{heightTween?.kill();heightObserver.disconnect();});settle();