fix(B06): 측점 선택 시 횡단도 카드 상단을 패널 손잡이 아래 정지선에 정렬

- revealCard: scrollIntoView block nearest -> start (카드 하단이 브라우저
  바닥에 걸리던 문제 수정, 카드 상단이 sticky 패널 아래에 붙음)
- syncScrollMargin 신설: 스크롤 직전 패널 높이 실측 + 손잡이 24px + 여유 8px
  (접기 시 drawPanel 미실행이어도 정지선 최신 유지)
- PLAN.md: A~D 항목 완료·취소 정리(2026-08-04 사용자 확정), 아카이빙 대기 표기

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-04 16:50:07 +09:00
co-authored by Claude Opus 5
parent b3c64625df
commit c6d930b3f1
@@ -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` 높이는 내용과 무관하니