diff --git a/packages/opencode/src/cli/cmd/tui/component/logo.tsx b/packages/opencode/src/cli/cmd/tui/component/logo.tsx
index d1be06a7f..6fd744794 100644
--- a/packages/opencode/src/cli/cmd/tui/component/logo.tsx
+++ b/packages/opencode/src/cli/cmd/tui/component/logo.tsx
@@ -1,24 +1,75 @@
-import { TextAttributes } from "@opentui/core"
-import { For } from "solid-js"
-import { useTheme } from "@tui/context/theme"
+import { TextAttributes, RGBA } from "@opentui/core"
+import { For, type JSX } from "solid-js"
+import { useTheme, tint } from "@tui/context/theme"
-const LOGO_LEFT = [` `, `█▀▀█ █▀▀█ █▀▀█ █▀▀▄`, `█░░█ █░░█ █▀▀▀ █░░█`, `▀▀▀▀ █▀▀▀ ▀▀▀▀ ▀ ▀`]
+// Shadow markers (rendered chars in parens):
+// _ = full shadow cell (space with bg=shadow)
+// ^ = letter top, shadow bottom (▀ with fg=letter, bg=shadow)
+// ~ = shadow top only (▀ with fg=shadow)
+const SHADOW_MARKER = /[_^~]/
-const LOGO_RIGHT = [` ▄ `, `█▀▀▀ █▀▀█ █▀▀█ █▀▀█`, `█░░░ █░░█ █░░█ █▀▀▀`, `▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀`]
+const LOGO_LEFT = [
+ ` `,
+ `█▀▀█ █▀▀█ █▀▀█ █▀▀▄`,
+ `█__█ █__█ █^^^ █__█`,
+ `▀▀▀▀ █▀▀▀ ▀▀▀▀ ▀~~▀`,
+]
+
+const LOGO_RIGHT = [
+ ` ▄ `,
+ `█▀▀▀ █▀▀█ █▀▀█ █▀▀█`,
+ `█___ █__█ █__█ █^^^`,
+ `▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀`,
+]
export function Logo() {
const { theme } = useTheme()
+
+ const renderLine = (line: string, fg: RGBA, bold: boolean): JSX.Element[] => {
+ const shadow = tint(theme.background, fg, 0.25)
+ const attrs = bold ? TextAttributes.BOLD : undefined
+ const elements: JSX.Element[] = []
+ let i = 0
+
+ while (i < line.length) {
+ const rest = line.slice(i)
+ const markerIndex = rest.search(SHADOW_MARKER)
+
+ if (markerIndex === -1) {
+ elements.push({rest})
+ break
+ }
+
+ if (markerIndex > 0) {
+ elements.push({rest.slice(0, markerIndex)})
+ }
+
+ const marker = rest[markerIndex]
+ switch (marker) {
+ case "_":
+ elements.push( )
+ break
+ case "^":
+ elements.push(▀)
+ break
+ case "~":
+ elements.push(▀)
+ break
+ }
+
+ i += markerIndex + 1
+ }
+
+ return elements
+ }
+
return (
{(line, index) => (
-
- {line}
-
-
- {LOGO_RIGHT[index()]}
-
+ {renderLine(line, theme.textMuted, false)}
+ {renderLine(LOGO_RIGHT[index()], theme.text, true)}
)}
diff --git a/packages/opencode/src/cli/cmd/tui/context/theme.tsx b/packages/opencode/src/cli/cmd/tui/context/theme.tsx
index 6489fc0e1..127be0dfc 100644
--- a/packages/opencode/src/cli/cmd/tui/context/theme.tsx
+++ b/packages/opencode/src/cli/cmd/tui/context/theme.tsx
@@ -417,6 +417,13 @@ async function getCustomThemes() {
return result
}
+export function tint(base: RGBA, overlay: RGBA, alpha: number): RGBA {
+ const r = base.r + (overlay.r - base.r) * alpha
+ const g = base.g + (overlay.g - base.g) * alpha
+ const b = base.b + (overlay.b - base.b) * alpha
+ return RGBA.fromInts(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255))
+}
+
function generateSystem(colors: TerminalColors, mode: "dark" | "light"): ThemeJson {
const bg = RGBA.fromHex(colors.defaultBackground ?? colors.palette[0]!)
const fg = RGBA.fromHex(colors.defaultForeground ?? colors.palette[7]!)
@@ -428,13 +435,6 @@ function generateSystem(colors: TerminalColors, mode: "dark" | "light"): ThemeJs
return ansiToRgba(i)
}
- const tint = (base: RGBA, overlay: RGBA, alpha: number) => {
- const r = base.r + (overlay.r - base.r) * alpha
- const g = base.g + (overlay.g - base.g) * alpha
- const b = base.b + (overlay.b - base.b) * alpha
- return RGBA.fromInts(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255))
- }
-
// Generate gray scale based on terminal background
const grays = generateGrayScale(bg, isDark)
const textMuted = generateMutedTextColor(bg, isDark)