package app import "github.com/charmbracelet/lipgloss" // Palette is the "Soft" chrome from docs/visual/ref with the blue accent: // rounded borders, opaque dark panels, generous spacing. type Palette struct { Bg lipgloss.Color // panel/background fill BgDeep lipgloss.Color // outermost backdrop (slightly darker) BgPanel lipgloss.Color // inside-panel fill Sel lipgloss.Color // selection row background Border lipgloss.Color // idle panel border BorderHi lipgloss.Color // active panel border Fg lipgloss.Color // primary text FgStrong lipgloss.Color // headings / emphasis Dim lipgloss.Color // labels, secondary text Faint lipgloss.Color // tertiary, hints Accent lipgloss.Color // blue accent Accent2 lipgloss.Color // secondary accent OK lipgloss.Color Warn lipgloss.Color Bad lipgloss.Color CatLifecycle lipgloss.Color CatContext lipgloss.Color CatInference lipgloss.Color CatTool lipgloss.Color CatDomain lipgloss.Color CatApproval lipgloss.Color } // SoftBlue mirrors the reference Soft theme (#14161a bg, #ced3da fg) with the // blue accent the user chose. var SoftBlue = Palette{ BgDeep: lipgloss.Color("#101216"), Bg: lipgloss.Color("#14161a"), BgPanel: lipgloss.Color("#171a1f"), Sel: lipgloss.Color("#1b2733"), Border: lipgloss.Color("#262b33"), BorderHi: lipgloss.Color("#4a9eff"), Fg: lipgloss.Color("#ced3da"), FgStrong: lipgloss.Color("#e8edf2"), Dim: lipgloss.Color("#7c8794"), Faint: lipgloss.Color("#525c68"), Accent: lipgloss.Color("#4a9eff"), Accent2: lipgloss.Color("#56c8d8"), OK: lipgloss.Color("#7fd88f"), Warn: lipgloss.Color("#e8c06a"), Bad: lipgloss.Color("#e87f7f"), CatLifecycle: lipgloss.Color("#c98fd9"), CatContext: lipgloss.Color("#b9c0c9"), CatInference: lipgloss.Color("#56c8d8"), CatTool: lipgloss.Color("#8fd96a"), CatDomain: lipgloss.Color("#e8b765"), CatApproval: lipgloss.Color("#e8c06a"), } // Theme holds prebuilt lipgloss styles derived from a Palette. Every style sets // a Background so the panels are fully opaque (no terminal wallpaper bleed). type Theme struct { P Palette Screen lipgloss.Style // full backdrop fill Panel lipgloss.Style // idle rounded panel PanelHi lipgloss.Style // active rounded panel PanelTitle lipgloss.Style // uppercase dim header label TitleHi lipgloss.Style // active header label Text lipgloss.Style Strong lipgloss.Style Dim lipgloss.Style Faint lipgloss.Style Accent lipgloss.Style SelRow lipgloss.Style Status lipgloss.Style // top bar Footer lipgloss.Style // bottom hints Input lipgloss.Style // input bar panel Overlay lipgloss.Style // modal box Scrim lipgloss.Style // dim backdrop behind modals } // NewTheme builds the style set for a palette. func NewTheme(p Palette) Theme { base := lipgloss.NewStyle().Background(p.Bg).Foreground(p.Fg) roundBase := func(border lipgloss.Color) lipgloss.Style { return lipgloss.NewStyle(). Border(lipgloss.RoundedBorder()). BorderForeground(border). BorderBackground(p.Bg). Background(p.Bg). Foreground(p.Fg). Padding(0, 1) } return Theme{ P: p, Screen: lipgloss.NewStyle().Background(p.BgDeep).Foreground(p.Fg), Panel: roundBase(p.Border), PanelHi: roundBase(p.BorderHi), PanelTitle: lipgloss.NewStyle().Background(p.Bg).Foreground(p.Dim).Bold(true), TitleHi: lipgloss.NewStyle().Background(p.Bg).Foreground(p.Accent).Bold(true), Text: base, Strong: lipgloss.NewStyle().Background(p.Bg).Foreground(p.FgStrong).Bold(true), Dim: lipgloss.NewStyle().Background(p.Bg).Foreground(p.Dim), Faint: lipgloss.NewStyle().Background(p.Bg).Foreground(p.Faint), Accent: lipgloss.NewStyle().Background(p.Bg).Foreground(p.Accent).Bold(true), SelRow: lipgloss.NewStyle().Background(p.Sel).Foreground(p.FgStrong), Status: lipgloss.NewStyle().Background(p.BgPanel).Foreground(p.Dim), Footer: lipgloss.NewStyle().Background(p.BgDeep).Foreground(p.Faint), Input: roundBase(p.BorderHi), Overlay: lipgloss.NewStyle(). Border(lipgloss.RoundedBorder()). BorderForeground(p.Accent). BorderBackground(p.BgPanel). Background(p.BgPanel). Foreground(p.Fg). Padding(1, 2), Scrim: lipgloss.NewStyle().Background(p.BgDeep).Foreground(p.Faint), } } // categoryColor maps an event category label to its accent color. func (t Theme) categoryColor(cat string) lipgloss.Color { switch cat { case "Lifecycle": return t.P.CatLifecycle case "Context": return t.P.CatContext case "Inference": return t.P.CatInference case "Tool": return t.P.CatTool case "Domain": return t.P.CatDomain case "Approval": return t.P.CatApproval default: return t.P.Dim } }