agent: dynamic header height, badges+pills one row, composer alignment

mara, live: 'login panel still looks like it is behind', 'bottom input
row text not aligned / inconsistent sizes', 'can we put the badges on
the same row as the links button etc? then the header would be more
compact.'

- Real fix for the overlap this time, not another band-aid: the
  header's downstream offset (.agent-status-overlay, .agent-main's
  scroll padding) was reading a STATIC --agent-header-h guess (6em).
  Every prior fix on this PR removed one specific contributor to the
  header wrapping past that guess (meta-nav's inline list, then
  disconnected badge/pills clusters) but the guess itself was always
  the actual defect — any content that can wrap an extra line breaks
  it at whatever width triggers it, and no width is safe to promise.
  Header.tsx now measures its own rendered height via ResizeObserver
  and writes it to a new --agent-header-real-h var; downstream
  consumers prefer that over the static guess. Deliberately a SEPARATE
  var from --agent-header-h, not an overwrite: .agent-header's own
  min-height also reads that var, so overwriting it in place created
  an actual ResizeObserver feedback loop (confirmed live on the first
  pass of this fix, fixed by splitting the var).
- Badges (StatusChips) + pills (inbox/todos/links/overflow) now share
  one row (.agent-state-row) instead of two visually disconnected
  clusters (old app.js markup's 3-column layout, which the new page
  had also carried over) — pills pushed to the row's right edge via a
  margin-left: auto rule scoped to that nesting, so app.js's own
  still-live separate-column usage of the same classes is untouched.
- Composer text alignment: real cause was .prompt (1em) and
  .submit-hint (0.8em) each getting a different-sized default line-box
  under align-items: flex-start, so the same nominal padding-top
  landed at different absolute offsets. align-items: center sidesteps
  the whole line-box-size mismatch. This one's shared with app.js too
  (same markup/classes) — same bug there, now fixed for both.

Verified at 480/500/768/1024/1400px — no overlap, no ResizeObserver
loop, badges+pills share one row, composer aligned. tsc --noEmit
clean, build clean, both pre-push lints clean.
This commit is contained in:
iris 2026-08-28 22:30:35 +02:00
commit f49e236c74
2 changed files with 99 additions and 31 deletions

View file

@ -128,6 +128,19 @@ body.agent-shell {
margin: 0;
gap: 0.5em;
}
/* New Preact page only: `Header.tsx` nests `.agent-header-pills`
INSIDE `.agent-state-row` (badges + pills sharing one row mara,
live: "can we put the badges on the same row as the links button
etc? then the header would be more compact"), unlike the old
app.js markup where `.agent-header-pills` is a separate header-
level column (index.html line ~54). Scoped as a descendant
selector so it only fires for that nesting app.js's own
still-live 3-column layout below is untouched. Pushes the pills
cluster to the row's right edge; badges (`children`, rendered
first) fill the space to its left. */
.agent-state-row .agent-header-pills {
margin-left: auto;
}
/* Right cluster flyout pills stacked / inline with the overflow
trigger. Vertically centred against the full-height icon, no
@ -357,10 +370,16 @@ h2, h3 {
/* Login flow overlay: only rendered when status != online. Sits
centred over the (likely-empty) terminal area; doesn't take chrome
space in the normal online flow. */
space in the normal online flow. `--agent-header-real-h` (set by
the new Preact page's `Header.tsx` via ResizeObserver, falling back
to the static `--agent-header-h` guess before the first
measurement / on the old app.js page, which never sets it) is the
header's ACTUAL rendered height, not an assumed one see
Header.tsx's file comment for why this matters (a static guess is
wrong the moment the header wraps an extra line on some viewport). */
.agent-status-overlay {
position: absolute;
top: calc(var(--agent-header-h) + 1.5em);
top: calc(var(--agent-header-real-h, var(--agent-header-h)) + 1.5em);
left: 50%;
transform: translateX(-50%);
max-width: 44em;
@ -716,9 +735,9 @@ pre.diff {
and last rows reachable with extra padding inside the scroll
area. scroll-padding-* keeps anchor-jumps (the ` N new` pill,
focus restore) clear of the floats too. */
padding-top: calc(var(--agent-header-h) + 0.8em);
padding-top: calc(var(--agent-header-real-h, var(--agent-header-h)) + 0.8em);
padding-bottom: calc(var(--agent-composer-h) + 0.8em);
scroll-padding-top: calc(var(--agent-header-h) + 0.8em);
scroll-padding-top: calc(var(--agent-header-real-h, var(--agent-header-h)) + 0.8em);
scroll-padding-bottom: calc(var(--agent-composer-h) + 0.8em);
overflow: auto;
}
@ -739,7 +758,21 @@ pre.diff {
rules below stay scoped to whichever ancestor owns it. */
.term-input .sendform-term {
display: flex;
align-items: flex-start;
/* mara, live: "bottom input row text not aligned / inconsistent
sizes." Real cause: `.prompt` (1em, no line-height override) and
`.submit-hint` (0.8em, no line-height override) each get a
browser-default line-box at a different em-relative size, so
`align-items: flex-start` (their old value) pinned each one's
line-box top edge to the row's top same nominal `padding-top`
but a DIFFERENT absolute offset per element, since 0.25em means
something different at 1em vs 0.8em font-size. `center` sidesteps
the whole "line-box for text this size" mismatch by aligning each
item's own box middle instead of a top edge that was never
actually equal. Still correct once the textarea grows multi-line
(a common composer-bar convention Slack/Discord centre their
send affordance against a grown box too, not pin it to the first
line). */
align-items: center;
gap: 0.5em;
/* The dashed in-frame separator is dropped see the
.agent-composer .term-input override above for the floating-bar
@ -747,9 +780,6 @@ pre.diff {
border-top: 1px dashed var(--purple-dim);
padding-top: 0.5em;
}
.term-input .prompt, .term-input .submit-hint {
padding-top: 0.25em;
}
.term-input .prompt {
color: var(--green);
text-shadow: 0 0 6px color-mix(in srgb, var(--green) 60%, transparent);