diff --git a/CHANGELOG.md b/CHANGELOG.md
index 232767d3..ade513aa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
# 印度占星 Skill 更新日志
+## 2026-10-28 — 星盘页页头整齐了,深色模式下几处灰底和白边去掉
+
+- 首页输入框在深色模式下不再有一块灰底。
+- 星盘页:页头按钮和切换一样高,下面的「上升 / 月亮 / 太阳 / 当前大运」胶囊小一号;「日期 · 时间 · 地点 ✎」挪到名字下面,顶栏只剩一行。
+- 「盘面检视」卡片固定高度,点宫位或星体时页面不再上下跳。
+- 「星盘类型」面板:标题和关闭按钮在同一行。
+- 手机聊天页拉起的盘面:顶边不再有白线,四周留白变窄,能看到的内容更多。
+- Skill 版本不变(BUG-1470,issue #140)。
+
## 2026-10-28 — 星盘页、星盘档案页打开更快
- 星盘页第一次打开少下载约 116 KB:「改出生资料」弹窗等到点了那一行才加载(鼠标移上去就开始预取)。
diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md
index a1f3381c..4d59ee87 100644
--- a/docs/BUG_HISTORY.md
+++ b/docs/BUG_HISTORY.md
@@ -20049,3 +20049,18 @@
- 复发自:BUG-1130(防复发只覆盖首页首屏)
- 修复版本:分支 `codex/chart-lazy-editor-20261028`。
+## BUG-1470 | 深色模式输入框仍发灰、星盘页页头按钮三种高度且顶栏两行、检视卡高度跳动、星盘类型面板头部竖排、手机盘面白边与三层留白
+
+- 状态:resolved(代码 + 回归测试;待部署,真机待产品)
+- 首次发现 / 最近更新:2026-10-28 / 2026-10-28(issue #140,产品手机截图;「星盘类型」面板一项 10-27 已在 #114 提过,当时漏接)
+- 影响面:首页与对话页输入框;`/chart` 页头、顶栏、检视卡、「星盘类型」面板;聊天页手机底部盘面;全站组件库里只设了边框宽度的零件。
+- 现象:一、深色模式下输入框里一块灰底。二、页头「印度盘 / 西洋盘」、「生成报告」「带这张盘去对话」与事实胶囊三种高度(约 35 / 41 / 30 px)。三、手机顶栏「星盘」与出生资料行拆成两行,顶栏变粗。四、检视卡未选时矮、选中后高,下面内容跟着跳。五、「星盘类型」面板标题和叉号上下堆着居中。六、聊天页手机盘面顶边一条白线,内容外三层边距。
+- 触发条件:深色模式(一、六);手机宽度(三、六);任意(二、四、五)。
+- 根因:一、BUG-1466 只取消了 `InputGroup` 浅色模式的底色,它在深色模式另有 `dark:bg-input/30` 与 `dark:has-disabled:bg-input/80`。二、页头按钮与分段沿用组件默认尺寸,没按签过的原型统一小号。三、出生资料行放在顶栏 `note` 里,手机样式强制它整行换行。四、检视卡高度由内容决定。五、`SheetHeader` 自带 `flex-col`,我们的样式只写了 `display: flex` 与两端对齐,没改方向。六、换组件库(K0)时漏了 shadcn 标准的 `@layer base { * { border-color: var(--border) } }`;Tailwind v4 的裸 `border` 默认用 currentColor,抽屉的 `border-t` 在深色模式就画成浅色文字色;盘面容器、工作区、卡片各带一层边距。
+- 修复:一、输入框把深色两层底色也取消。二、页头控件统一 32px / 13px,胶囊 28px / 13px(原型 `.seg` / `.btn` / `.chip`)。三、出生资料行挪到名字下面(`.chart-page-head-meta`,原型 meta 行),顶栏只剩标题和「那一刻的天空」。四、检视卡固定 440px,卡内滚动。五、面板头部 `flex-direction: row`,格子区 `min-height: 0` 可滚。六、补回 shadcn 基础边框色规则;手机盘面只留工作区一层 8px 边距。
+- 验证:新测试 `frontend/tests/ui-polish-140-20261028.test.ts`(5 条)+ `chart-page-view.test.tsx` 出生资料行位置断言 + `composer-sidebar-tidy-20261027.test.tsx` 逐个检查 `InputGroup` 每条底色都被取消;6 条在改动前代码上均失败。全量前端测试与 staging 逐条比对无新失败、无消失。首页首屏 gzip 704,289 → 704,341 B(+0.01%),`/` 仍 Static。
+- 防复发:上述测试;组件库零件引入时连同其标准基础层一起引入;用组件库零件覆盖样式时,按其全部变体(含 `dark:`、`has-*:`)逐条取消,而不是只取消看到的那条。
+- 相关记录:BUG-1466(输入框浅色模式版)、BUG-1433(K1 外壳换组件库)、BUG-1465;issue #114、#140。
+- 复发自:BUG-1466(深色变体未覆盖)
+- 修复版本:分支 `codex/ui-polish-140-20261028`。
+
diff --git a/docs/testing/code-health-118-20261028.md b/docs/testing/code-health-118-20261028.md
index 8116371e..78dc4956 100644
--- a/docs/testing/code-health-118-20261028.md
+++ b/docs/testing/code-health-118-20261028.md
@@ -8,3 +8,13 @@
2. 手机打开星盘页,点那一行:同样能弹出编辑框(可能比以前慢一点点,但不出现转圈)。
3. 打开星盘档案页:每个人那一行的「日期 · 时间 · 城市」和以前一样;老资料(只选过省市、很早建的)城市也照常显示。
4. 档案页点「添加一个人」、点某人的「编辑」:表单照常弹出,出生地能选、能存。
+
+## #140 界面优化(BUG-1470)
+
+5. 手机深色模式打开首页:输入框里没有灰底块。
+6. 手机打开星盘页:顶栏只有一行(「星盘」和「那一刻的天空」);名字下面一行小字是「日期 时间 · 地点 ✎」,点它弹出改资料。
+7. 名字右边 / 下面:「印度盘 / 西洋盘」「生成报告」「带这张盘去对话」三个一样高;「上升 / 月亮 / 太阳 / 当前大运」胶囊比它们小一号。
+8. 点盘上任意宫或星,「盘面检视」卡片高度不变,下面的九曜卡不上下跳;内容多时在卡片里滑动。
+9. 点盘型条右边的 ≡:「星盘类型」标题在左、叉号在右,同一行;电脑上整块面板完整可见。
+10. 手机聊天页点开盘面:顶边没有白线,盘离屏幕两边更近。
+
diff --git a/frontend/DESIGN.md b/frontend/DESIGN.md
index 9f33902d..2f1e075d 100644
--- a/frontend/DESIGN.md
+++ b/frontend/DESIGN.md
@@ -412,7 +412,7 @@ The birth-time rectification session is the consultation transcript plus a house
- Before the first message the list selects a person and updates that empty session's binding. Self is the visible default. After the first message the current person stays selected; another person offers only `新建会话并使用此人物` and does not rebind the old session. That action waits until the current request ends.
- Loading shows the small orbit (`OrbitWaiting`, 2026-09-30), with `人物列表还在读` for screen readers only. Failure reads `人物列表暂时读不出来` with `重试`. When the people API itself fails, the popover reads `暂时读不到其他人` and lists only the signed-in person; history stays on that person and the page does not drop into the recoverable error screen. An incomplete row reads `这份资料还不完整` and cannot be chosen. A deleted person reads `资料已删除 · {名字}`; the old session stays readable and sending is blocked. None of these states use a spinner.
- Rectification and daily horoscope do not get this control. Their quiet note, when present, remains the static `.chat-header-chart` span and still drops out below 768px. The person button stays on narrow screens and ellipsizes so the header remains one line.
-- The chart page birth line is a button (`.chart-birth-line`) after the person: `日期 时间 · 地点` and a pen. The name is not repeated. The whole row opens an editor on this page. Self can change every field. Someone else's already-saved birth time stays locked. The sentence `填报的出生时间保存后不能再改` appears once, beside that field, and is not repeated in the form description. Changing the date, time, or place shows `改了出生时间、日期或地点,之前生时校正采用的时间会作废,星盘改按你新填的时间排。` Saving uses the shared other-person write (self still goes through the account). The editor is a component-library dialog (2026-10-25, K3). A click inside the form, including its padding, does not close it or drop unsaved edits. Escape and a click on the backdrop do close it. The fields stay the shared profile form used by the people page, so this page does not grow a second set of fields. Below 768px that row wraps onto a second line and the chart header grows to fit it. The editor's code is not in `/chart`'s first load: it loads on the click and is warmed when the pen row is hovered or focused, and nothing is drawn while it arrives (no placeholder; BUG-1469). The people page's add / edit form likewise stays out of `/people`'s first load and is fetched right after the page mounts.
+- The chart page birth line is a button (`.chart-birth-line`) under the person's name in the page head (`.chart-page-head-meta`, 13px tertiary, as in the signed prototype; it left the top bar on 2026-10-28, BUG-1470, because on a phone it wrapped the bar to two lines): `日期 时间 · 地点` and a pen. The name is not repeated. The whole row opens an editor on this page. Self can change every field. Someone else's already-saved birth time stays locked. The sentence `填报的出生时间保存后不能再改` appears once, beside that field, and is not repeated in the form description. Changing the date, time, or place shows `改了出生时间、日期或地点,之前生时校正采用的时间会作废,星盘改按你新填的时间排。` Saving uses the shared other-person write (self still goes through the account). The editor is a component-library dialog (2026-10-25, K3). A click inside the form, including its padding, does not close it or drop unsaved edits. Escape and a click on the backdrop do close it. The fields stay the shared profile form used by the people page, so this page does not grow a second set of fields. Below 768px that row wraps onto a second line and the chart header grows to fit it. The editor's code is not in `/chart`'s first load: it loads on the click and is warmed when the pen row is hovered or focused, and nothing is drawn while it arrives (no placeholder; BUG-1469). The people page's add / edit form likewise stays out of `/people`'s first load and is fetched right after the page mounts.
- With the composer strip gone as well, the two pieces of permanent chrome went from 68 + 148 to 46 + 124 px.
- On viewports ≤767px the header row is 52px plus the safe-area inset. The credit control (`.credit-balance`) is a normal outline button, 44px, with a coins icon and the number; 点 stays in the accessible name. The rectification 「当前盘面」 chip stays 40px. The shared `::before` hit area stays inset -2px. The onboarding checklist trigger stays 32px.
- Window-level scroll is reset by `ViewportScrollLock` after the on-screen keyboard closes, so the header cannot be left above the screen.
@@ -1077,6 +1077,8 @@ Three product rules for assistant markdown in `.message-markdown` (BUG-962 / 963
条尾固定一个菜单按钮(`.chart-page-type-menu`,44×44,`aria-label="全部盘型"`),在滚动容器外面,不会被滚走。点它打开底部「星盘类型」抽屉:标题 + 关闭,三列网格(`.chart-page-type-grid`),每格大字标签 + 一行小字用途(D 号盘的用途取引擎 `VargaType.meaning`,与 `vedic-chart-tables.json` 同源;本命「D1」、月亮盘「以月亮为第 1 宫」、Bhava「不等宫」、行运「今天」)。当前格主文字色描边 + 浅底。点任一格 = 选中、关面板、把条滚到该项。≥860px 抽屉变窄并四角圆角,仍从底部打开。Esc、点遮罩关闭。页签、盘型格、「全部盘型」、格子触摸目标均 ≥ 44px(格子 64px)。
+抽屉头部是一行:标题在左、关闭在右(`flex-direction: row`;SheetHeader 默认竖排,曾把两者上下堆着居中,BUG-1470)。格子区在抽屉内滚动(`min-height: 0`)。
+
D40 / D45 / D60 的表格上方,出生时间不是「已校正」时多一句:「这张盘每格不到一度,出生时间差两三分钟就可能换一格。先做生时校正再看,会更稳。」
侧栏在「新建对话」之后、「我的报告」之前加「星盘」「星历」两个入口;折叠轨(64px)仍用既有 `report-nav-button` 图标行,当前项用白玻璃面 + 2px 深棕标记,不新造选中态。星历入口指向 `/ephemeris`(由另一单交付,合入前 404 是预期)。
@@ -1433,3 +1435,13 @@ Bhava Bala 保留完整十二宫力量表;Score / Weight 等领域表头不单
## 普通对话寒暄轮(2026-09-20)
服务端标记 `responseKind: smalltalk` 的回复仅展示正文与既有头像/消息操作,不展示思考面板、活动步骤、已完成步骤或技法证据;刷新后的历史也遵循此规则。分类尚未确定、且没有任何真实 activity/thinking/timeline 时,保留消息位置,不虚构「正在分析」或步骤,不另加 spinner。咨询收到真实活动后恢复既有呈现。完成后读取服务端账户余额,寒暄预留点数原额退回,净点数不变;不增加 Home 状态。
+
+### 星盘页页头、检视卡与手机盘面(2026-10-28,issue #140,BUG-1470)
+
+- 页头一排控件同高 32px、字 13px:「印度盘 / 西洋盘」分段、「生成报告」「带这张盘去对话」。下面的事实胶囊(上升、月亮、太阳、当前大运)高 28px、字 13px,比按钮小一档。依据是签过的原型(`.seg` / `.btn` / `.chip`)。
+- 顶栏只有「星盘」和「那一刻的天空」,一行。
+- 「盘面检视」卡固定 440px 高,选不选东西都一样高,内容多时卡内滚动,下面的卡片不再跟着跳。
+- 聊天页手机底部盘面:只留一层 8px 边距(原来面板、工作区、卡片三层)。
+- 全站:组件库零件只写了边框宽度、没写颜色时,用主题边框色(shadcn 的基础规则,`@layer base`)。此前 Tailwind v4 用文字颜色画这些边,深色模式下是一条白线。
+- 输入框:`InputGroup` 自带的底色(含深色模式那一层和禁用时的灰)在输入框上全部取消,外框只由 `.composer` 画。
+
diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css
index 7d873b14..4957a174 100644
--- a/frontend/src/app/globals.css
+++ b/frontend/src/app/globals.css
@@ -2,6 +2,15 @@
@import "shadcn/tailwind.css";
@import "tw-animate-css";
+/* shadcn's standard base rule, missed when the UI kit came in (BUG-1470). Tailwind v4
+ draws a bare `border` / `border-t` in currentColor, so every kit part that sets a
+ width but no colour (drawer and sheet edges among them) drew a line in the text
+ colour: near-white in dark mode. Our own rules set their colours explicitly and,
+ being unlayered, still win over this. */
+@layer base {
+ *, ::after, ::before, ::backdrop, ::file-selector-button { border-color: var(--border); }
+}
+
.personal-report-fact-tables { margin-block: 2rem; min-width: 0; }
.personal-report-fact-tables details { margin-block: 1rem; padding: 1rem; border: 1px solid var(--color-border); border-radius: 0.5rem; }
.personal-report-fact-tables summary { cursor: pointer; min-height: 2.75rem; }
@@ -5655,8 +5664,11 @@ button.synastry-dd-add { border-radius: 0 0 var(--radius-md) var(--radius-md); }
@supports (height: 1dvh) {
.chart-page-type-sheet, .chart-page-type-sheet-panel { max-height: 80dvh; }
}
+/* SheetHeader ships `flex-col`; without an explicit row the title and the close
+ button stacked and both centred (BUG-1470, issue #140). */
.chart-page-type-sheet-header {
display: flex;
+ flex-direction: row;
flex-shrink: 0;
align-items: center;
justify-content: space-between;
@@ -5681,6 +5693,7 @@ button.synastry-dd-add { border-radius: 0 0 var(--radius-md) var(--radius-md); }
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: var(--space-2);
padding: var(--space-3) var(--space-4) max(var(--space-4), env(safe-area-inset-bottom));
+ min-height: 0;
overflow-y: auto;
overscroll-behavior: contain;
}
diff --git a/frontend/src/components/chart-board/chart-board.css b/frontend/src/components/chart-board/chart-board.css
index e8a5da9a..9307256d 100644
--- a/frontend/src/components/chart-board/chart-board.css
+++ b/frontend/src/components/chart-board/chart-board.css
@@ -31,7 +31,8 @@
.chart-board-tab small { font-size: 11px; color: var(--color-ink-tertiary); font-weight: 400; }
.chart-tags { display: flex; flex-wrap: wrap; gap: var(--space-2); }
-.chart-tag { border-radius: 999px; height: 32px; }
+/* Facts, not actions: one step smaller than the head buttons (prototype chip, BUG-1470). */
+.chart-tag { border-radius: 999px; height: 28px; padding: 0 11px; font-size: 13px; }
.chart-tag.is-on,
.chart-tag[aria-pressed="true"] { border-color: var(--color-action); color: var(--color-action); background: var(--color-action-soft); }
.chart-tag.is-dasha { color: var(--color-warning); }
@@ -315,13 +316,21 @@
.chat-chart-head { display: flex; align-items: center; gap: var(--space-2); }
.chat-chart-head strong { font-family: var(--font-display); font-size: 15px; font-weight: 600; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-chart-sheet-body { overflow-y: auto; max-height: 80dvh; }
+/* In the phone sheet the panel, the workspace and each card all padded: three
+ insets before the first glyph (BUG-1470). The sheet keeps one thin gutter. */
+.chat-chart-sheet .chat-natal-chart { padding: 0; }
+.chat-chart-sheet .chat-chart-workspace { padding: var(--space-2); }
@media (prefers-reduced-motion: reduce) {
.chart-board-cell polygon,
.chart-board-cell rect,
.chart-board-ink { transition: none; }
}
-.chart-inspector { min-width: 0; }
+/* One height whatever is selected, so picking a house or a planet does not push
+ everything below it up and down (BUG-1470, issue #140). Long selections scroll
+ inside the card. */
+.chart-inspector { min-width: 0; height: 440px; }
+.chart-inspector > [data-slot="card-content"] { min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.chart-scroll-row { min-width: 0; }
.chat-chart-sheet { --drawer-height: 86dvh; }
@@ -367,11 +376,18 @@
/* Page head (prototype): name on the left; system switch, report and chat on the right. */
.chart-page-head { width: min(1240px, 100%); margin: var(--space-4) auto 0; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); }
+.chart-page-head-title { min-width: 0; }
.chart-page-head-title h2 { margin: 0; font-family: var(--font-display); font-size: 20px; font-weight: 600; }
+/* 「日期 时间 · 地点 ✎」 under the name, the prototype's meta line (BUG-1470). */
+.chart-page-head-meta { min-width: 0; margin-top: 2px; color: var(--color-ink-tertiary); font-size: 13px; }
+.chart-page-head-meta .chart-birth-line { min-height: 32px; width: auto; justify-content: flex-start; }
.chart-page-head-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
+/* One control height across the head, as in the signed prototype: the 印度盘 / 西洋盘
+ segment and both buttons are 32px with 13px type (they had been 35 / 41 px). */
.chart-page-head .chart-page-tabs { width: auto; margin: 0; padding: 0; border: 0; overflow: visible; }
-.chart-page-head .chart-page-tab { min-height: 0; min-width: 0; border-bottom: 0; padding: 0 10px; }
-.chart-page-head-button { border-radius: 999px; }
+.chart-page-head .chart-page-tabs [data-slot="tabs-list"] { height: 32px; padding: 3px; }
+.chart-page-head .chart-page-tab { min-height: 0; min-width: 0; height: 26px; border-bottom: 0; padding: 0 10px; font-size: 13px; }
+.chart-page-head-button[data-slot="button"] { height: 32px; padding: 0 14px; border-radius: 999px; font-size: 13px; }
.chart-book-grid.is-three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 640px) { .chart-book-grid.is-three { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.chart-date-step { gap: 2px; border-radius: 999px; }
diff --git a/frontend/src/components/chart-page/chart-page-view.tsx b/frontend/src/components/chart-page/chart-page-view.tsx
index 27f30e8e..231ed7cd 100644
--- a/frontend/src/components/chart-page/chart-page-view.tsx
+++ b/frontend/src/components/chart-page/chart-page-view.tsx
@@ -307,7 +307,6 @@ export function ChartPageView({
return (