diff --git a/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Section_View.ts b/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Section_View.ts index b543e27c..741f892a 100644 --- a/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Section_View.ts +++ b/B06_wf3_ProfileCross/B06_wf3_ProfileCross_UI_Section_View.ts @@ -340,13 +340,27 @@ export function createSectionView( }; /** - * 선택 카드를 화면에 남긴다. 상단 패널이 sticky라 `center`로 보내면 패널이 커졌을 때 - * 그 아래로 숨는다 — `nearest` + `scroll-margin-top`(패널 높이)이면 가려질 때만, - * 가려지지 않을 만큼만 움직인다. + * 상단 패널이 sticky라 카드 스크롤 정지선은 `scroll-margin-top`(패널 높이 + 손잡이 몫)이다. + * 패널은 리사이저·접기 손잡이로 수시로 높이가 변하고, 접을 때는 drawPanel이 돌지 않으므로 + * **스크롤 직전에 실측**해야 정지선이 현재 패널과 맞는다. + */ + const syncScrollMargin = (): void => { + // 접기 손잡이가 패널 아래 24px 밖으로 나와 있고, 선택 강조(빨간 테두리 + 2px ring)가 + // 잘리지 않도록 8px 여유를 더한다. + const panelPx = panel.getBoundingClientRect().height || panelHeight(); + root.style.setProperty("--b06-cross-scroll-margin", `${Math.round(panelPx + 32)}px`); + }; + + /** + * 선택 카드를 화면에 남긴다. `nearest`는 카드가 아래에 있을 때 카드 **하단**을 브라우저 + * 바닥에 맞춰 멈추는데, 그러면 카드 상단(측점 라벨)이 화면 밖이다(2026-08-04 사용자 지적). + * `start`로 카드 **상단**을 접기 손잡이 바로 아래 정지선에 붙인다. 목록 맨 끝 카드는 + * 스크롤이 바닥에 걸려 그 자리까지 못 올라오며, 그대로 둔다(브라우저가 알아서 멈춘다). */ const revealCard = (stationId: string | null, behavior: ScrollBehavior): void => { if (!stationId) return; - document.getElementById(`cross-${stationId}`)?.scrollIntoView({ behavior, block: "nearest" }); + syncScrollMargin(); + document.getElementById(`cross-${stationId}`)?.scrollIntoView({ behavior, block: "start" }); }; /** 카드 하나의 선택 표시를 갱신한다 — **다시 만들지 않는다**(줌·팬이 살아남아야 한다). */ @@ -537,9 +551,7 @@ export function createSectionView( } chartWrap.scrollLeft = keepScrollLeft; // 상단 패널이 sticky라 선택 카드가 그 아래로 숨는다 — 패널 높이만큼 스크롤 여백을 잡아 준다. - // 접기 손잡이가 패널 아래 24px 밖으로 나와 있으므로 그 몫까지 더한다. - const panelPx = panel.getBoundingClientRect().height || panelHeight(); - root.style.setProperty("--b06-cross-scroll-margin", `${Math.round(panelPx + 32)}px`); + syncScrollMargin(); // 첫 렌더(detached)나 패널 높이 변경 직후에는 위에서 잰 값이 아직 옛 레이아웃일 수 있다. // 다음 프레임에 한 번만 다시 재서 어긋나면 고쳐 그린다. `chartWrap` 높이는 내용과 무관하니