产品实测:生时校正答了三题后 46px 顶栏消失。devtools 取证——栅格是对的 (rows "46px 1297px"、panel y=0),但 header 自己的 rect 在 **y=-88**: 面板被程序化滚动了 88px。 根因:`overflow: hidden` 仍然是滚动容器,它只是去掉了滚动条。 BirthTimeChoiceQuestion 在每答完一题后 focus 新题的第一个选项,浏览器 为把它带进视野会滚动所有可滚动祖先,`.chat-panel` 就是其中之一—— 而用户没有滚动条可以滚回来,顶栏于是永久消失。 两处都修: - 病因:面板内 7 处程序化 focus 一律加 { preventScroll: true }。 消息区有自己的 useConversationScrollAnchor,本来就不需要浏览器代劳。 账户弹窗的 closeButton / returnTarget 不在此列——那是对话框焦点管理。 同一教训 use-billing-panel.ts 已经吃过一次(那里早写了 preventScroll)。 - 结构:.chat-panel 与 .chat-app 从 overflow:hidden 改成 overflow:clip。 clip 根本不创建滚动容器,此后任何 focus / scrollIntoView 都无法位移它。 新增 tests/chat-panel-scroll-guard.test.ts:锁住两个容器必须是 clip、 面板内不得有裸 focus(),并遍历 rectification/birth-time/chat- 全部组件, 新组件再写裸 focus 会直接打红。 测试 3372(+3),fail 仍 31 且与基线逐条一致;四个路由标记不变。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0193vBv6w5MV2cifdTUu9H5P