# 팝업이 라벨보다 늦게 사라지고, 닫힘 후 첫 클릭이 무시되던 문제

**날짜**: 2026-06-24
**수정 파일**: `client/src/components/overlay/StationOverlay.tsx`
**관련**: [2026-06-24_1220_팝업-라벨아래-글자클릭.md](2026-06-24_1220_팝업-라벨아래-글자클릭.md)

## 증상
1. 라벨이 화면에서 사라졌는데 팝업이 ~1초 더 보이다가 사라짐.
2. 팝업이 (라벨 따라) 사라진 뒤, 화면 첫 클릭은 영상이 안 멈추고 두 번째 클릭에 멈춤.

## 원인 (동일 뿌리)
`object-fit:cover` 로 영상이 컨테이너 밖까지 확장(크롭)되므로, 라벨이 **보이는 컨테이너에서
잘려 사라져도 영상-정규좌표상으론 아직 존재**(pyRaw<1.02). 그래서:
- 팝업이 화면 가장자리에 클램프된 채 라벨이 영상 끝(1.02)에 갈 때까지 남음(~1초).
- 그 팝업이 `infoPopups` state 에 살아 있어 `hasPopupRef=true` → 빈 곳 첫 클릭이 그 '유령 팝업'을
  닫는 데 쓰이고(토글 안 함), 두 번째 클릭에야 재생 토글.

## 조치 — 라벨이 컨테이너를 벗어나면 팝업 state 에서 제거
RAF 팝업 위치 갱신에서, 라벨이 없거나 마커 화면좌표(sx,sy)가 **컨테이너 밖**(±16px)이면 '사라짐':
```ts
const off = !disp || sx < -16 || sx > W+16 || sy < -16 || sy > H+16;
if (off) { miss++; if (miss>=4) toRemove.push(id); else hide; return; }
...
if (toRemove.length) setInfoPopups(prev => prev.filter(p => !toRemove.includes(p.id)));
```
- 4프레임(~0.07s) 연속 밖이면 **state 에서 제거**(라벨과 거의 동시에 사라짐). 짧은 깜빡임 유예.
- state 에서 빠지므로 `hasPopupRef` 즉시 false → 다음 빈 클릭이 바로 재생 토글(2번 문제 해결).
- `popupMissRef`(id별 연속 밖 카운터)로 일시적 갭에 의한 조기 제거 방지.

## 검증
- `npm run build -w client` (node20) tsc + vite build 통과.

**소요 시간**: 약 8분
**Context 사용량**: input ~535k / output ~4k tokens
