From e594e11baa5df9fe1f52e78907086e13dee0b6cd Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Mon, 20 Jul 2026 17:47:16 -0500 Subject: [PATCH] =?UTF-8?q?fix(ui-tui):=20session-panel=20fade=20anchors?= =?UTF-8?q?=20on=20muted,=20not=20the=20surface=20=E2=80=94=20readable=20o?= =?UTF-8?q?n=20every=20pole?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mix(text, surface) was invisible whenever text was already pale (the light-rendered default: cream blended toward white = nothing) and inherited wrong-polarity detection through the surface. mix(muted, text, .5) is pole-proof: muted is mid-luminance by construction, so the midpoint stays readable everywhere. Audited 9 skins x both poles: 2.0-2.9:1 on white, 5.6-9.3:1 on dark (worst case 1.92 for a light-authored skin on dark). --- ui-tui/src/components/branding.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ui-tui/src/components/branding.tsx b/ui-tui/src/components/branding.tsx index 513d5a57624..87006a5e0c9 100644 --- a/ui-tui/src/components/branding.tsx +++ b/ui-tui/src/components/branding.tsx @@ -233,10 +233,12 @@ export function SessionPanel({ info, maxWidth, sid, t }: SessionPanelProps) { const strip = (s: string) => (s.endsWith('_tools') ? s.slice(0, -6) : s) // Hierarchy: category labels lead in the theme's label tone; member lists - // recede in body-text faded toward the surface. Skin-relative on purpose — - // `muted` is the STRONG family tone on gold skins but the weak one on blue - // skins, so hardcoding it flips the hierarchy per skin (slate/poseidon bug). - const listFade = mix(t.color.text, t.color.completionBg, 0.5) + // recede in the midpoint of muted and text. Anchoring on MUTED (a + // mid-luminance family tone) keeps the fade readable on both poles even + // when polarity detection is wrong — blending toward the SURFACE instead + // made the fade invisible whenever text was already pale (light-rendered + // default: cream toward white = nothing). + const listFade = mix(t.color.muted, t.color.text, 0.5) // ── Local collapse state for each section ── const [toolsOpen, setToolsOpen] = useState(true)