Float chat components on the two Glass tiers (standard prose/bubbles/composer, dense code/diffs/plots/tools) #61

Description

@kateebonner

Important

Problem

With the Brain mounted as the Chat's full-bleed background (slice #59) and the AA-floored Glass tokens available (slice #60), the chat's content cards are still styled for a solid chat surface: user bubbles carry an opaque --surface-base fill and assistant prose has no background at all — over the living Brain they would tile the motion away or become illegible. See #56 for the "everything floats, legibly" why.

Approach

Apply slice #60's two Glass tiers to the real content cards: the standard tier on user bubbles, assistant prose, and the composer; the dense tier on code blocks, diffs, run-plots, and tool cards. Bare assistant prose gains its own standard card; muted/secondary text is routed off the ultra-transparent standard tier onto the dense tier (the prose meta on a dense-backed inline zone — slice #60's dense token, no new literal); timeline row frames and gutters stay transparent so the Brain shows in the gaps. Then re-validate that each real archetype's rendered text clears its tier's contrast floor over the running-brain reference frame in both chat themes — extending slice #60's synthetic contrast test onto a component→tier mapping.

Scope

In: the seven content archetypes get a data-glass tier (standard: user bubble, assistant prose, composer; dense: code block, diff, run-plot, tool card); the opaque bubble fill is replaced by the glass tint; assistant prose gets a standard card; muted text rides the dense tier (a dense-backed inline zone for the prose meta); row frames/gutters stay transparent; a component→tier contrast mapping is validated over the reference frame in both themes.
Out: mounting the Brain / retiring the inline strip / one render loop (slice #59 owns the room; this slice only styles what floats on it); deriving tints/blur + the synthetic reference-frame validator (slice #60 owns the tokens + contrast helpers; this slice consumes them); motion / at-rest / data-true heartbeat (slice 4); the laptop-webview perf gate + motion-ease fallback (slice 5); Rail, titlebar, Panels, and the in-timeline sticky session-title header (nav/timeline chrome stays solid — not floating content); new geometry/accent tokens (the tier token already carries radius/border/shadow — no per-component literals).


Acceptance Criteria

  • Tier assignment: the user-message bubble, the assistant prose text-part, and the composer each carry data-glass="standard"; a markdown code block, a diff view, a run-plot/run-window, and a tool card each carry data-glass="dense". No third tier value and no data-glass on any non-content element are present.
  • Nothing bare, nothing opaque: every persistent readable region above (bubble, prose, code, diff, plot, tool, composer) resolves a Glass tint whose alpha is < 1 (translucent) — none is transparent (would be illegible over the Brain) and none is opaque (would tile the Brain away).
  • Gaps stay live: the timeline row frame (session-turn) and the centered column/gutter wrappers carry no glass background and resolve a transparent background — only leaf content cards float, so the Brain is visible between top-level cards.
  • Contrast over the reference frame (both chat themes): measured with slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's validator against its worst-case running-brain reference frame — body text on a standard card clears ≥4.5:1 with the same safety margin; code/diff text on a dense card clears ≥4.5:1; graphical marks (syntax colors, diff fills, plot lines) on a dense card clear ≥3:1. The mapping is asserted per archetype, not eyeballed.
  • No muted text on standard: every muted/secondary-role text element (e.g. the copy/timestamp meta inside a prose card) sits in a dense-tier element or a dense-backed inline zone (slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's dense token — never a new tint/literal); the mapping table rejects any (muted-role → standard) pairing.
  • No ad-hoc blur/tint literal: a source scan of the seven restyled cards' style-rules finds zero backdrop-filter/blur-radius/rgba-tint literals outside slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's Glass token CSS — the scan is scoped to those card rules and explicitly excludes the in-timeline sticky session-title header's pre-existing chrome blur (out-of-scope chrome that stays), so styling the diff seam that lives alongside it does not require touching it; and the previous opaque --surface-base bubble fill is gone (replaced by the standard tint).
  • Chrome untouched: no data-glass appears on the Rail, titlebar, Panels, or the in-timeline sticky session-title header.

Testing Decisions

  • Extends slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60 test surface — component→tier contrast mapping (CREATE, alongside slice 2's glass-token contrast test): a table test over {archetype → (tier, text-role)} for the seven archetypes, asserting tierContrast(theme, tier, colorForRole(role)) ≥ floor(+margin) in both shipped chat themes using slice 2's exported contrast/tierContrast and the theme's real text tokens: body→standard ≥4.5:1+margin, code/diff→dense ≥4.5:1, marks→dense ≥3:1. The table also asserts no muted-role text maps to the standard tier — it rides dense / a dense-backed inline zone (guards the exact grey-on-glass failure the earlier build hit).
  • Tier-assignment DOM test (CREATE glass-float behavior test): render each archetype through the real message renderer / composer / tool / run-plot components and assert the correct data-glass value on the leaf card; assert the wrapping session-turn/column frame has no data-glass and a transparent resolved background (the "gaps stay live" + "nothing bare/opaque" criteria).
  • No-literal source guard (CREATE, static scan): scan the seven restyled cards' style-rules (not whole files) for backdrop-filter, blur radii, and rgba tint literals; assert zero outside the Glass token CSS; explicitly exclude the in-timeline sticky session-title header's pre-existing chrome blur (chrome that stays); and assert the user bubble no longer sets an opaque --surface-base fill.
  • Reuse existing component tests: extend the tool-card, run-card, and run-plot render tests to cover the new data-glass="dense" attribute rather than adding parallel harnesses; do not re-test the token derivation (that is slice 2's).
  • All tests are external-behavior (rendered attribute + computed style + slice-2 validator math) — none reach into engine internals or attempt live canvas/backdrop-filter pixel compositing (jsdom cannot composite backdrop-filter; the reference-frame floor stands in for "legible over the running brain").

Key Decisions

  • Tier map (the contract): standard = {user bubble, assistant prose, composer}; dense = {code block, diff, run-plot, tool card}. Composer is standard (a control surface holding body text), per the ADR grouping — the old branch's separate chrome tier collapses into standard.
  • data-glass attribute contract: values are standard | dense, defined and emitted by slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60; this slice only applies them and consumes the emitted CSS utility + validator. Applying an undefined tier value is a slice-2 change, never a local literal.
  • Assistant prose gains a card: assistant text-parts are bare (no background) today; they get a standard card so prose is legible over the Brain.
  • Nesting is conservative: a dense card nested in a standard card (code inside prose) keeps its dense tier; every tier's floor is derived over the bare worst-case Brain, and nesting only adds opacity, so contrast is guaranteed without per-nesting recomputation.
  • Muted/secondary text: rides the dense tier — the prose card's meta (copy/timestamp) is the concrete case, wrapped in a dense-backed inline zone (slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's dense token, no new literal) so it never composites directly against the standard tint. This is the ADR's "locally-dimmed zone", realized without a third token.
  • Motion lives in the gaps, not thinner cards: cards stay at slice 2's derived tint; the visible Brain comes from the transparent row gaps/gutters — do not dilute a card's tint to "let more Brain through."

Constraints & Invariants

  • Do not mount the background, retire the inline brain strip, or touch the render loop — that is slice Mount the Brain chat-wide and absorb the inline brain strip #59; this slice only styles the floating cards.
  • Do not define new glass tints, blur values, or geometry — consume slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's two tokens verbatim (they already carry radius/border/shadow); a value the tokens lack is a slice-2 change, not a per-component literal. The dense-backed inline zone for muted text uses the existing dense token — not a new one.
  • The standard tier's tint alpha is bounded below by its contrast floor; never override it lower locally.
  • Row frames (session-turn), the centered column, and inter-card gutters must never receive a glass fill — that would tile and hide the Brain.
  • Rail, titlebar, Panels, and the in-timeline sticky session-title header stay as-is; no data-glass on them, and their existing chrome blur is left untouched.
  • Amicode design-system law holds for the card chrome: geometry from the tier token, single-yellow accent — yellow is never a card fill; #fff676 stays the Brain's live-thought color.
Prior Art / Patterns Real seams to restyle (current branch): the message renderer `packages/ui/src/components/message-part.tsx` + `message-part.css` — user bubble `[data-slot="user-message-text"]` (currently `background: var(--surface-base)`), assistant `[data-component="text-part"]` / `[data-slot="text-part-body"]`, markdown code `[data-component="markdown-code"]` (`packages/ui/src/components/markdown.tsx` + `markdown.css`); the timeline `packages/app/src/pages/session/message-timeline.tsx` — `TimelineRowFrame` → `[data-component="session-turn"]`, diff group `session-turn-diffs-group` / `session-turn-diff-view` (note: this file also holds the sticky session-title header with a pre-existing `backdrop-blur` — that is out-of-scope chrome; do not touch it); the composer `packages/app/src/pages/session/composer/session-composer-region.tsx` — `[data-component="session-prompt-dock"]`; the tool card `packages/ui/src/components/basic-tool.tsx` — `[data-component="tool-trigger"]`; the run-plot `packages/ui/src/amicode/run-window.tsx` — `[data-component="amicode-run-window"]`; diffs `packages/ui/src/components/diff-changes.tsx`. Old-branch raw material to reuse (design-neutral, slice #60 lands it, this slice consumes it): `opencode-brain-atmosphere-wt/packages/ui/src/amicode/glass.css` — the `[data-glass=...]` tier utilities, the `@supports not (backdrop-filter)` opaque fallback so text never lands on bare canvas, and `glass-tokens.ts`'s `contrast`/`tierContrast` validator functions; note its three tiers (airy/dense/chrome) collapse to slice 2's two (standard/dense) with the composer moving from `chrome` to `standard`. The mounted background is slice #59's `BrainAtmosphere` (old `brain/brain-atmosphere.tsx`), which paints on a transparent, `aria-hidden`, pointer-events-none ground beneath the cards.

Source

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    afkImplement + merge unattended

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
       blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
      }
      } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
      })();
      (function(){
      try {
      var __m = "github.com";
      var __re = new RegExp('^' + "github\\.com" + '
      
      Skip to content

      Float chat components on the two Glass tiers (standard prose/bubbles/composer, dense code/diffs/plots/tools) #61

      Description

      @kateebonner

      Important

      Problem

      With the Brain mounted as the Chat's full-bleed background (slice #59) and the AA-floored Glass tokens available (slice #60), the chat's content cards are still styled for a solid chat surface: user bubbles carry an opaque --surface-base fill and assistant prose has no background at all — over the living Brain they would tile the motion away or become illegible. See #56 for the "everything floats, legibly" why.

      Approach

      Apply slice #60's two Glass tiers to the real content cards: the standard tier on user bubbles, assistant prose, and the composer; the dense tier on code blocks, diffs, run-plots, and tool cards. Bare assistant prose gains its own standard card; muted/secondary text is routed off the ultra-transparent standard tier onto the dense tier (the prose meta on a dense-backed inline zone — slice #60's dense token, no new literal); timeline row frames and gutters stay transparent so the Brain shows in the gaps. Then re-validate that each real archetype's rendered text clears its tier's contrast floor over the running-brain reference frame in both chat themes — extending slice #60's synthetic contrast test onto a component→tier mapping.

      Scope

      In: the seven content archetypes get a data-glass tier (standard: user bubble, assistant prose, composer; dense: code block, diff, run-plot, tool card); the opaque bubble fill is replaced by the glass tint; assistant prose gets a standard card; muted text rides the dense tier (a dense-backed inline zone for the prose meta); row frames/gutters stay transparent; a component→tier contrast mapping is validated over the reference frame in both themes.
      Out: mounting the Brain / retiring the inline strip / one render loop (slice #59 owns the room; this slice only styles what floats on it); deriving tints/blur + the synthetic reference-frame validator (slice #60 owns the tokens + contrast helpers; this slice consumes them); motion / at-rest / data-true heartbeat (slice 4); the laptop-webview perf gate + motion-ease fallback (slice 5); Rail, titlebar, Panels, and the in-timeline sticky session-title header (nav/timeline chrome stays solid — not floating content); new geometry/accent tokens (the tier token already carries radius/border/shadow — no per-component literals).


      Acceptance Criteria

      • Tier assignment: the user-message bubble, the assistant prose text-part, and the composer each carry data-glass="standard"; a markdown code block, a diff view, a run-plot/run-window, and a tool card each carry data-glass="dense". No third tier value and no data-glass on any non-content element are present.
      • Nothing bare, nothing opaque: every persistent readable region above (bubble, prose, code, diff, plot, tool, composer) resolves a Glass tint whose alpha is < 1 (translucent) — none is transparent (would be illegible over the Brain) and none is opaque (would tile the Brain away).
      • Gaps stay live: the timeline row frame (session-turn) and the centered column/gutter wrappers carry no glass background and resolve a transparent background — only leaf content cards float, so the Brain is visible between top-level cards.
      • Contrast over the reference frame (both chat themes): measured with slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's validator against its worst-case running-brain reference frame — body text on a standard card clears ≥4.5:1 with the same safety margin; code/diff text on a dense card clears ≥4.5:1; graphical marks (syntax colors, diff fills, plot lines) on a dense card clear ≥3:1. The mapping is asserted per archetype, not eyeballed.
      • No muted text on standard: every muted/secondary-role text element (e.g. the copy/timestamp meta inside a prose card) sits in a dense-tier element or a dense-backed inline zone (slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's dense token — never a new tint/literal); the mapping table rejects any (muted-role → standard) pairing.
      • No ad-hoc blur/tint literal: a source scan of the seven restyled cards' style-rules finds zero backdrop-filter/blur-radius/rgba-tint literals outside slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's Glass token CSS — the scan is scoped to those card rules and explicitly excludes the in-timeline sticky session-title header's pre-existing chrome blur (out-of-scope chrome that stays), so styling the diff seam that lives alongside it does not require touching it; and the previous opaque --surface-base bubble fill is gone (replaced by the standard tint).
      • Chrome untouched: no data-glass appears on the Rail, titlebar, Panels, or the in-timeline sticky session-title header.

      Testing Decisions

      • Extends slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60 test surface — component→tier contrast mapping (CREATE, alongside slice 2's glass-token contrast test): a table test over {archetype → (tier, text-role)} for the seven archetypes, asserting tierContrast(theme, tier, colorForRole(role)) ≥ floor(+margin) in both shipped chat themes using slice 2's exported contrast/tierContrast and the theme's real text tokens: body→standard ≥4.5:1+margin, code/diff→dense ≥4.5:1, marks→dense ≥3:1. The table also asserts no muted-role text maps to the standard tier — it rides dense / a dense-backed inline zone (guards the exact grey-on-glass failure the earlier build hit).
      • Tier-assignment DOM test (CREATE glass-float behavior test): render each archetype through the real message renderer / composer / tool / run-plot components and assert the correct data-glass value on the leaf card; assert the wrapping session-turn/column frame has no data-glass and a transparent resolved background (the "gaps stay live" + "nothing bare/opaque" criteria).
      • No-literal source guard (CREATE, static scan): scan the seven restyled cards' style-rules (not whole files) for backdrop-filter, blur radii, and rgba tint literals; assert zero outside the Glass token CSS; explicitly exclude the in-timeline sticky session-title header's pre-existing chrome blur (chrome that stays); and assert the user bubble no longer sets an opaque --surface-base fill.
      • Reuse existing component tests: extend the tool-card, run-card, and run-plot render tests to cover the new data-glass="dense" attribute rather than adding parallel harnesses; do not re-test the token derivation (that is slice 2's).
      • All tests are external-behavior (rendered attribute + computed style + slice-2 validator math) — none reach into engine internals or attempt live canvas/backdrop-filter pixel compositing (jsdom cannot composite backdrop-filter; the reference-frame floor stands in for "legible over the running brain").

      Key Decisions

      • Tier map (the contract): standard = {user bubble, assistant prose, composer}; dense = {code block, diff, run-plot, tool card}. Composer is standard (a control surface holding body text), per the ADR grouping — the old branch's separate chrome tier collapses into standard.
      • data-glass attribute contract: values are standard | dense, defined and emitted by slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60; this slice only applies them and consumes the emitted CSS utility + validator. Applying an undefined tier value is a slice-2 change, never a local literal.
      • Assistant prose gains a card: assistant text-parts are bare (no background) today; they get a standard card so prose is legible over the Brain.
      • Nesting is conservative: a dense card nested in a standard card (code inside prose) keeps its dense tier; every tier's floor is derived over the bare worst-case Brain, and nesting only adds opacity, so contrast is guaranteed without per-nesting recomputation.
      • Muted/secondary text: rides the dense tier — the prose card's meta (copy/timestamp) is the concrete case, wrapped in a dense-backed inline zone (slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's dense token, no new literal) so it never composites directly against the standard tint. This is the ADR's "locally-dimmed zone", realized without a third token.
      • Motion lives in the gaps, not thinner cards: cards stay at slice 2's derived tint; the visible Brain comes from the transparent row gaps/gutters — do not dilute a card's tint to "let more Brain through."

      Constraints & Invariants

      • Do not mount the background, retire the inline brain strip, or touch the render loop — that is slice Mount the Brain chat-wide and absorb the inline brain strip #59; this slice only styles the floating cards.
      • Do not define new glass tints, blur values, or geometry — consume slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's two tokens verbatim (they already carry radius/border/shadow); a value the tokens lack is a slice-2 change, not a per-component literal. The dense-backed inline zone for muted text uses the existing dense token — not a new one.
      • The standard tier's tint alpha is bounded below by its contrast floor; never override it lower locally.
      • Row frames (session-turn), the centered column, and inter-card gutters must never receive a glass fill — that would tile and hide the Brain.
      • Rail, titlebar, Panels, and the in-timeline sticky session-title header stay as-is; no data-glass on them, and their existing chrome blur is left untouched.
      • Amicode design-system law holds for the card chrome: geometry from the tier token, single-yellow accent — yellow is never a card fill; #fff676 stays the Brain's live-thought color.
      Prior Art / Patterns Real seams to restyle (current branch): the message renderer `packages/ui/src/components/message-part.tsx` + `message-part.css` — user bubble `[data-slot="user-message-text"]` (currently `background: var(--surface-base)`), assistant `[data-component="text-part"]` / `[data-slot="text-part-body"]`, markdown code `[data-component="markdown-code"]` (`packages/ui/src/components/markdown.tsx` + `markdown.css`); the timeline `packages/app/src/pages/session/message-timeline.tsx` — `TimelineRowFrame` → `[data-component="session-turn"]`, diff group `session-turn-diffs-group` / `session-turn-diff-view` (note: this file also holds the sticky session-title header with a pre-existing `backdrop-blur` — that is out-of-scope chrome; do not touch it); the composer `packages/app/src/pages/session/composer/session-composer-region.tsx` — `[data-component="session-prompt-dock"]`; the tool card `packages/ui/src/components/basic-tool.tsx` — `[data-component="tool-trigger"]`; the run-plot `packages/ui/src/amicode/run-window.tsx` — `[data-component="amicode-run-window"]`; diffs `packages/ui/src/components/diff-changes.tsx`. Old-branch raw material to reuse (design-neutral, slice #60 lands it, this slice consumes it): `opencode-brain-atmosphere-wt/packages/ui/src/amicode/glass.css` — the `[data-glass=...]` tier utilities, the `@supports not (backdrop-filter)` opaque fallback so text never lands on bare canvas, and `glass-tokens.ts`'s `contrast`/`tierContrast` validator functions; note its three tiers (airy/dense/chrome) collapse to slice 2's two (standard/dense) with the composer moving from `chrome` to `standard`. The mounted background is slice #59's `BrainAtmosphere` (old `brain/brain-atmosphere.tsx`), which paints on a transparent, `aria-hidden`, pointer-events-none ground beneath the cards.

      Source

      Activity

      Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

      Metadata

      Metadata

      Assignees

      No one assigned

        Labels

        afkImplement + merge unattended

        Type

        No type

        Projects

        No projects

          Milestone

          No milestone

          Relationships

          None yet

          Development

          No branches or pull requests

          Issue actions

          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
          Skip to content

          Float chat components on the two Glass tiers (standard prose/bubbles/composer, dense code/diffs/plots/tools) #61

          Description

          @kateebonner

          Important

          Problem

          With the Brain mounted as the Chat's full-bleed background (slice #59) and the AA-floored Glass tokens available (slice #60), the chat's content cards are still styled for a solid chat surface: user bubbles carry an opaque --surface-base fill and assistant prose has no background at all — over the living Brain they would tile the motion away or become illegible. See #56 for the "everything floats, legibly" why.

          Approach

          Apply slice #60's two Glass tiers to the real content cards: the standard tier on user bubbles, assistant prose, and the composer; the dense tier on code blocks, diffs, run-plots, and tool cards. Bare assistant prose gains its own standard card; muted/secondary text is routed off the ultra-transparent standard tier onto the dense tier (the prose meta on a dense-backed inline zone — slice #60's dense token, no new literal); timeline row frames and gutters stay transparent so the Brain shows in the gaps. Then re-validate that each real archetype's rendered text clears its tier's contrast floor over the running-brain reference frame in both chat themes — extending slice #60's synthetic contrast test onto a component→tier mapping.

          Scope

          In: the seven content archetypes get a data-glass tier (standard: user bubble, assistant prose, composer; dense: code block, diff, run-plot, tool card); the opaque bubble fill is replaced by the glass tint; assistant prose gets a standard card; muted text rides the dense tier (a dense-backed inline zone for the prose meta); row frames/gutters stay transparent; a component→tier contrast mapping is validated over the reference frame in both themes.
          Out: mounting the Brain / retiring the inline strip / one render loop (slice #59 owns the room; this slice only styles what floats on it); deriving tints/blur + the synthetic reference-frame validator (slice #60 owns the tokens + contrast helpers; this slice consumes them); motion / at-rest / data-true heartbeat (slice 4); the laptop-webview perf gate + motion-ease fallback (slice 5); Rail, titlebar, Panels, and the in-timeline sticky session-title header (nav/timeline chrome stays solid — not floating content); new geometry/accent tokens (the tier token already carries radius/border/shadow — no per-component literals).


          Acceptance Criteria

          • Tier assignment: the user-message bubble, the assistant prose text-part, and the composer each carry data-glass="standard"; a markdown code block, a diff view, a run-plot/run-window, and a tool card each carry data-glass="dense". No third tier value and no data-glass on any non-content element are present.
          • Nothing bare, nothing opaque: every persistent readable region above (bubble, prose, code, diff, plot, tool, composer) resolves a Glass tint whose alpha is < 1 (translucent) — none is transparent (would be illegible over the Brain) and none is opaque (would tile the Brain away).
          • Gaps stay live: the timeline row frame (session-turn) and the centered column/gutter wrappers carry no glass background and resolve a transparent background — only leaf content cards float, so the Brain is visible between top-level cards.
          • Contrast over the reference frame (both chat themes): measured with slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's validator against its worst-case running-brain reference frame — body text on a standard card clears ≥4.5:1 with the same safety margin; code/diff text on a dense card clears ≥4.5:1; graphical marks (syntax colors, diff fills, plot lines) on a dense card clear ≥3:1. The mapping is asserted per archetype, not eyeballed.
          • No muted text on standard: every muted/secondary-role text element (e.g. the copy/timestamp meta inside a prose card) sits in a dense-tier element or a dense-backed inline zone (slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's dense token — never a new tint/literal); the mapping table rejects any (muted-role → standard) pairing.
          • No ad-hoc blur/tint literal: a source scan of the seven restyled cards' style-rules finds zero backdrop-filter/blur-radius/rgba-tint literals outside slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's Glass token CSS — the scan is scoped to those card rules and explicitly excludes the in-timeline sticky session-title header's pre-existing chrome blur (out-of-scope chrome that stays), so styling the diff seam that lives alongside it does not require touching it; and the previous opaque --surface-base bubble fill is gone (replaced by the standard tint).
          • Chrome untouched: no data-glass appears on the Rail, titlebar, Panels, or the in-timeline sticky session-title header.

          Testing Decisions

          • Extends slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60 test surface — component→tier contrast mapping (CREATE, alongside slice 2's glass-token contrast test): a table test over {archetype → (tier, text-role)} for the seven archetypes, asserting tierContrast(theme, tier, colorForRole(role)) ≥ floor(+margin) in both shipped chat themes using slice 2's exported contrast/tierContrast and the theme's real text tokens: body→standard ≥4.5:1+margin, code/diff→dense ≥4.5:1, marks→dense ≥3:1. The table also asserts no muted-role text maps to the standard tier — it rides dense / a dense-backed inline zone (guards the exact grey-on-glass failure the earlier build hit).
          • Tier-assignment DOM test (CREATE glass-float behavior test): render each archetype through the real message renderer / composer / tool / run-plot components and assert the correct data-glass value on the leaf card; assert the wrapping session-turn/column frame has no data-glass and a transparent resolved background (the "gaps stay live" + "nothing bare/opaque" criteria).
          • No-literal source guard (CREATE, static scan): scan the seven restyled cards' style-rules (not whole files) for backdrop-filter, blur radii, and rgba tint literals; assert zero outside the Glass token CSS; explicitly exclude the in-timeline sticky session-title header's pre-existing chrome blur (chrome that stays); and assert the user bubble no longer sets an opaque --surface-base fill.
          • Reuse existing component tests: extend the tool-card, run-card, and run-plot render tests to cover the new data-glass="dense" attribute rather than adding parallel harnesses; do not re-test the token derivation (that is slice 2's).
          • All tests are external-behavior (rendered attribute + computed style + slice-2 validator math) — none reach into engine internals or attempt live canvas/backdrop-filter pixel compositing (jsdom cannot composite backdrop-filter; the reference-frame floor stands in for "legible over the running brain").

          Key Decisions

          • Tier map (the contract): standard = {user bubble, assistant prose, composer}; dense = {code block, diff, run-plot, tool card}. Composer is standard (a control surface holding body text), per the ADR grouping — the old branch's separate chrome tier collapses into standard.
          • data-glass attribute contract: values are standard | dense, defined and emitted by slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60; this slice only applies them and consumes the emitted CSS utility + validator. Applying an undefined tier value is a slice-2 change, never a local literal.
          • Assistant prose gains a card: assistant text-parts are bare (no background) today; they get a standard card so prose is legible over the Brain.
          • Nesting is conservative: a dense card nested in a standard card (code inside prose) keeps its dense tier; every tier's floor is derived over the bare worst-case Brain, and nesting only adds opacity, so contrast is guaranteed without per-nesting recomputation.
          • Muted/secondary text: rides the dense tier — the prose card's meta (copy/timestamp) is the concrete case, wrapped in a dense-backed inline zone (slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's dense token, no new literal) so it never composites directly against the standard tint. This is the ADR's "locally-dimmed zone", realized without a third token.
          • Motion lives in the gaps, not thinner cards: cards stay at slice 2's derived tint; the visible Brain comes from the transparent row gaps/gutters — do not dilute a card's tint to "let more Brain through."

          Constraints & Invariants

          • Do not mount the background, retire the inline brain strip, or touch the render loop — that is slice Mount the Brain chat-wide and absorb the inline brain strip #59; this slice only styles the floating cards.
          • Do not define new glass tints, blur values, or geometry — consume slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's two tokens verbatim (they already carry radius/border/shadow); a value the tokens lack is a slice-2 change, not a per-component literal. The dense-backed inline zone for muted text uses the existing dense token — not a new one.
          • The standard tier's tint alpha is bounded below by its contrast floor; never override it lower locally.
          • Row frames (session-turn), the centered column, and inter-card gutters must never receive a glass fill — that would tile and hide the Brain.
          • Rail, titlebar, Panels, and the in-timeline sticky session-title header stay as-is; no data-glass on them, and their existing chrome blur is left untouched.
          • Amicode design-system law holds for the card chrome: geometry from the tier token, single-yellow accent — yellow is never a card fill; #fff676 stays the Brain's live-thought color.
          Prior Art / Patterns Real seams to restyle (current branch): the message renderer `packages/ui/src/components/message-part.tsx` + `message-part.css` — user bubble `[data-slot="user-message-text"]` (currently `background: var(--surface-base)`), assistant `[data-component="text-part"]` / `[data-slot="text-part-body"]`, markdown code `[data-component="markdown-code"]` (`packages/ui/src/components/markdown.tsx` + `markdown.css`); the timeline `packages/app/src/pages/session/message-timeline.tsx` — `TimelineRowFrame` → `[data-component="session-turn"]`, diff group `session-turn-diffs-group` / `session-turn-diff-view` (note: this file also holds the sticky session-title header with a pre-existing `backdrop-blur` — that is out-of-scope chrome; do not touch it); the composer `packages/app/src/pages/session/composer/session-composer-region.tsx` — `[data-component="session-prompt-dock"]`; the tool card `packages/ui/src/components/basic-tool.tsx` — `[data-component="tool-trigger"]`; the run-plot `packages/ui/src/amicode/run-window.tsx` — `[data-component="amicode-run-window"]`; diffs `packages/ui/src/components/diff-changes.tsx`. Old-branch raw material to reuse (design-neutral, slice #60 lands it, this slice consumes it): `opencode-brain-atmosphere-wt/packages/ui/src/amicode/glass.css` — the `[data-glass=...]` tier utilities, the `@supports not (backdrop-filter)` opaque fallback so text never lands on bare canvas, and `glass-tokens.ts`'s `contrast`/`tierContrast` validator functions; note its three tiers (airy/dense/chrome) collapse to slice 2's two (standard/dense) with the composer moving from `chrome` to `standard`. The mounted background is slice #59's `BrainAtmosphere` (old `brain/brain-atmosphere.tsx`), which paints on a transparent, `aria-hidden`, pointer-events-none ground beneath the cards.

          Source

          Activity

          Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

          Metadata

          Metadata

          Assignees

          No one assigned

            Labels

            afkImplement + merge unattended

            Type

            No type

            Projects

            No projects

              Milestone

              No milestone

              Relationships

              None yet

              Development

              No branches or pull requests

              Issue actions

              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
              Skip to content

              Float chat components on the two Glass tiers (standard prose/bubbles/composer, dense code/diffs/plots/tools) #61

              Description

              @kateebonner

              Important

              Problem

              With the Brain mounted as the Chat's full-bleed background (slice #59) and the AA-floored Glass tokens available (slice #60), the chat's content cards are still styled for a solid chat surface: user bubbles carry an opaque --surface-base fill and assistant prose has no background at all — over the living Brain they would tile the motion away or become illegible. See #56 for the "everything floats, legibly" why.

              Approach

              Apply slice #60's two Glass tiers to the real content cards: the standard tier on user bubbles, assistant prose, and the composer; the dense tier on code blocks, diffs, run-plots, and tool cards. Bare assistant prose gains its own standard card; muted/secondary text is routed off the ultra-transparent standard tier onto the dense tier (the prose meta on a dense-backed inline zone — slice #60's dense token, no new literal); timeline row frames and gutters stay transparent so the Brain shows in the gaps. Then re-validate that each real archetype's rendered text clears its tier's contrast floor over the running-brain reference frame in both chat themes — extending slice #60's synthetic contrast test onto a component→tier mapping.

              Scope

              In: the seven content archetypes get a data-glass tier (standard: user bubble, assistant prose, composer; dense: code block, diff, run-plot, tool card); the opaque bubble fill is replaced by the glass tint; assistant prose gets a standard card; muted text rides the dense tier (a dense-backed inline zone for the prose meta); row frames/gutters stay transparent; a component→tier contrast mapping is validated over the reference frame in both themes.
              Out: mounting the Brain / retiring the inline strip / one render loop (slice #59 owns the room; this slice only styles what floats on it); deriving tints/blur + the synthetic reference-frame validator (slice #60 owns the tokens + contrast helpers; this slice consumes them); motion / at-rest / data-true heartbeat (slice 4); the laptop-webview perf gate + motion-ease fallback (slice 5); Rail, titlebar, Panels, and the in-timeline sticky session-title header (nav/timeline chrome stays solid — not floating content); new geometry/accent tokens (the tier token already carries radius/border/shadow — no per-component literals).


              Acceptance Criteria

              • Tier assignment: the user-message bubble, the assistant prose text-part, and the composer each carry data-glass="standard"; a markdown code block, a diff view, a run-plot/run-window, and a tool card each carry data-glass="dense". No third tier value and no data-glass on any non-content element are present.
              • Nothing bare, nothing opaque: every persistent readable region above (bubble, prose, code, diff, plot, tool, composer) resolves a Glass tint whose alpha is < 1 (translucent) — none is transparent (would be illegible over the Brain) and none is opaque (would tile the Brain away).
              • Gaps stay live: the timeline row frame (session-turn) and the centered column/gutter wrappers carry no glass background and resolve a transparent background — only leaf content cards float, so the Brain is visible between top-level cards.
              • Contrast over the reference frame (both chat themes): measured with slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's validator against its worst-case running-brain reference frame — body text on a standard card clears ≥4.5:1 with the same safety margin; code/diff text on a dense card clears ≥4.5:1; graphical marks (syntax colors, diff fills, plot lines) on a dense card clear ≥3:1. The mapping is asserted per archetype, not eyeballed.
              • No muted text on standard: every muted/secondary-role text element (e.g. the copy/timestamp meta inside a prose card) sits in a dense-tier element or a dense-backed inline zone (slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's dense token — never a new tint/literal); the mapping table rejects any (muted-role → standard) pairing.
              • No ad-hoc blur/tint literal: a source scan of the seven restyled cards' style-rules finds zero backdrop-filter/blur-radius/rgba-tint literals outside slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's Glass token CSS — the scan is scoped to those card rules and explicitly excludes the in-timeline sticky session-title header's pre-existing chrome blur (out-of-scope chrome that stays), so styling the diff seam that lives alongside it does not require touching it; and the previous opaque --surface-base bubble fill is gone (replaced by the standard tint).
              • Chrome untouched: no data-glass appears on the Rail, titlebar, Panels, or the in-timeline sticky session-title header.

              Testing Decisions

              • Extends slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60 test surface — component→tier contrast mapping (CREATE, alongside slice 2's glass-token contrast test): a table test over {archetype → (tier, text-role)} for the seven archetypes, asserting tierContrast(theme, tier, colorForRole(role)) ≥ floor(+margin) in both shipped chat themes using slice 2's exported contrast/tierContrast and the theme's real text tokens: body→standard ≥4.5:1+margin, code/diff→dense ≥4.5:1, marks→dense ≥3:1. The table also asserts no muted-role text maps to the standard tier — it rides dense / a dense-backed inline zone (guards the exact grey-on-glass failure the earlier build hit).
              • Tier-assignment DOM test (CREATE glass-float behavior test): render each archetype through the real message renderer / composer / tool / run-plot components and assert the correct data-glass value on the leaf card; assert the wrapping session-turn/column frame has no data-glass and a transparent resolved background (the "gaps stay live" + "nothing bare/opaque" criteria).
              • No-literal source guard (CREATE, static scan): scan the seven restyled cards' style-rules (not whole files) for backdrop-filter, blur radii, and rgba tint literals; assert zero outside the Glass token CSS; explicitly exclude the in-timeline sticky session-title header's pre-existing chrome blur (chrome that stays); and assert the user bubble no longer sets an opaque --surface-base fill.
              • Reuse existing component tests: extend the tool-card, run-card, and run-plot render tests to cover the new data-glass="dense" attribute rather than adding parallel harnesses; do not re-test the token derivation (that is slice 2's).
              • All tests are external-behavior (rendered attribute + computed style + slice-2 validator math) — none reach into engine internals or attempt live canvas/backdrop-filter pixel compositing (jsdom cannot composite backdrop-filter; the reference-frame floor stands in for "legible over the running brain").

              Key Decisions

              • Tier map (the contract): standard = {user bubble, assistant prose, composer}; dense = {code block, diff, run-plot, tool card}. Composer is standard (a control surface holding body text), per the ADR grouping — the old branch's separate chrome tier collapses into standard.
              • data-glass attribute contract: values are standard | dense, defined and emitted by slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60; this slice only applies them and consumes the emitted CSS utility + validator. Applying an undefined tier value is a slice-2 change, never a local literal.
              • Assistant prose gains a card: assistant text-parts are bare (no background) today; they get a standard card so prose is legible over the Brain.
              • Nesting is conservative: a dense card nested in a standard card (code inside prose) keeps its dense tier; every tier's floor is derived over the bare worst-case Brain, and nesting only adds opacity, so contrast is guaranteed without per-nesting recomputation.
              • Muted/secondary text: rides the dense tier — the prose card's meta (copy/timestamp) is the concrete case, wrapped in a dense-backed inline zone (slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's dense token, no new literal) so it never composites directly against the standard tint. This is the ADR's "locally-dimmed zone", realized without a third token.
              • Motion lives in the gaps, not thinner cards: cards stay at slice 2's derived tint; the visible Brain comes from the transparent row gaps/gutters — do not dilute a card's tint to "let more Brain through."

              Constraints & Invariants

              • Do not mount the background, retire the inline brain strip, or touch the render loop — that is slice Mount the Brain chat-wide and absorb the inline brain strip #59; this slice only styles the floating cards.
              • Do not define new glass tints, blur values, or geometry — consume slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's two tokens verbatim (they already carry radius/border/shadow); a value the tokens lack is a slice-2 change, not a per-component literal. The dense-backed inline zone for muted text uses the existing dense token — not a new one.
              • The standard tier's tint alpha is bounded below by its contrast floor; never override it lower locally.
              • Row frames (session-turn), the centered column, and inter-card gutters must never receive a glass fill — that would tile and hide the Brain.
              • Rail, titlebar, Panels, and the in-timeline sticky session-title header stay as-is; no data-glass on them, and their existing chrome blur is left untouched.
              • Amicode design-system law holds for the card chrome: geometry from the tier token, single-yellow accent — yellow is never a card fill; #fff676 stays the Brain's live-thought color.
              Prior Art / Patterns Real seams to restyle (current branch): the message renderer `packages/ui/src/components/message-part.tsx` + `message-part.css` — user bubble `[data-slot="user-message-text"]` (currently `background: var(--surface-base)`), assistant `[data-component="text-part"]` / `[data-slot="text-part-body"]`, markdown code `[data-component="markdown-code"]` (`packages/ui/src/components/markdown.tsx` + `markdown.css`); the timeline `packages/app/src/pages/session/message-timeline.tsx` — `TimelineRowFrame` → `[data-component="session-turn"]`, diff group `session-turn-diffs-group` / `session-turn-diff-view` (note: this file also holds the sticky session-title header with a pre-existing `backdrop-blur` — that is out-of-scope chrome; do not touch it); the composer `packages/app/src/pages/session/composer/session-composer-region.tsx` — `[data-component="session-prompt-dock"]`; the tool card `packages/ui/src/components/basic-tool.tsx` — `[data-component="tool-trigger"]`; the run-plot `packages/ui/src/amicode/run-window.tsx` — `[data-component="amicode-run-window"]`; diffs `packages/ui/src/components/diff-changes.tsx`. Old-branch raw material to reuse (design-neutral, slice #60 lands it, this slice consumes it): `opencode-brain-atmosphere-wt/packages/ui/src/amicode/glass.css` — the `[data-glass=...]` tier utilities, the `@supports not (backdrop-filter)` opaque fallback so text never lands on bare canvas, and `glass-tokens.ts`'s `contrast`/`tierContrast` validator functions; note its three tiers (airy/dense/chrome) collapse to slice 2's two (standard/dense) with the composer moving from `chrome` to `standard`. The mounted background is slice #59's `BrainAtmosphere` (old `brain/brain-atmosphere.tsx`), which paints on a transparent, `aria-hidden`, pointer-events-none ground beneath the cards.

              Source

              Activity

              Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

              Metadata

              Metadata

              Assignees

              No one assigned

                Labels

                afkImplement + merge unattended

                Type

                No type

                Projects

                No projects

                  Milestone

                  No milestone

                  Relationships

                  None yet

                  Development

                  No branches or pull requests

                  Issue actions

                  , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
                  Skip to content

                  Float chat components on the two Glass tiers (standard prose/bubbles/composer, dense code/diffs/plots/tools) #61

                  Description

                  @kateebonner

                  Important

                  Problem

                  With the Brain mounted as the Chat's full-bleed background (slice #59) and the AA-floored Glass tokens available (slice #60), the chat's content cards are still styled for a solid chat surface: user bubbles carry an opaque --surface-base fill and assistant prose has no background at all — over the living Brain they would tile the motion away or become illegible. See #56 for the "everything floats, legibly" why.

                  Approach

                  Apply slice #60's two Glass tiers to the real content cards: the standard tier on user bubbles, assistant prose, and the composer; the dense tier on code blocks, diffs, run-plots, and tool cards. Bare assistant prose gains its own standard card; muted/secondary text is routed off the ultra-transparent standard tier onto the dense tier (the prose meta on a dense-backed inline zone — slice #60's dense token, no new literal); timeline row frames and gutters stay transparent so the Brain shows in the gaps. Then re-validate that each real archetype's rendered text clears its tier's contrast floor over the running-brain reference frame in both chat themes — extending slice #60's synthetic contrast test onto a component→tier mapping.

                  Scope

                  In: the seven content archetypes get a data-glass tier (standard: user bubble, assistant prose, composer; dense: code block, diff, run-plot, tool card); the opaque bubble fill is replaced by the glass tint; assistant prose gets a standard card; muted text rides the dense tier (a dense-backed inline zone for the prose meta); row frames/gutters stay transparent; a component→tier contrast mapping is validated over the reference frame in both themes.
                  Out: mounting the Brain / retiring the inline strip / one render loop (slice #59 owns the room; this slice only styles what floats on it); deriving tints/blur + the synthetic reference-frame validator (slice #60 owns the tokens + contrast helpers; this slice consumes them); motion / at-rest / data-true heartbeat (slice 4); the laptop-webview perf gate + motion-ease fallback (slice 5); Rail, titlebar, Panels, and the in-timeline sticky session-title header (nav/timeline chrome stays solid — not floating content); new geometry/accent tokens (the tier token already carries radius/border/shadow — no per-component literals).


                  Acceptance Criteria

                  • Tier assignment: the user-message bubble, the assistant prose text-part, and the composer each carry data-glass="standard"; a markdown code block, a diff view, a run-plot/run-window, and a tool card each carry data-glass="dense". No third tier value and no data-glass on any non-content element are present.
                  • Nothing bare, nothing opaque: every persistent readable region above (bubble, prose, code, diff, plot, tool, composer) resolves a Glass tint whose alpha is < 1 (translucent) — none is transparent (would be illegible over the Brain) and none is opaque (would tile the Brain away).
                  • Gaps stay live: the timeline row frame (session-turn) and the centered column/gutter wrappers carry no glass background and resolve a transparent background — only leaf content cards float, so the Brain is visible between top-level cards.
                  • Contrast over the reference frame (both chat themes): measured with slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's validator against its worst-case running-brain reference frame — body text on a standard card clears ≥4.5:1 with the same safety margin; code/diff text on a dense card clears ≥4.5:1; graphical marks (syntax colors, diff fills, plot lines) on a dense card clear ≥3:1. The mapping is asserted per archetype, not eyeballed.
                  • No muted text on standard: every muted/secondary-role text element (e.g. the copy/timestamp meta inside a prose card) sits in a dense-tier element or a dense-backed inline zone (slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's dense token — never a new tint/literal); the mapping table rejects any (muted-role → standard) pairing.
                  • No ad-hoc blur/tint literal: a source scan of the seven restyled cards' style-rules finds zero backdrop-filter/blur-radius/rgba-tint literals outside slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's Glass token CSS — the scan is scoped to those card rules and explicitly excludes the in-timeline sticky session-title header's pre-existing chrome blur (out-of-scope chrome that stays), so styling the diff seam that lives alongside it does not require touching it; and the previous opaque --surface-base bubble fill is gone (replaced by the standard tint).
                  • Chrome untouched: no data-glass appears on the Rail, titlebar, Panels, or the in-timeline sticky session-title header.

                  Testing Decisions

                  • Extends slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60 test surface — component→tier contrast mapping (CREATE, alongside slice 2's glass-token contrast test): a table test over {archetype → (tier, text-role)} for the seven archetypes, asserting tierContrast(theme, tier, colorForRole(role)) ≥ floor(+margin) in both shipped chat themes using slice 2's exported contrast/tierContrast and the theme's real text tokens: body→standard ≥4.5:1+margin, code/diff→dense ≥4.5:1, marks→dense ≥3:1. The table also asserts no muted-role text maps to the standard tier — it rides dense / a dense-backed inline zone (guards the exact grey-on-glass failure the earlier build hit).
                  • Tier-assignment DOM test (CREATE glass-float behavior test): render each archetype through the real message renderer / composer / tool / run-plot components and assert the correct data-glass value on the leaf card; assert the wrapping session-turn/column frame has no data-glass and a transparent resolved background (the "gaps stay live" + "nothing bare/opaque" criteria).
                  • No-literal source guard (CREATE, static scan): scan the seven restyled cards' style-rules (not whole files) for backdrop-filter, blur radii, and rgba tint literals; assert zero outside the Glass token CSS; explicitly exclude the in-timeline sticky session-title header's pre-existing chrome blur (chrome that stays); and assert the user bubble no longer sets an opaque --surface-base fill.
                  • Reuse existing component tests: extend the tool-card, run-card, and run-plot render tests to cover the new data-glass="dense" attribute rather than adding parallel harnesses; do not re-test the token derivation (that is slice 2's).
                  • All tests are external-behavior (rendered attribute + computed style + slice-2 validator math) — none reach into engine internals or attempt live canvas/backdrop-filter pixel compositing (jsdom cannot composite backdrop-filter; the reference-frame floor stands in for "legible over the running brain").

                  Key Decisions

                  • Tier map (the contract): standard = {user bubble, assistant prose, composer}; dense = {code block, diff, run-plot, tool card}. Composer is standard (a control surface holding body text), per the ADR grouping — the old branch's separate chrome tier collapses into standard.
                  • data-glass attribute contract: values are standard | dense, defined and emitted by slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60; this slice only applies them and consumes the emitted CSS utility + validator. Applying an undefined tier value is a slice-2 change, never a local literal.
                  • Assistant prose gains a card: assistant text-parts are bare (no background) today; they get a standard card so prose is legible over the Brain.
                  • Nesting is conservative: a dense card nested in a standard card (code inside prose) keeps its dense tier; every tier's floor is derived over the bare worst-case Brain, and nesting only adds opacity, so contrast is guaranteed without per-nesting recomputation.
                  • Muted/secondary text: rides the dense tier — the prose card's meta (copy/timestamp) is the concrete case, wrapped in a dense-backed inline zone (slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's dense token, no new literal) so it never composites directly against the standard tint. This is the ADR's "locally-dimmed zone", realized without a third token.
                  • Motion lives in the gaps, not thinner cards: cards stay at slice 2's derived tint; the visible Brain comes from the transparent row gaps/gutters — do not dilute a card's tint to "let more Brain through."

                  Constraints & Invariants

                  • Do not mount the background, retire the inline brain strip, or touch the render loop — that is slice Mount the Brain chat-wide and absorb the inline brain strip #59; this slice only styles the floating cards.
                  • Do not define new glass tints, blur values, or geometry — consume slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's two tokens verbatim (they already carry radius/border/shadow); a value the tokens lack is a slice-2 change, not a per-component literal. The dense-backed inline zone for muted text uses the existing dense token — not a new one.
                  • The standard tier's tint alpha is bounded below by its contrast floor; never override it lower locally.
                  • Row frames (session-turn), the centered column, and inter-card gutters must never receive a glass fill — that would tile and hide the Brain.
                  • Rail, titlebar, Panels, and the in-timeline sticky session-title header stay as-is; no data-glass on them, and their existing chrome blur is left untouched.
                  • Amicode design-system law holds for the card chrome: geometry from the tier token, single-yellow accent — yellow is never a card fill; #fff676 stays the Brain's live-thought color.
                  Prior Art / Patterns Real seams to restyle (current branch): the message renderer `packages/ui/src/components/message-part.tsx` + `message-part.css` — user bubble `[data-slot="user-message-text"]` (currently `background: var(--surface-base)`), assistant `[data-component="text-part"]` / `[data-slot="text-part-body"]`, markdown code `[data-component="markdown-code"]` (`packages/ui/src/components/markdown.tsx` + `markdown.css`); the timeline `packages/app/src/pages/session/message-timeline.tsx` — `TimelineRowFrame` → `[data-component="session-turn"]`, diff group `session-turn-diffs-group` / `session-turn-diff-view` (note: this file also holds the sticky session-title header with a pre-existing `backdrop-blur` — that is out-of-scope chrome; do not touch it); the composer `packages/app/src/pages/session/composer/session-composer-region.tsx` — `[data-component="session-prompt-dock"]`; the tool card `packages/ui/src/components/basic-tool.tsx` — `[data-component="tool-trigger"]`; the run-plot `packages/ui/src/amicode/run-window.tsx` — `[data-component="amicode-run-window"]`; diffs `packages/ui/src/components/diff-changes.tsx`. Old-branch raw material to reuse (design-neutral, slice #60 lands it, this slice consumes it): `opencode-brain-atmosphere-wt/packages/ui/src/amicode/glass.css` — the `[data-glass=...]` tier utilities, the `@supports not (backdrop-filter)` opaque fallback so text never lands on bare canvas, and `glass-tokens.ts`'s `contrast`/`tierContrast` validator functions; note its three tiers (airy/dense/chrome) collapse to slice 2's two (standard/dense) with the composer moving from `chrome` to `standard`. The mounted background is slice #59's `BrainAtmosphere` (old `brain/brain-atmosphere.tsx`), which paints on a transparent, `aria-hidden`, pointer-events-none ground beneath the cards.

                  Source

                  Activity

                  Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

                  Metadata

                  Metadata

                  Assignees

                  No one assigned

                    Labels

                    afkImplement + merge unattended

                    Type

                    No type

                    Projects

                    No projects

                      Milestone

                      No milestone

                      Relationships

                      None yet

                      Development

                      No branches or pull requests

                      Issue actions

                      , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
                      Skip to content

                      Float chat components on the two Glass tiers (standard prose/bubbles/composer, dense code/diffs/plots/tools) #61

                      Description

                      @kateebonner

                      Important

                      Problem

                      With the Brain mounted as the Chat's full-bleed background (slice #59) and the AA-floored Glass tokens available (slice #60), the chat's content cards are still styled for a solid chat surface: user bubbles carry an opaque --surface-base fill and assistant prose has no background at all — over the living Brain they would tile the motion away or become illegible. See #56 for the "everything floats, legibly" why.

                      Approach

                      Apply slice #60's two Glass tiers to the real content cards: the standard tier on user bubbles, assistant prose, and the composer; the dense tier on code blocks, diffs, run-plots, and tool cards. Bare assistant prose gains its own standard card; muted/secondary text is routed off the ultra-transparent standard tier onto the dense tier (the prose meta on a dense-backed inline zone — slice #60's dense token, no new literal); timeline row frames and gutters stay transparent so the Brain shows in the gaps. Then re-validate that each real archetype's rendered text clears its tier's contrast floor over the running-brain reference frame in both chat themes — extending slice #60's synthetic contrast test onto a component→tier mapping.

                      Scope

                      In: the seven content archetypes get a data-glass tier (standard: user bubble, assistant prose, composer; dense: code block, diff, run-plot, tool card); the opaque bubble fill is replaced by the glass tint; assistant prose gets a standard card; muted text rides the dense tier (a dense-backed inline zone for the prose meta); row frames/gutters stay transparent; a component→tier contrast mapping is validated over the reference frame in both themes.
                      Out: mounting the Brain / retiring the inline strip / one render loop (slice #59 owns the room; this slice only styles what floats on it); deriving tints/blur + the synthetic reference-frame validator (slice #60 owns the tokens + contrast helpers; this slice consumes them); motion / at-rest / data-true heartbeat (slice 4); the laptop-webview perf gate + motion-ease fallback (slice 5); Rail, titlebar, Panels, and the in-timeline sticky session-title header (nav/timeline chrome stays solid — not floating content); new geometry/accent tokens (the tier token already carries radius/border/shadow — no per-component literals).


                      Acceptance Criteria

                      • Tier assignment: the user-message bubble, the assistant prose text-part, and the composer each carry data-glass="standard"; a markdown code block, a diff view, a run-plot/run-window, and a tool card each carry data-glass="dense". No third tier value and no data-glass on any non-content element are present.
                      • Nothing bare, nothing opaque: every persistent readable region above (bubble, prose, code, diff, plot, tool, composer) resolves a Glass tint whose alpha is < 1 (translucent) — none is transparent (would be illegible over the Brain) and none is opaque (would tile the Brain away).
                      • Gaps stay live: the timeline row frame (session-turn) and the centered column/gutter wrappers carry no glass background and resolve a transparent background — only leaf content cards float, so the Brain is visible between top-level cards.
                      • Contrast over the reference frame (both chat themes): measured with slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's validator against its worst-case running-brain reference frame — body text on a standard card clears ≥4.5:1 with the same safety margin; code/diff text on a dense card clears ≥4.5:1; graphical marks (syntax colors, diff fills, plot lines) on a dense card clear ≥3:1. The mapping is asserted per archetype, not eyeballed.
                      • No muted text on standard: every muted/secondary-role text element (e.g. the copy/timestamp meta inside a prose card) sits in a dense-tier element or a dense-backed inline zone (slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's dense token — never a new tint/literal); the mapping table rejects any (muted-role → standard) pairing.
                      • No ad-hoc blur/tint literal: a source scan of the seven restyled cards' style-rules finds zero backdrop-filter/blur-radius/rgba-tint literals outside slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's Glass token CSS — the scan is scoped to those card rules and explicitly excludes the in-timeline sticky session-title header's pre-existing chrome blur (out-of-scope chrome that stays), so styling the diff seam that lives alongside it does not require touching it; and the previous opaque --surface-base bubble fill is gone (replaced by the standard tint).
                      • Chrome untouched: no data-glass appears on the Rail, titlebar, Panels, or the in-timeline sticky session-title header.

                      Testing Decisions

                      • Extends slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60 test surface — component→tier contrast mapping (CREATE, alongside slice 2's glass-token contrast test): a table test over {archetype → (tier, text-role)} for the seven archetypes, asserting tierContrast(theme, tier, colorForRole(role)) ≥ floor(+margin) in both shipped chat themes using slice 2's exported contrast/tierContrast and the theme's real text tokens: body→standard ≥4.5:1+margin, code/diff→dense ≥4.5:1, marks→dense ≥3:1. The table also asserts no muted-role text maps to the standard tier — it rides dense / a dense-backed inline zone (guards the exact grey-on-glass failure the earlier build hit).
                      • Tier-assignment DOM test (CREATE glass-float behavior test): render each archetype through the real message renderer / composer / tool / run-plot components and assert the correct data-glass value on the leaf card; assert the wrapping session-turn/column frame has no data-glass and a transparent resolved background (the "gaps stay live" + "nothing bare/opaque" criteria).
                      • No-literal source guard (CREATE, static scan): scan the seven restyled cards' style-rules (not whole files) for backdrop-filter, blur radii, and rgba tint literals; assert zero outside the Glass token CSS; explicitly exclude the in-timeline sticky session-title header's pre-existing chrome blur (chrome that stays); and assert the user bubble no longer sets an opaque --surface-base fill.
                      • Reuse existing component tests: extend the tool-card, run-card, and run-plot render tests to cover the new data-glass="dense" attribute rather than adding parallel harnesses; do not re-test the token derivation (that is slice 2's).
                      • All tests are external-behavior (rendered attribute + computed style + slice-2 validator math) — none reach into engine internals or attempt live canvas/backdrop-filter pixel compositing (jsdom cannot composite backdrop-filter; the reference-frame floor stands in for "legible over the running brain").

                      Key Decisions

                      • Tier map (the contract): standard = {user bubble, assistant prose, composer}; dense = {code block, diff, run-plot, tool card}. Composer is standard (a control surface holding body text), per the ADR grouping — the old branch's separate chrome tier collapses into standard.
                      • data-glass attribute contract: values are standard | dense, defined and emitted by slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60; this slice only applies them and consumes the emitted CSS utility + validator. Applying an undefined tier value is a slice-2 change, never a local literal.
                      • Assistant prose gains a card: assistant text-parts are bare (no background) today; they get a standard card so prose is legible over the Brain.
                      • Nesting is conservative: a dense card nested in a standard card (code inside prose) keeps its dense tier; every tier's floor is derived over the bare worst-case Brain, and nesting only adds opacity, so contrast is guaranteed without per-nesting recomputation.
                      • Muted/secondary text: rides the dense tier — the prose card's meta (copy/timestamp) is the concrete case, wrapped in a dense-backed inline zone (slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's dense token, no new literal) so it never composites directly against the standard tint. This is the ADR's "locally-dimmed zone", realized without a third token.
                      • Motion lives in the gaps, not thinner cards: cards stay at slice 2's derived tint; the visible Brain comes from the transparent row gaps/gutters — do not dilute a card's tint to "let more Brain through."

                      Constraints & Invariants

                      • Do not mount the background, retire the inline brain strip, or touch the render loop — that is slice Mount the Brain chat-wide and absorb the inline brain strip #59; this slice only styles the floating cards.
                      • Do not define new glass tints, blur values, or geometry — consume slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's two tokens verbatim (they already carry radius/border/shadow); a value the tokens lack is a slice-2 change, not a per-component literal. The dense-backed inline zone for muted text uses the existing dense token — not a new one.
                      • The standard tier's tint alpha is bounded below by its contrast floor; never override it lower locally.
                      • Row frames (session-turn), the centered column, and inter-card gutters must never receive a glass fill — that would tile and hide the Brain.
                      • Rail, titlebar, Panels, and the in-timeline sticky session-title header stay as-is; no data-glass on them, and their existing chrome blur is left untouched.
                      • Amicode design-system law holds for the card chrome: geometry from the tier token, single-yellow accent — yellow is never a card fill; #fff676 stays the Brain's live-thought color.
                      Prior Art / Patterns Real seams to restyle (current branch): the message renderer `packages/ui/src/components/message-part.tsx` + `message-part.css` — user bubble `[data-slot="user-message-text"]` (currently `background: var(--surface-base)`), assistant `[data-component="text-part"]` / `[data-slot="text-part-body"]`, markdown code `[data-component="markdown-code"]` (`packages/ui/src/components/markdown.tsx` + `markdown.css`); the timeline `packages/app/src/pages/session/message-timeline.tsx` — `TimelineRowFrame` → `[data-component="session-turn"]`, diff group `session-turn-diffs-group` / `session-turn-diff-view` (note: this file also holds the sticky session-title header with a pre-existing `backdrop-blur` — that is out-of-scope chrome; do not touch it); the composer `packages/app/src/pages/session/composer/session-composer-region.tsx` — `[data-component="session-prompt-dock"]`; the tool card `packages/ui/src/components/basic-tool.tsx` — `[data-component="tool-trigger"]`; the run-plot `packages/ui/src/amicode/run-window.tsx` — `[data-component="amicode-run-window"]`; diffs `packages/ui/src/components/diff-changes.tsx`. Old-branch raw material to reuse (design-neutral, slice #60 lands it, this slice consumes it): `opencode-brain-atmosphere-wt/packages/ui/src/amicode/glass.css` — the `[data-glass=...]` tier utilities, the `@supports not (backdrop-filter)` opaque fallback so text never lands on bare canvas, and `glass-tokens.ts`'s `contrast`/`tierContrast` validator functions; note its three tiers (airy/dense/chrome) collapse to slice 2's two (standard/dense) with the composer moving from `chrome` to `standard`. The mounted background is slice #59's `BrainAtmosphere` (old `brain/brain-atmosphere.tsx`), which paints on a transparent, `aria-hidden`, pointer-events-none ground beneath the cards.

                      Source

                      Activity

                      Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

                      Metadata

                      Metadata

                      Assignees

                      No one assigned

                        Labels

                        afkImplement + merge unattended

                        Type

                        No type

                        Projects

                        No projects

                          Milestone

                          No milestone

                          Relationships

                          None yet

                          Development

                          No branches or pull requests

                          Issue actions

                          , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
                          Skip to content

                          Float chat components on the two Glass tiers (standard prose/bubbles/composer, dense code/diffs/plots/tools) #61

                          Description

                          @kateebonner

                          Important

                          Problem

                          With the Brain mounted as the Chat's full-bleed background (slice #59) and the AA-floored Glass tokens available (slice #60), the chat's content cards are still styled for a solid chat surface: user bubbles carry an opaque --surface-base fill and assistant prose has no background at all — over the living Brain they would tile the motion away or become illegible. See #56 for the "everything floats, legibly" why.

                          Approach

                          Apply slice #60's two Glass tiers to the real content cards: the standard tier on user bubbles, assistant prose, and the composer; the dense tier on code blocks, diffs, run-plots, and tool cards. Bare assistant prose gains its own standard card; muted/secondary text is routed off the ultra-transparent standard tier onto the dense tier (the prose meta on a dense-backed inline zone — slice #60's dense token, no new literal); timeline row frames and gutters stay transparent so the Brain shows in the gaps. Then re-validate that each real archetype's rendered text clears its tier's contrast floor over the running-brain reference frame in both chat themes — extending slice #60's synthetic contrast test onto a component→tier mapping.

                          Scope

                          In: the seven content archetypes get a data-glass tier (standard: user bubble, assistant prose, composer; dense: code block, diff, run-plot, tool card); the opaque bubble fill is replaced by the glass tint; assistant prose gets a standard card; muted text rides the dense tier (a dense-backed inline zone for the prose meta); row frames/gutters stay transparent; a component→tier contrast mapping is validated over the reference frame in both themes.
                          Out: mounting the Brain / retiring the inline strip / one render loop (slice #59 owns the room; this slice only styles what floats on it); deriving tints/blur + the synthetic reference-frame validator (slice #60 owns the tokens + contrast helpers; this slice consumes them); motion / at-rest / data-true heartbeat (slice 4); the laptop-webview perf gate + motion-ease fallback (slice 5); Rail, titlebar, Panels, and the in-timeline sticky session-title header (nav/timeline chrome stays solid — not floating content); new geometry/accent tokens (the tier token already carries radius/border/shadow — no per-component literals).


                          Acceptance Criteria

                          • Tier assignment: the user-message bubble, the assistant prose text-part, and the composer each carry data-glass="standard"; a markdown code block, a diff view, a run-plot/run-window, and a tool card each carry data-glass="dense". No third tier value and no data-glass on any non-content element are present.
                          • Nothing bare, nothing opaque: every persistent readable region above (bubble, prose, code, diff, plot, tool, composer) resolves a Glass tint whose alpha is < 1 (translucent) — none is transparent (would be illegible over the Brain) and none is opaque (would tile the Brain away).
                          • Gaps stay live: the timeline row frame (session-turn) and the centered column/gutter wrappers carry no glass background and resolve a transparent background — only leaf content cards float, so the Brain is visible between top-level cards.
                          • Contrast over the reference frame (both chat themes): measured with slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's validator against its worst-case running-brain reference frame — body text on a standard card clears ≥4.5:1 with the same safety margin; code/diff text on a dense card clears ≥4.5:1; graphical marks (syntax colors, diff fills, plot lines) on a dense card clear ≥3:1. The mapping is asserted per archetype, not eyeballed.
                          • No muted text on standard: every muted/secondary-role text element (e.g. the copy/timestamp meta inside a prose card) sits in a dense-tier element or a dense-backed inline zone (slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's dense token — never a new tint/literal); the mapping table rejects any (muted-role → standard) pairing.
                          • No ad-hoc blur/tint literal: a source scan of the seven restyled cards' style-rules finds zero backdrop-filter/blur-radius/rgba-tint literals outside slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's Glass token CSS — the scan is scoped to those card rules and explicitly excludes the in-timeline sticky session-title header's pre-existing chrome blur (out-of-scope chrome that stays), so styling the diff seam that lives alongside it does not require touching it; and the previous opaque --surface-base bubble fill is gone (replaced by the standard tint).
                          • Chrome untouched: no data-glass appears on the Rail, titlebar, Panels, or the in-timeline sticky session-title header.

                          Testing Decisions

                          • Extends slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60 test surface — component→tier contrast mapping (CREATE, alongside slice 2's glass-token contrast test): a table test over {archetype → (tier, text-role)} for the seven archetypes, asserting tierContrast(theme, tier, colorForRole(role)) ≥ floor(+margin) in both shipped chat themes using slice 2's exported contrast/tierContrast and the theme's real text tokens: body→standard ≥4.5:1+margin, code/diff→dense ≥4.5:1, marks→dense ≥3:1. The table also asserts no muted-role text maps to the standard tier — it rides dense / a dense-backed inline zone (guards the exact grey-on-glass failure the earlier build hit).
                          • Tier-assignment DOM test (CREATE glass-float behavior test): render each archetype through the real message renderer / composer / tool / run-plot components and assert the correct data-glass value on the leaf card; assert the wrapping session-turn/column frame has no data-glass and a transparent resolved background (the "gaps stay live" + "nothing bare/opaque" criteria).
                          • No-literal source guard (CREATE, static scan): scan the seven restyled cards' style-rules (not whole files) for backdrop-filter, blur radii, and rgba tint literals; assert zero outside the Glass token CSS; explicitly exclude the in-timeline sticky session-title header's pre-existing chrome blur (chrome that stays); and assert the user bubble no longer sets an opaque --surface-base fill.
                          • Reuse existing component tests: extend the tool-card, run-card, and run-plot render tests to cover the new data-glass="dense" attribute rather than adding parallel harnesses; do not re-test the token derivation (that is slice 2's).
                          • All tests are external-behavior (rendered attribute + computed style + slice-2 validator math) — none reach into engine internals or attempt live canvas/backdrop-filter pixel compositing (jsdom cannot composite backdrop-filter; the reference-frame floor stands in for "legible over the running brain").

                          Key Decisions

                          • Tier map (the contract): standard = {user bubble, assistant prose, composer}; dense = {code block, diff, run-plot, tool card}. Composer is standard (a control surface holding body text), per the ADR grouping — the old branch's separate chrome tier collapses into standard.
                          • data-glass attribute contract: values are standard | dense, defined and emitted by slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60; this slice only applies them and consumes the emitted CSS utility + validator. Applying an undefined tier value is a slice-2 change, never a local literal.
                          • Assistant prose gains a card: assistant text-parts are bare (no background) today; they get a standard card so prose is legible over the Brain.
                          • Nesting is conservative: a dense card nested in a standard card (code inside prose) keeps its dense tier; every tier's floor is derived over the bare worst-case Brain, and nesting only adds opacity, so contrast is guaranteed without per-nesting recomputation.
                          • Muted/secondary text: rides the dense tier — the prose card's meta (copy/timestamp) is the concrete case, wrapped in a dense-backed inline zone (slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's dense token, no new literal) so it never composites directly against the standard tint. This is the ADR's "locally-dimmed zone", realized without a third token.
                          • Motion lives in the gaps, not thinner cards: cards stay at slice 2's derived tint; the visible Brain comes from the transparent row gaps/gutters — do not dilute a card's tint to "let more Brain through."

                          Constraints & Invariants

                          • Do not mount the background, retire the inline brain strip, or touch the render loop — that is slice Mount the Brain chat-wide and absorb the inline brain strip #59; this slice only styles the floating cards.
                          • Do not define new glass tints, blur values, or geometry — consume slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's two tokens verbatim (they already carry radius/border/shadow); a value the tokens lack is a slice-2 change, not a per-component literal. The dense-backed inline zone for muted text uses the existing dense token — not a new one.
                          • The standard tier's tint alpha is bounded below by its contrast floor; never override it lower locally.
                          • Row frames (session-turn), the centered column, and inter-card gutters must never receive a glass fill — that would tile and hide the Brain.
                          • Rail, titlebar, Panels, and the in-timeline sticky session-title header stay as-is; no data-glass on them, and their existing chrome blur is left untouched.
                          • Amicode design-system law holds for the card chrome: geometry from the tier token, single-yellow accent — yellow is never a card fill; #fff676 stays the Brain's live-thought color.
                          Prior Art / Patterns Real seams to restyle (current branch): the message renderer `packages/ui/src/components/message-part.tsx` + `message-part.css` — user bubble `[data-slot="user-message-text"]` (currently `background: var(--surface-base)`), assistant `[data-component="text-part"]` / `[data-slot="text-part-body"]`, markdown code `[data-component="markdown-code"]` (`packages/ui/src/components/markdown.tsx` + `markdown.css`); the timeline `packages/app/src/pages/session/message-timeline.tsx` — `TimelineRowFrame` → `[data-component="session-turn"]`, diff group `session-turn-diffs-group` / `session-turn-diff-view` (note: this file also holds the sticky session-title header with a pre-existing `backdrop-blur` — that is out-of-scope chrome; do not touch it); the composer `packages/app/src/pages/session/composer/session-composer-region.tsx` — `[data-component="session-prompt-dock"]`; the tool card `packages/ui/src/components/basic-tool.tsx` — `[data-component="tool-trigger"]`; the run-plot `packages/ui/src/amicode/run-window.tsx` — `[data-component="amicode-run-window"]`; diffs `packages/ui/src/components/diff-changes.tsx`. Old-branch raw material to reuse (design-neutral, slice #60 lands it, this slice consumes it): `opencode-brain-atmosphere-wt/packages/ui/src/amicode/glass.css` — the `[data-glass=...]` tier utilities, the `@supports not (backdrop-filter)` opaque fallback so text never lands on bare canvas, and `glass-tokens.ts`'s `contrast`/`tierContrast` validator functions; note its three tiers (airy/dense/chrome) collapse to slice 2's two (standard/dense) with the composer moving from `chrome` to `standard`. The mounted background is slice #59's `BrainAtmosphere` (old `brain/brain-atmosphere.tsx`), which paints on a transparent, `aria-hidden`, pointer-events-none ground beneath the cards.

                          Source

                          Activity

                          Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

                          Metadata

                          Metadata

                          Assignees

                          No one assigned

                            Labels

                            afkImplement + merge unattended

                            Type

                            No type

                            Projects

                            No projects

                              Milestone

                              No milestone

                              Relationships

                              None yet

                              Development

                              No branches or pull requests

                              Issue actions

                              , 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
                              Skip to content

                              Float chat components on the two Glass tiers (standard prose/bubbles/composer, dense code/diffs/plots/tools) #61

                              Description

                              @kateebonner

                              Important

                              Problem

                              With the Brain mounted as the Chat's full-bleed background (slice #59) and the AA-floored Glass tokens available (slice #60), the chat's content cards are still styled for a solid chat surface: user bubbles carry an opaque --surface-base fill and assistant prose has no background at all — over the living Brain they would tile the motion away or become illegible. See #56 for the "everything floats, legibly" why.

                              Approach

                              Apply slice #60's two Glass tiers to the real content cards: the standard tier on user bubbles, assistant prose, and the composer; the dense tier on code blocks, diffs, run-plots, and tool cards. Bare assistant prose gains its own standard card; muted/secondary text is routed off the ultra-transparent standard tier onto the dense tier (the prose meta on a dense-backed inline zone — slice #60's dense token, no new literal); timeline row frames and gutters stay transparent so the Brain shows in the gaps. Then re-validate that each real archetype's rendered text clears its tier's contrast floor over the running-brain reference frame in both chat themes — extending slice #60's synthetic contrast test onto a component→tier mapping.

                              Scope

                              In: the seven content archetypes get a data-glass tier (standard: user bubble, assistant prose, composer; dense: code block, diff, run-plot, tool card); the opaque bubble fill is replaced by the glass tint; assistant prose gets a standard card; muted text rides the dense tier (a dense-backed inline zone for the prose meta); row frames/gutters stay transparent; a component→tier contrast mapping is validated over the reference frame in both themes.
                              Out: mounting the Brain / retiring the inline strip / one render loop (slice #59 owns the room; this slice only styles what floats on it); deriving tints/blur + the synthetic reference-frame validator (slice #60 owns the tokens + contrast helpers; this slice consumes them); motion / at-rest / data-true heartbeat (slice 4); the laptop-webview perf gate + motion-ease fallback (slice 5); Rail, titlebar, Panels, and the in-timeline sticky session-title header (nav/timeline chrome stays solid — not floating content); new geometry/accent tokens (the tier token already carries radius/border/shadow — no per-component literals).


                              Acceptance Criteria

                              • Tier assignment: the user-message bubble, the assistant prose text-part, and the composer each carry data-glass="standard"; a markdown code block, a diff view, a run-plot/run-window, and a tool card each carry data-glass="dense". No third tier value and no data-glass on any non-content element are present.
                              • Nothing bare, nothing opaque: every persistent readable region above (bubble, prose, code, diff, plot, tool, composer) resolves a Glass tint whose alpha is < 1 (translucent) — none is transparent (would be illegible over the Brain) and none is opaque (would tile the Brain away).
                              • Gaps stay live: the timeline row frame (session-turn) and the centered column/gutter wrappers carry no glass background and resolve a transparent background — only leaf content cards float, so the Brain is visible between top-level cards.
                              • Contrast over the reference frame (both chat themes): measured with slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's validator against its worst-case running-brain reference frame — body text on a standard card clears ≥4.5:1 with the same safety margin; code/diff text on a dense card clears ≥4.5:1; graphical marks (syntax colors, diff fills, plot lines) on a dense card clear ≥3:1. The mapping is asserted per archetype, not eyeballed.
                              • No muted text on standard: every muted/secondary-role text element (e.g. the copy/timestamp meta inside a prose card) sits in a dense-tier element or a dense-backed inline zone (slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's dense token — never a new tint/literal); the mapping table rejects any (muted-role → standard) pairing.
                              • No ad-hoc blur/tint literal: a source scan of the seven restyled cards' style-rules finds zero backdrop-filter/blur-radius/rgba-tint literals outside slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's Glass token CSS — the scan is scoped to those card rules and explicitly excludes the in-timeline sticky session-title header's pre-existing chrome blur (out-of-scope chrome that stays), so styling the diff seam that lives alongside it does not require touching it; and the previous opaque --surface-base bubble fill is gone (replaced by the standard tint).
                              • Chrome untouched: no data-glass appears on the Rail, titlebar, Panels, or the in-timeline sticky session-title header.

                              Testing Decisions

                              • Extends slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60 test surface — component→tier contrast mapping (CREATE, alongside slice 2's glass-token contrast test): a table test over {archetype → (tier, text-role)} for the seven archetypes, asserting tierContrast(theme, tier, colorForRole(role)) ≥ floor(+margin) in both shipped chat themes using slice 2's exported contrast/tierContrast and the theme's real text tokens: body→standard ≥4.5:1+margin, code/diff→dense ≥4.5:1, marks→dense ≥3:1. The table also asserts no muted-role text maps to the standard tier — it rides dense / a dense-backed inline zone (guards the exact grey-on-glass failure the earlier build hit).
                              • Tier-assignment DOM test (CREATE glass-float behavior test): render each archetype through the real message renderer / composer / tool / run-plot components and assert the correct data-glass value on the leaf card; assert the wrapping session-turn/column frame has no data-glass and a transparent resolved background (the "gaps stay live" + "nothing bare/opaque" criteria).
                              • No-literal source guard (CREATE, static scan): scan the seven restyled cards' style-rules (not whole files) for backdrop-filter, blur radii, and rgba tint literals; assert zero outside the Glass token CSS; explicitly exclude the in-timeline sticky session-title header's pre-existing chrome blur (chrome that stays); and assert the user bubble no longer sets an opaque --surface-base fill.
                              • Reuse existing component tests: extend the tool-card, run-card, and run-plot render tests to cover the new data-glass="dense" attribute rather than adding parallel harnesses; do not re-test the token derivation (that is slice 2's).
                              • All tests are external-behavior (rendered attribute + computed style + slice-2 validator math) — none reach into engine internals or attempt live canvas/backdrop-filter pixel compositing (jsdom cannot composite backdrop-filter; the reference-frame floor stands in for "legible over the running brain").

                              Key Decisions

                              • Tier map (the contract): standard = {user bubble, assistant prose, composer}; dense = {code block, diff, run-plot, tool card}. Composer is standard (a control surface holding body text), per the ADR grouping — the old branch's separate chrome tier collapses into standard.
                              • data-glass attribute contract: values are standard | dense, defined and emitted by slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60; this slice only applies them and consumes the emitted CSS utility + validator. Applying an undefined tier value is a slice-2 change, never a local literal.
                              • Assistant prose gains a card: assistant text-parts are bare (no background) today; they get a standard card so prose is legible over the Brain.
                              • Nesting is conservative: a dense card nested in a standard card (code inside prose) keeps its dense tier; every tier's floor is derived over the bare worst-case Brain, and nesting only adds opacity, so contrast is guaranteed without per-nesting recomputation.
                              • Muted/secondary text: rides the dense tier — the prose card's meta (copy/timestamp) is the concrete case, wrapped in a dense-backed inline zone (slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's dense token, no new literal) so it never composites directly against the standard tint. This is the ADR's "locally-dimmed zone", realized without a third token.
                              • Motion lives in the gaps, not thinner cards: cards stay at slice 2's derived tint; the visible Brain comes from the transparent row gaps/gutters — do not dilute a card's tint to "let more Brain through."

                              Constraints & Invariants

                              • Do not mount the background, retire the inline brain strip, or touch the render loop — that is slice Mount the Brain chat-wide and absorb the inline brain strip #59; this slice only styles the floating cards.
                              • Do not define new glass tints, blur values, or geometry — consume slice Derive two AA-floored, chat-theme-keyed Glass tint tiers with a contrast test #60's two tokens verbatim (they already carry radius/border/shadow); a value the tokens lack is a slice-2 change, not a per-component literal. The dense-backed inline zone for muted text uses the existing dense token — not a new one.
                              • The standard tier's tint alpha is bounded below by its contrast floor; never override it lower locally.
                              • Row frames (session-turn), the centered column, and inter-card gutters must never receive a glass fill — that would tile and hide the Brain.
                              • Rail, titlebar, Panels, and the in-timeline sticky session-title header stay as-is; no data-glass on them, and their existing chrome blur is left untouched.
                              • Amicode design-system law holds for the card chrome: geometry from the tier token, single-yellow accent — yellow is never a card fill; #fff676 stays the Brain's live-thought color.
                              Prior Art / Patterns Real seams to restyle (current branch): the message renderer `packages/ui/src/components/message-part.tsx` + `message-part.css` — user bubble `[data-slot="user-message-text"]` (currently `background: var(--surface-base)`), assistant `[data-component="text-part"]` / `[data-slot="text-part-body"]`, markdown code `[data-component="markdown-code"]` (`packages/ui/src/components/markdown.tsx` + `markdown.css`); the timeline `packages/app/src/pages/session/message-timeline.tsx` — `TimelineRowFrame` → `[data-component="session-turn"]`, diff group `session-turn-diffs-group` / `session-turn-diff-view` (note: this file also holds the sticky session-title header with a pre-existing `backdrop-blur` — that is out-of-scope chrome; do not touch it); the composer `packages/app/src/pages/session/composer/session-composer-region.tsx` — `[data-component="session-prompt-dock"]`; the tool card `packages/ui/src/components/basic-tool.tsx` — `[data-component="tool-trigger"]`; the run-plot `packages/ui/src/amicode/run-window.tsx` — `[data-component="amicode-run-window"]`; diffs `packages/ui/src/components/diff-changes.tsx`. Old-branch raw material to reuse (design-neutral, slice #60 lands it, this slice consumes it): `opencode-brain-atmosphere-wt/packages/ui/src/amicode/glass.css` — the `[data-glass=...]` tier utilities, the `@supports not (backdrop-filter)` opaque fallback so text never lands on bare canvas, and `glass-tokens.ts`'s `contrast`/`tierContrast` validator functions; note its three tiers (airy/dense/chrome) collapse to slice 2's two (standard/dense) with the composer moving from `chrome` to `standard`. The mounted background is slice #59's `BrainAtmosphere` (old `brain/brain-atmosphere.tsx`), which paints on a transparent, `aria-hidden`, pointer-events-none ground beneath the cards.

                              Source

                              Activity

                              Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

                              Metadata

                              Metadata

                              Assignees

                              No one assigned

                                Labels

                                afkImplement + merge unattended

                                Type

                                No type

                                Projects

                                No projects

                                  Milestone

                                  No milestone

                                  Relationships

                                  None yet

                                  Development

                                  No branches or pull requests

                                  Issue actions