Files
brain-of-reese/.agents/phases/todo/161_reasoning_bubble/03_container_css.md
T

5.9 KiB

Task 03 — The container's CSS

Phase: 161_reasoning_bubble · Source: TODO.md:3 — "The reasoning process should be one collapsible section that **stays open** during the reasoning process and shows all thinking and tool calls in order. Right now the thinking, tool calling, thinking, tool calling blocks take up a ton of space and obscure the answer. We need to condense this while still letting the user watch the thinking process happen so the latency doesn't feel super low. This new thinking/tool calling bubble should only collapse once the final response has been returned and the session has stopped." Story: n/a

Objective

The details.reasoning container's styling: the native details/summary treatment of the house family (the details.thinking convention — L633), the bounded 320px live window (D3), the inner-run compacting (de-bordered, one scroll surface), the reduced-motion stills — all AA-contrast, WCAG 2.1 AA basics (focusable summary ≥44px, :focus-visible, chevron).

Work

  1. frontend/assets/styles.css — the details.reasoning block (a NEW distinct comment block citing this phase + D3; placed ADJACENT to the details.thinking family — after the details.thinking .thinking-text margin rule ~L684, before the phase-117 .tool-calls-disclosure comment ~L689 — verify the actual layout in the file and keep the family blocks adjacent): background: var(--surface); border: 1px solid var(--line); border-left: 3px solid var(--brand-soft); border-radius: var(--radius-sm); margin: 0 0 0.5rem; overflow: hidden; — the family treatment of details.thinking (the same surface/line/ brand-soft/radius tokens; the comment documents the parity + the D3 window).
  2. frontend/assets/styles.css — summary.reasoning-summary: display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 0.75rem; min-height: 44px; (the WCAG ≥44px target — parity with the details.thinking summary); color: var(--brand-ink) (8.7:1 on --surface — AA — the token the details.thinking summary uses); font-size: 0.9rem; cursor: pointer; list-style: none;; summary.reasoning-summary::-webkit-details-marker { display: none }; the CSS chevron summary.reasoning-summary::before { content: "▸"; display: inline-block; transition: transform 0.15s ease; } + details.reasoning[open] summary.reasoning-summary::before { transform: rotate(90deg); } (the details.thinking convention); summary.reasoning-summary:focus-visible { outline: 3px solid var(--brand); outline-offset: 2px; } (the house 3px ring).
  3. frontend/assets/styles.css — .reasoning-status: color: var(--ink-soft) (6.9:1 on --surface — AA); font-size: 0.8rem; line-height: 1.4; margin-left: 0.25rem; (D6 — text + color, never color alone — B5; the status is a span INSIDE the summary — the flex row lays it out after the literal).
  4. frontend/assets/styles.css — .reasoning-body: padding: 0 0.75rem 0.75rem; max-height: 320px; overflow-y: auto; (D3 — the ONE bounded live window; a user-scrollable window — the phase-17 convention; the comment cites this phase + D3 + the pinned-tail follow in app.js).
  5. frontend/assets/styles.css — the inner-run compacting (D3 — the nested-border weight removed; ONE scroll surface): details.reasoning details.thinking { border: 0; border-left: 2px solid var(--line); border-radius: 0; margin: 0.25rem 0; background: transparent; } + details.reasoning details.thinking .thinking-text { max-height: none; overflow-y: visible; } (the inner 320px window disabled — the container's window is the single scroll surface; the phase-17 per-block follow in app.js no-ops accordingly — the task-01 comment) + details.reasoning .tool-calls-disclosure { margin: 0.25rem 0; } (already compact — the rule documents the intent, no visual change).
  6. frontend/assets/styles.css — the reduced-motion block (L1499, the existing details.thinking summary::before { transition: none; } stills list): append summary.reasoning-summary::before { transition: none; } (the chevron rotation stills — parity with the existing stills).
  7. No JS change in this task (the selectors the task-01/02 JS creates — reasoning / reasoning-summary / reasoning-status / reasoning-body — are the CSS contract).

Testing & Quality

  • Unit: tests/unit/test_reasoning_bubble.py (extended) — the source pins: the details.reasoning rule exists with the family tokens + overflow: hidden; the summary.reasoning-summary rule with min-height: 44px + the :focus-visible ring + the webkit-marker suppression + the chevron ::before + the [open] rotation; the .reasoning-status rule with the AA token; the .reasoning-body rule with max-height: 320px + overflow-y: auto; the inner-run compacting rules (the de-border + the max-height: none on the inner .thinking-text); the reduced-motion still appended.
  • E2E (verified in task 04's suite): the computed-style pins — .reasoning-body's max-height ≤ 320px + overflow-y: auto (the D3 contract — test 6 of test_reasoning_bubble.py per the phase overview).
  • Coverage: >90% on this task's new/modified code (frontend — the app/ gate is untouched; held by the suite).

Completion Criteria

  • tests/unit/test_reasoning_bubble.py green (uv run pytest tests/unit/test_reasoning_bubble.py -v --no-cov)
  • uv run ruff check . && uv run pyright clean (the CSS is verified by the unit source pins — no CSS lint gate)
  • the full test suite green (uv run pytest)
  • no behavior change in completed work beyond the documented inner-run compacting (the details.thinking / .tool-calls-disclosure rules OUTSIDE the container are byte-identical — the legacy no-container path renders unchanged)