diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css index d86c3a5a..caf0c2ef 100644 --- a/frontend/src/app/globals.css +++ b/frontend/src/app/globals.css @@ -853,6 +853,24 @@ button:disabled { cursor: default; opacity: .45; } .chat-header-chart { flex: 0 1 auto; min-width: 0; overflow: hidden; color: var(--color-ink-tertiary); font-size: var(--type-caption); text-overflow: ellipsis; white-space: nowrap; } .chat-header-actions { min-width: max-content; display: flex; flex: 0 0 auto; align-items: center; gap: var(--space-2); white-space: nowrap; } .chat-header-actions > * { flex: 0 0 auto; } +/* The page header is 46px tall, so its actions are 32px — the button primitives + default to 44px, which is why 「生成完整报告」 read as a banner CTA parked in + the corner. The touch target comes back through the hit expansion below, the + same trade the message actions and the starter pills make. */ +.chat-header-actions button { + position: relative; + min-height: 32px; + height: 32px; + padding-inline: var(--space-3); + border-radius: var(--radius-md); + font-size: var(--type-caption); +} +.chat-header-actions button::after { + position: absolute; + inset: -6px; + content: ""; +} +.chat-header-actions button > svg { width: 14px; height: 14px; } .credit-button { min-height: 44px; display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2); padding: 0 var(--space-3); cursor: pointer; font-size: var(--type-caption); font-variant-numeric: tabular-nums; transition: background-color 120ms ease-out, transform 120ms ease-out; min-width: 64px; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-canvas-soft); color: var(--color-ink-secondary); font-weight: 500; } .conversation { min-width: 0; min-height: 0; overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain; padding-bottom: var(--composer-reserve); background: var(--color-canvas); } @@ -861,6 +879,12 @@ button:disabled { cursor: default; opacity: .45; } stack reads as one centred group while the composer keeps the single DOM position it has in a live session. */ .conversation.is-empty { display: grid; align-content: end; justify-items: center; padding: var(--space-8) var(--space-8) 0; } +/* With the balance row present the panel has four rows: header, the conversation + (1fr, greeting bottom-aligned), the composer (auto), and an equal 1fr below. + The two 1fr rows cancel out, so the group is vertically centred while the + composer keeps the single DOM position it holds in a live session. */ +.chat-panel:has(.starter-balance) { grid-template-rows: 46px minmax(0, 1fr) auto minmax(0, 1fr); } +.starter-balance { min-height: 0; } .welcome { width: min(820px, 100%); padding: var(--space-10) 0 var(--space-16); } .welcome > .onboarding-message:first-child { padding-bottom: var(--space-8); } .welcome > .onboarding-message:first-child .message-bubble p { @@ -2208,7 +2232,7 @@ button.nav-rail-identity:hover { background: var(--sidebar-accent); } .composer-wrap-starter { border-top-color: transparent; - padding-bottom: var(--space-16); + padding-bottom: var(--space-4); background: transparent; backdrop-filter: none; } diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index 3acc6e47..160445c7 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -1807,6 +1807,12 @@ export default function Home() { /> )} } + {/* Balances the 1fr row above the composer so the greeting / composer / + pills group sits in the middle of the panel instead of resting on the + bottom edge. It collapses to 0 on short viewports. */} + {starterHomeVisible && !rectificationSurfaceOpen && !onboardingFormActive + ?