agent.css + docs: migrate icon sizing + popover :not([hidden]) prose (#713 batch 2)

agent.css carried 17 #NNN cookies, mostly attribution refs to the
#394 vibec0re overhaul (mara's full-screen redesign). Most were
not substantive WHY-prose — just "this exists because of #394"
breadcrumbs. The two genuine WHY-explanations move to docs.

Moved to docs/web-ui.md::Per-agent page:
- **Agent icon paragraph**: rewrote with explicit-em-sizing
  rationale (intrinsic <img> dimensions push parent flex container
  open via align-items: stretch height feedback) + the 5em ≈ 6em
  min-height - 0.5em padding × 2 derivation + align-self:
  flex-start sticks-to-top.
- **Overflow button paragraph**: added the :not([hidden]) display
  scoping rationale (UA stylesheet sets display:none on [hidden],
  but author display:flex would override — scope to :not([hidden])
  so the popover stays hidden until JS unhides).

Collapsed in agent.css: 17 cookies scrubbed across the file:
- #360 (full-screen vibec0re overhaul — closed) ×2: section
  header preface + side-panel section header
- #394 (vibec0re header redesign — closed) ×7: header height,
  main column, agent icon, meta-nav, overflow trigger, two
  orphaned-style tombstones
- #411 (popover scoping + icon align-start — closed) ×2: icon
  sticks-to-top + overflow popover scoping
- #568 (OAuth code mask + reveal — closed) ×1: show/hide toggle
- #666 (ask→operator inline-answer slot — closed) ×1: slot
  styling (substance partly in PR #780 docs section)
- #559 (mark all read header row — closed) ×1
- #376 (inbox row layout — closed) ×1: long-message wrap
- #375 (tail pill z-index — closed) ×1: collision fix

agent.css: 17 → 0 refs (100% reduction, fully migrated).
This commit is contained in:
iris 2026-05-31 14:37:43 +02:00 committed by mara
commit b07d74b51b
2 changed files with 72 additions and 69 deletions

View file

@ -807,13 +807,17 @@ Three fixed-position layers frame a full-viewport terminal:
**Fixed-overlay header** (`<header class="agent-header">`): frosted **Fixed-overlay header** (`<header class="agent-header">`): frosted
glass — `backdrop-filter: blur` lets scrolled terminal rows show glass — `backdrop-filter: blur` lets scrolled terminal rows show
through. Three flex columns (#394 redesign): through. Three flex columns:
- **Agent icon** (`<img class="agent-icon">`): fixed-size square - **Agent icon** (`<img class="agent-icon">`): fixed-size square
identity anchor (5em, `width: 5em; aspect-ratio: 1; identity anchor — `width: 5em; height: 5em` with explicit pixel
align-self: flex-start` — capped so a tall state-row doesn't sizing so the `<img>`'s intrinsic (large) dimensions don't push
inflate the icon, #411). Falls back to the dimmed hyperhive mark the parent flex container open via `align-items: stretch`-driven
on load error. height feedback. 5em ≈ header content area (header `min-height: 6em`
minus `2 × 0.5em` padding). `align-self: flex-start` keeps the
icon stuck to the top so a state-row line-wrap doesn't drag it
down with it. Falls back to the dimmed hyperhive mark on load
error.
- **Main column** (`.agent-header-main`): two rows. - **Main column** (`.agent-header-main`): two rows.
- Row 1 (`.agent-header-title-row`): title (`<h2 id="title">`) + - Row 1 (`.agent-header-title-row`): title (`<h2 id="title">`) +
meta-nav (`<nav id="meta-links">`). Meta-nav renders meta-nav (`<nav id="meta-links">`). Meta-nav renders
@ -861,8 +865,11 @@ through. Three flex columns (#394 redesign):
(POST confirm → `POST /api/logout`; SIGINTs any in-flight turn, (POST confirm → `POST /api/logout`; SIGINTs any in-flight turn,
wipes OAuth credential files, flips the agent to `needs_login` wipes OAuth credential files, flips the agent to `needs_login`
— session history preserved). All destructive actions require — session history preserved). All destructive actions require
one extra click to acknowledge (#394 — rare ops shouldn't live one extra click to acknowledge — rare ops shouldn't live in the
in the primary state strip). primary state strip. The popover's display rules are scoped to
`:not([hidden])` so the `[hidden]` HTML attribute's UA `display:
none` isn't overridden by the author CSS's `display: flex` —
the popover stays hidden until JS removes the attribute.
`/api/state` is fetched once on cold load (+ while `/api/state` is fetched once on cold load (+ while
`status === 'needs_login_in_progress'`); all other updates arrive via `status === 'needs_login_in_progress'`); all other updates arrive via

View file

@ -3,18 +3,16 @@
@import "@hive/shared/base.css"; @import "@hive/shared/base.css";
@import "@hive/shared/terminal.css"; @import "@hive/shared/terminal.css";
/* full-screen vibec0re overhaul (issue #360) /* full-screen layout overrides
Layout shape: fixed-position frosted-glass header at top, fixed- The agent page mounts a full-viewport terminal under a fixed
position composer at bottom, full-viewport terminal in between. frosted-glass header + composer pair. See docs/web-ui.md::Per-agent
The terminal scrolls its text passes BENEATH the floating page for the layer / pill / side-panel structure; rules below
header/composer with backdrop-filter blur for the frosted look. override the in-page defaults from @hive/shared. */
Inbox + loose-ends move into the side-panel flyout; header pills
surface their counts as the only chrome they get. */
:root { :root {
/* Bumped to 6em (#394) so the agent icon can be a full-height /* 6em min-height accommodates the full-height agent icon (5em +
square identity anchor without crowding the two-row main column padding) alongside the two-row main column (title + nav-links
(title + nav-links on top, state strip below). */ on top, state strip below). */
--agent-header-h: 6em; --agent-header-h: 6em;
--agent-composer-h: 3.6em; --agent-composer-h: 3.6em;
--agent-frost-bg: rgba(30, 30, 46, 0.72); --agent-frost-bg: rgba(30, 30, 46, 0.72);
@ -86,7 +84,7 @@ body.agent-shell {
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35); box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
} }
/* Main column: title row on top, state strip below (#394). Centred /* Main column: title row on top, state strip below. Centred
vertically against the full-height icon on the left. */ vertically against the full-height icon on the left. */
.agent-header-main { .agent-header-main {
display: flex; display: flex;
@ -140,12 +138,10 @@ h2, h3 {
text-shadow: 0 0 8px rgba(203, 166, 247, 0.4); text-shadow: 0 0 8px rgba(203, 166, 247, 0.4);
} }
.agent-icon { .agent-icon {
/* Square identity anchor (#394 mara's spec). Explicit em sizing /* Square identity anchor explicit 5em sizing + align-self.
so the <img>'s intrinsic (large) dimensions don't push the See docs/web-ui.md::Per-agent page (Agent icon) for the
parent flex container open via `align-items: stretch`-driven intrinsic-dim-pushes-parent-flex-open + sticks-to-top
height feedback. Width = header content area (header min-h 6em rationale. */
- 2 × 0.5em padding 5em). Sticks to the top so a state-row
wrap doesn't drag the icon down with it. (#411) */
width: 5em; width: 5em;
height: 5em; height: 5em;
flex-shrink: 0; flex-shrink: 0;
@ -156,9 +152,9 @@ h2, h3 {
} }
/* Meta-nav links (stats / screen / forge / dashboard / extras) /* Meta-nav links (stats / screen / forge / dashboard / extras)
no underline (#394 mara's spec); hover lights with cyan glow + no underline; hover lights with cyan glow + subtle background
subtle background tint. Reads as a row of soft tabs rather than tint. Reads as a row of soft tabs rather than default-styled
default-styled inline anchors. */ inline anchors. */
.agent-nav-link { .agent-nav-link {
color: var(--cyan); color: var(--cyan);
text-decoration: none; text-decoration: none;
@ -176,7 +172,7 @@ h2, h3 {
} }
/* Overflow menu trigger `` round button on the right of the /* Overflow menu trigger `` round button on the right of the
pills row. Quiet by default, lights on hover / open (#394). */ pills row. Quiet by default, lights on hover / open. */
.overflow-btn { .overflow-btn {
background: transparent; background: transparent;
border: 1px solid var(--purple-dim); border: 1px solid var(--purple-dim);
@ -200,13 +196,11 @@ h2, h3 {
box-shadow: 0 0 10px -2px var(--purple); box-shadow: 0 0 10px -2px var(--purple);
} }
/* Overflow popover rebuild + new-session (and the dashboard /* Overflow popover rebuild + new-session + logout (and the
back-link, prepended in app.js setHeader). Positioned in JS so dashboard back-link, prepended in app.js setHeader). Positioned
the menu's top-right corner anchors under the trigger button. in JS so the menu's top-right corner anchors under the trigger
`:not([hidden])` scoping (#411): the `[hidden]` HTML attribute button. See docs/web-ui.md::Per-agent page (Overflow button)
sets `display: none` via the UA stylesheet, but author CSS's for the `:not([hidden])` scoping rationale. */
`display: flex` would override that. Scope display rules so
they apply only when the menu is unhidden. */
.overflow-menu:not([hidden]) { .overflow-menu:not([hidden]) {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -395,14 +389,12 @@ a:hover { color: var(--fg); text-shadow: 0 0 12px rgba(137, 220, 235, 0.9); }
} }
.btn-login { color: var(--amber); border-color: var(--amber); } .btn-login { color: var(--amber); border-color: var(--amber); }
.btn-cancel { color: var(--red); border-color: var(--red); font-size: 0.85em; padding: 0.15em 0.6em; } .btn-cancel { color: var(--red); border-color: var(--red); font-size: 0.85em; padding: 0.15em 0.6em; }
/* `.btn-rebuild` was the per-agent header chip moved into the /* Orphaned rules left here as a tombstone so a search for the
overflow menu in #394 (`.overflow-item-rebuild` covers it now). class name finds them. Live consumers gone:
The dashboard has its own `.btn-rebuild` rule for the per-row - `.btn-rebuild` was a per-agent header chip (covered now by
R3BU1LD form on the SW4RM tab; this one was specific to the `.overflow-item-rebuild` in the overflow menu).
per-agent header. - `.btn-send` was a green send-button variant the dashboard's
`.btn-send` was a green send-button variant orphaned since compose form that used it is retired. */
the dashboard's compose form was retired; no live consumer left
in either the agent or dashboard tree. */
.sendform { display: flex; gap: 0.6em; margin-top: 0.5em; } .sendform { display: flex; gap: 0.6em; margin-top: 0.5em; }
.sendform input { .sendform input {
font-family: inherit; font-size: 1em; font-family: inherit; font-size: 1em;
@ -424,10 +416,10 @@ a:hover { color: var(--fg); text-shadow: 0 0 12px rgba(137, 220, 235, 0.9); }
} }
.loginform input:focus { outline: 1px solid var(--purple); } .loginform input:focus { outline: 1px solid var(--purple); }
/* #568: show / hide toggle for the masked OAuth-code input. Quiet /* Show / hide toggle for the masked OAuth-code input. Quiet by
by default (muted border + transparent bg), lights amber on default (muted border + transparent bg), lights amber on hover
hover / when pressed (aria-pressed="true") so the operator / when pressed (`aria-pressed="true"`) so the operator sees at
sees at a glance whether the code is currently visible. */ a glance whether the code is currently visible. */
.loginform-reveal { .loginform-reveal {
font-family: inherit; font-family: inherit;
font-size: 1em; font-size: 1em;
@ -489,7 +481,7 @@ pre.diff {
/* Inbox / loose-ends rows: header (from / sep / ts) on one line, /* Inbox / loose-ends rows: header (from / sep / ts) on one line,
body on its own line below gives the body the full panel width body on its own line below gives the body the full panel width
instead of squeezing it into a fourth grid column that wrapped instead of squeezing it into a fourth grid column that wrapped
long messages over many narrow lines (issue #376). */ long messages over many narrow lines. */
.agent-inbox li { .agent-inbox li {
padding: 0.4em 0; padding: 0.4em 0;
display: block; display: block;
@ -552,15 +544,16 @@ pre.diff {
.agent-inbox .answer-form button:disabled { opacity: 0.5; cursor: default; } .agent-inbox .answer-form button:disabled { opacity: 0.5; cursor: default; }
.agent-inbox .answer-status { color: var(--muted); align-self: center; } .agent-inbox .answer-status { color: var(--muted); align-self: center; }
/* #666: inline answer slot mounted under each `ask operator` row /* Inline answer slot mounted under each `ask operator` row in
in the live terminal stream. Mirrors the side-panel `.answer-form` the live terminal stream. Mirrors the side-panel `.answer-form`
look-and-feel same textarea, same send button so the operator look-and-feel same textarea, same send button so the operator
doesn't have to context-switch between "answering in the panel" and doesn't have to context-switch between "answering in the panel"
"answering inline". Empty slot collapses to nothing (no margin) so and "answering inline". Empty slot collapses to nothing (no
pre-bind rows stay tidy; populated slot gets a thin top divider to margin) so pre-bind rows stay tidy; populated slot gets a thin
separate the question body from the form. Resolved tag (the top divider to separate the question body from the form. A
struck-through `[answered ]`) replaces the form once the `[resolved]` tag (neutral, covers answered / cancelled /
question's been answered. */ TTL-expired uniformly) replaces the form once the question
leaves the pending list. */
.live .ask-answer-inline-slot:empty { display: none; } .live .ask-answer-inline-slot:empty { display: none; }
.live .ask-answer-inline-slot { .live .ask-answer-inline-slot {
margin-top: 0.5em; margin-top: 0.5em;
@ -613,10 +606,10 @@ pre.diff {
text-decoration-color: var(--muted); text-decoration-color: var(--muted);
} }
/* #559: "mark all read" header row sits above the recent-messages /* "mark all read" header row sits above the recent-messages list
list in the inbox side-panel flyout. Same look as the answer-form in the inbox side-panel flyout. Same look as the answer-form
button (mauve hover, bg-elev background) so they read as part of button (mauve hover, bg-elev background) so they read as part
the same affordance family. */ of the same affordance family. */
.agent-inbox .inbox-mark-all-row { .agent-inbox .inbox-mark-all-row {
display: flex; display: flex;
gap: 0.6em; gap: 0.6em;
@ -697,8 +690,9 @@ pre.diff {
text-shadow: 0 0 6px rgba(243, 139, 168, 0.55); } text-shadow: 0 0 6px rgba(243, 139, 168, 0.55); }
.status-badge.status-needs-login { color: var(--amber); border-color: var(--amber); } .status-badge.status-needs-login { color: var(--amber); border-color: var(--amber); }
.status-badge.status-offline { color: var(--muted); border-color: var(--muted); } .status-badge.status-offline { color: var(--muted); border-color: var(--muted); }
/* Orphaned in #394 `.btn-dashlink` chip beside the title moved /* Orphaned tombstone `.btn-dashlink` chip that lived beside the
into the overflow menu (`.overflow-item-dashboard` covers it). */ title was moved into the overflow menu (`.overflow-item-dashboard`
covers it now). */
.btn-cancel-turn { .btn-cancel-turn {
font-family: inherit; font-family: inherit;
font-size: 0.8em; font-size: 0.8em;
@ -716,8 +710,8 @@ pre.diff {
background: rgba(243, 139, 168, 0.1); background: rgba(243, 139, 168, 0.1);
box-shadow: 0 0 10px -2px currentColor; box-shadow: 0 0 10px -2px currentColor;
} }
/* Orphaned in #394 `.btn-new-session` round-pill moved into the /* Orphaned tombstone `.btn-new-session` round-pill moved into
overflow menu (`.overflow-item-new-session` covers it; the the overflow menu (`.overflow-item-new-session` covers it; the
`:disabled` opacity treatment lives on the shared `:disabled` opacity treatment lives on the shared
`.overflow-item:disabled` rule). */ `.overflow-item:disabled` rule). */
.state-badge { .state-badge {
@ -793,7 +787,10 @@ pre.diff {
/* Tail pill ( N new): nudged up so it floats clear of the composer /* Tail pill ( N new): nudged up so it floats clear of the composer
rather than colliding with the frosted bar. z-index bumped above rather than colliding with the frosted bar. z-index bumped above
the composer (z-30) so the pill sits on the top layer instead of the composer (z-30) so the pill sits on the top layer instead of
being clipped by the floating chrome (issue #375). */ being clipped by the floating chrome. (Pill is anchored in
`.agent-main` rather than `.terminal-wrap` see
docs/web-ui.md::Per-agent page Terminal-wrap paragraph for the
backdrop-filter stacking-context rationale.) */
.agent-main .tail-pill { .agent-main .tail-pill {
bottom: calc(var(--agent-composer-h) + 0.6em); bottom: calc(var(--agent-composer-h) + 0.6em);
z-index: 35; z-index: 35;
@ -843,10 +840,9 @@ pre.diff {
/* Row + pill + details styling moved to hive-fr0nt::TERMINAL_CSS. */ /* Row + pill + details styling moved to hive-fr0nt::TERMINAL_CSS. */
/* side panel (singleton drawer) /* side panel (singleton drawer)
Inbox + loose-ends details open here instead of expanding inline Inbox + loose-ends details open here instead of expanding inline.
(issue #360). Copy of the dashboard's side-panel pattern Copy of the dashboard's side-panel pattern candidate for
candidate for extraction into @hive/shared once both surfaces extraction into @hive/shared once both surfaces stabilize. */
stabilize. */
.side-panel { .side-panel {
position: fixed; position: fixed;
inset: 0; inset: 0;