styles.go

   1package styles
   2
   3import (
   4	"image/color"
   5	"strings"
   6
   7	"charm.land/bubbles/v2/filepicker"
   8	"charm.land/bubbles/v2/help"
   9	"charm.land/bubbles/v2/textarea"
  10	"charm.land/bubbles/v2/textinput"
  11	tea "charm.land/bubbletea/v2"
  12	"charm.land/glamour/v2/ansi"
  13	"charm.land/lipgloss/v2"
  14	"github.com/alecthomas/chroma/v2"
  15	"github.com/charmbracelet/crush/internal/ui/diffview"
  16	"github.com/charmbracelet/x/exp/charmtone"
  17)
  18
  19const (
  20	CheckIcon   string = "βœ“"
  21	SpinnerIcon string = "β‹―"
  22	LoadingIcon string = "⟳"
  23	ModelIcon   string = "β—‡"
  24
  25	ArrowRightIcon string = "β†’"
  26
  27	ToolPending string = "●"
  28	ToolSuccess string = "βœ“"
  29	ToolError   string = "Γ—"
  30
  31	RadioOn  string = "β—‰"
  32	RadioOff string = "β—‹"
  33
  34	BorderThin  string = "β”‚"
  35	BorderThick string = "β–Œ"
  36
  37	SectionSeparator string = "─"
  38
  39	TodoCompletedIcon  string = "βœ“"
  40	TodoPendingIcon    string = "β€’"
  41	TodoInProgressIcon string = "β†’"
  42
  43	ImageIcon string = "β– "
  44	TextIcon  string = "≑"
  45
  46	ScrollbarThumb string = "┃"
  47	ScrollbarTrack string = "β”‚"
  48
  49	LSPErrorIcon   string = "E"
  50	LSPWarningIcon string = "W"
  51	LSPInfoIcon    string = "I"
  52	LSPHintIcon    string = "H"
  53)
  54
  55const (
  56	defaultMargin     = 2
  57	defaultListIndent = 2
  58)
  59
  60type Styles struct {
  61	WindowTooSmall lipgloss.Style
  62
  63	// Reusable text styles
  64	Base      lipgloss.Style
  65	Muted     lipgloss.Style
  66	HalfMuted lipgloss.Style
  67	Subtle    lipgloss.Style
  68
  69	// Tags
  70	TagBase  lipgloss.Style
  71	TagError lipgloss.Style
  72	TagInfo  lipgloss.Style
  73
  74	// Header
  75	Header struct {
  76		Charm        lipgloss.Style // Style for "Charmβ„’" label
  77		Diagonals    lipgloss.Style // Style for diagonal separators (β•±)
  78		Percentage   lipgloss.Style // Style for context percentage
  79		Keystroke    lipgloss.Style // Style for keystroke hints (e.g., "ctrl+d")
  80		KeystrokeTip lipgloss.Style // Style for keystroke action text (e.g., "open", "close")
  81		WorkingDir   lipgloss.Style // Style for current working directory
  82		Separator    lipgloss.Style // Style for separator dots (β€’)
  83	}
  84
  85	CompactDetails struct {
  86		View    lipgloss.Style
  87		Version lipgloss.Style
  88		Title   lipgloss.Style
  89	}
  90
  91	// Panels
  92	PanelMuted lipgloss.Style
  93	PanelBase  lipgloss.Style
  94
  95	// Line numbers for code blocks
  96	LineNumber lipgloss.Style
  97
  98	// Message borders
  99	FocusedMessageBorder lipgloss.Border
 100
 101	// Tool calls
 102	ToolCallPending   lipgloss.Style
 103	ToolCallError     lipgloss.Style
 104	ToolCallSuccess   lipgloss.Style
 105	ToolCallCancelled lipgloss.Style
 106	EarlyStateMessage lipgloss.Style
 107
 108	// Text selection
 109	TextSelection lipgloss.Style
 110
 111	// LSP and MCP status indicators
 112	ResourceGroupTitle     lipgloss.Style
 113	ResourceOfflineIcon    lipgloss.Style
 114	ResourceBusyIcon       lipgloss.Style
 115	ResourceErrorIcon      lipgloss.Style
 116	ResourceOnlineIcon     lipgloss.Style
 117	ResourceName           lipgloss.Style
 118	ResourceStatus         lipgloss.Style
 119	ResourceAdditionalText lipgloss.Style
 120
 121	// Markdown & Chroma
 122	Markdown      ansi.StyleConfig
 123	PlainMarkdown ansi.StyleConfig
 124
 125	// Inputs
 126	TextInput textinput.Styles
 127	TextArea  textarea.Styles
 128
 129	// Help
 130	Help help.Styles
 131
 132	// Diff
 133	Diff diffview.Style
 134
 135	// FilePicker
 136	FilePicker filepicker.Styles
 137
 138	// Buttons
 139	ButtonFocus lipgloss.Style
 140	ButtonBlur  lipgloss.Style
 141
 142	// Borders
 143	BorderFocus lipgloss.Style
 144	BorderBlur  lipgloss.Style
 145
 146	// Editor
 147	EditorPromptNormalFocused   lipgloss.Style
 148	EditorPromptNormalBlurred   lipgloss.Style
 149	EditorPromptYoloIconFocused lipgloss.Style
 150	EditorPromptYoloIconBlurred lipgloss.Style
 151	EditorPromptYoloDotsFocused lipgloss.Style
 152	EditorPromptYoloDotsBlurred lipgloss.Style
 153
 154	// Radio
 155	RadioOn  lipgloss.Style
 156	RadioOff lipgloss.Style
 157
 158	// Background
 159	Background color.Color
 160
 161	// Logo
 162	LogoFieldColor   color.Color
 163	LogoTitleColorA  color.Color
 164	LogoTitleColorB  color.Color
 165	LogoCharmColor   color.Color
 166	LogoVersionColor color.Color
 167
 168	// Colors - semantic colors for tool rendering.
 169	Primary       color.Color
 170	Secondary     color.Color
 171	Tertiary      color.Color
 172	BgBase        color.Color
 173	BgBaseLighter color.Color
 174	BgSubtle      color.Color
 175	BgOverlay     color.Color
 176	FgBase        color.Color
 177	FgMuted       color.Color
 178	FgHalfMuted   color.Color
 179	FgSubtle      color.Color
 180	Border        color.Color
 181	BorderColor   color.Color // Border focus color
 182	Error         color.Color
 183	Warning       color.Color
 184	Info          color.Color
 185	White         color.Color
 186	BlueLight     color.Color
 187	Blue          color.Color
 188	BlueDark      color.Color
 189	GreenLight    color.Color
 190	Green         color.Color
 191	GreenDark     color.Color
 192	Red           color.Color
 193	RedDark       color.Color
 194	Yellow        color.Color
 195
 196	// Section Title
 197	Section struct {
 198		Title lipgloss.Style
 199		Line  lipgloss.Style
 200	}
 201
 202	// Initialize
 203	Initialize struct {
 204		Header  lipgloss.Style
 205		Content lipgloss.Style
 206		Accent  lipgloss.Style
 207	}
 208
 209	// LSP
 210	LSP struct {
 211		ErrorDiagnostic   lipgloss.Style
 212		WarningDiagnostic lipgloss.Style
 213		HintDiagnostic    lipgloss.Style
 214		InfoDiagnostic    lipgloss.Style
 215	}
 216
 217	// Files
 218	Files struct {
 219		Path      lipgloss.Style
 220		Additions lipgloss.Style
 221		Deletions lipgloss.Style
 222	}
 223
 224	// Chat
 225	Chat struct {
 226		// Message item styles
 227		Message struct {
 228			UserBlurred      lipgloss.Style
 229			UserFocused      lipgloss.Style
 230			AssistantBlurred lipgloss.Style
 231			AssistantFocused lipgloss.Style
 232			NoContent        lipgloss.Style
 233			Thinking         lipgloss.Style
 234			ErrorTag         lipgloss.Style
 235			ErrorTitle       lipgloss.Style
 236			ErrorDetails     lipgloss.Style
 237			ToolCallFocused  lipgloss.Style
 238			ToolCallCompact  lipgloss.Style
 239			ToolCallBlurred  lipgloss.Style
 240			SectionHeader    lipgloss.Style
 241
 242			// Thinking section styles
 243			ThinkingBox            lipgloss.Style // Background for thinking content
 244			ThinkingTruncationHint lipgloss.Style // "… (N lines hidden)" hint
 245			ThinkingFooterTitle    lipgloss.Style // "Thought for" text
 246			ThinkingFooterDuration lipgloss.Style // Duration value
 247			AssistantInfoIcon      lipgloss.Style
 248			AssistantInfoModel     lipgloss.Style
 249			AssistantInfoProvider  lipgloss.Style
 250			AssistantInfoDuration  lipgloss.Style
 251		}
 252	}
 253
 254	// Tool - styles for tool call rendering
 255	Tool struct {
 256		// Icon styles with tool status
 257		IconPending   lipgloss.Style
 258		IconSuccess   lipgloss.Style
 259		IconError     lipgloss.Style
 260		IconCancelled lipgloss.Style
 261
 262		// Tool name styles
 263		NameNormal lipgloss.Style // Top-level tool name
 264		NameNested lipgloss.Style // Nested child tool name (inside Agent/Agentic Fetch)
 265
 266		// Parameter list styles
 267		ParamMain lipgloss.Style
 268		ParamKey  lipgloss.Style
 269
 270		// Content rendering styles
 271		ContentLine           lipgloss.Style // Individual content line with background and width
 272		ContentTruncation     lipgloss.Style // Truncation message "… (N lines)"
 273		ContentCodeLine       lipgloss.Style // Code line with background and width
 274		ContentCodeTruncation lipgloss.Style // Code truncation message with bgBase
 275		ContentCodeBg         color.Color    // Background color for syntax highlighting
 276		Body                  lipgloss.Style // Body content padding (PaddingLeft(2))
 277
 278		// Deprecated - kept for backward compatibility
 279		ContentBg         lipgloss.Style // Content background
 280		ContentText       lipgloss.Style // Content text
 281		ContentLineNumber lipgloss.Style // Line numbers in code
 282
 283		// State message styles
 284		StateWaiting   lipgloss.Style // "Waiting for tool response..."
 285		StateCancelled lipgloss.Style // "Canceled."
 286
 287		// Error styles
 288		ErrorTag     lipgloss.Style // ERROR tag
 289		ErrorMessage lipgloss.Style // Error message text
 290
 291		// Diff styles
 292		DiffTruncation lipgloss.Style // Diff truncation message with padding
 293
 294		// Multi-edit note styles
 295		NoteTag     lipgloss.Style // NOTE tag (yellow background)
 296		NoteMessage lipgloss.Style // Note message text
 297
 298		// Job header styles (for bash jobs)
 299		JobIconPending lipgloss.Style // Pending job icon (green dark)
 300		JobIconError   lipgloss.Style // Error job icon (red dark)
 301		JobIconSuccess lipgloss.Style // Success job icon (green)
 302		JobToolName    lipgloss.Style // Job tool name "Bash" (blue)
 303		JobAction      lipgloss.Style // Action text (Start, Output, Kill)
 304		JobPID         lipgloss.Style // PID text
 305		JobDescription lipgloss.Style // Description text
 306
 307		// Agent task styles
 308		AgentTaskTag lipgloss.Style // Agent task tag (blue background, bold)
 309		AgentPrompt  lipgloss.Style // Agent prompt text
 310
 311		// Agentic fetch styles
 312		AgenticFetchPromptTag lipgloss.Style // Agentic fetch prompt tag (green background, bold)
 313
 314		// Todo styles
 315		TodoRatio          lipgloss.Style // Todo ratio (e.g., "2/5")
 316		TodoCompletedIcon  lipgloss.Style // Completed todo icon
 317		TodoInProgressIcon lipgloss.Style // In-progress todo icon
 318		TodoPendingIcon    lipgloss.Style // Pending todo icon
 319
 320		// MCP tools
 321		MCPName     lipgloss.Style // The mcp name
 322		MCPToolName lipgloss.Style // The mcp tool name
 323		MCPArrow    lipgloss.Style // The mcp arrow icon
 324
 325		// Images and external resources
 326		ResourceLoadedText      lipgloss.Style
 327		ResourceLoadedIndicator lipgloss.Style
 328		ResourceName            lipgloss.Style
 329		ResourceSize            lipgloss.Style
 330		MediaType               lipgloss.Style
 331
 332		// Docker MCP tools
 333		DockerMCPActionAdd lipgloss.Style // Docker MCP add action (green)
 334		DockerMCPActionDel lipgloss.Style // Docker MCP remove action (red)
 335	}
 336
 337	// Dialog styles
 338	Dialog struct {
 339		Title       lipgloss.Style
 340		TitleText   lipgloss.Style
 341		TitleError  lipgloss.Style
 342		TitleAccent lipgloss.Style
 343		// View is the main content area style.
 344		View          lipgloss.Style
 345		PrimaryText   lipgloss.Style
 346		SecondaryText lipgloss.Style
 347		// HelpView is the line that contains the help.
 348		HelpView lipgloss.Style
 349		Help     struct {
 350			Ellipsis       lipgloss.Style
 351			ShortKey       lipgloss.Style
 352			ShortDesc      lipgloss.Style
 353			ShortSeparator lipgloss.Style
 354			FullKey        lipgloss.Style
 355			FullDesc       lipgloss.Style
 356			FullSeparator  lipgloss.Style
 357		}
 358
 359		NormalItem   lipgloss.Style
 360		SelectedItem lipgloss.Style
 361		InputPrompt  lipgloss.Style
 362
 363		List lipgloss.Style
 364
 365		Spinner lipgloss.Style
 366
 367		// ContentPanel is used for content blocks with subtle background.
 368		ContentPanel lipgloss.Style
 369
 370		// Scrollbar styles for scrollable content.
 371		ScrollbarThumb lipgloss.Style
 372		ScrollbarTrack lipgloss.Style
 373
 374		// Arguments
 375		Arguments struct {
 376			Content                  lipgloss.Style
 377			Description              lipgloss.Style
 378			InputLabelBlurred        lipgloss.Style
 379			InputLabelFocused        lipgloss.Style
 380			InputRequiredMarkBlurred lipgloss.Style
 381			InputRequiredMarkFocused lipgloss.Style
 382		}
 383
 384		Commands struct{}
 385
 386		ImagePreview lipgloss.Style
 387
 388		Sessions struct {
 389			// styles for when we are in delete mode
 390			DeletingView                   lipgloss.Style
 391			DeletingItemFocused            lipgloss.Style
 392			DeletingItemBlurred            lipgloss.Style
 393			DeletingTitle                  lipgloss.Style
 394			DeletingMessage                lipgloss.Style
 395			DeletingTitleGradientFromColor color.Color
 396			DeletingTitleGradientToColor   color.Color
 397
 398			// styles for when we are in update mode
 399			RenamingView                   lipgloss.Style
 400			RenamingingItemFocused         lipgloss.Style
 401			RenamingItemBlurred            lipgloss.Style
 402			RenamingingTitle               lipgloss.Style
 403			RenamingingMessage             lipgloss.Style
 404			RenamingTitleGradientFromColor color.Color
 405			RenamingTitleGradientToColor   color.Color
 406			RenamingPlaceholder            lipgloss.Style
 407		}
 408	}
 409
 410	// Status bar and help
 411	Status struct {
 412		Help lipgloss.Style
 413
 414		ErrorIndicator   lipgloss.Style
 415		WarnIndicator    lipgloss.Style
 416		InfoIndicator    lipgloss.Style
 417		UpdateIndicator  lipgloss.Style
 418		SuccessIndicator lipgloss.Style
 419
 420		ErrorMessage   lipgloss.Style
 421		WarnMessage    lipgloss.Style
 422		InfoMessage    lipgloss.Style
 423		UpdateMessage  lipgloss.Style
 424		SuccessMessage lipgloss.Style
 425	}
 426
 427	// Completions popup styles
 428	Completions struct {
 429		Normal  lipgloss.Style
 430		Focused lipgloss.Style
 431		Match   lipgloss.Style
 432	}
 433
 434	// Attachments styles
 435	Attachments struct {
 436		Normal   lipgloss.Style
 437		Image    lipgloss.Style
 438		Text     lipgloss.Style
 439		Deleting lipgloss.Style
 440	}
 441
 442	// Pills styles for todo/queue pills
 443	Pills struct {
 444		Base            lipgloss.Style // Base pill style with padding
 445		Focused         lipgloss.Style // Focused pill with visible border
 446		Blurred         lipgloss.Style // Blurred pill with hidden border
 447		QueueItemPrefix lipgloss.Style // Prefix for queue list items
 448		HelpKey         lipgloss.Style // Keystroke hint style
 449		HelpText        lipgloss.Style // Help action text style
 450		Area            lipgloss.Style // Pills area container
 451		TodoSpinner     lipgloss.Style // Todo spinner style
 452	}
 453}
 454
 455// ChromaTheme converts the current markdown chroma styles to a chroma
 456// StyleEntries map.
 457func (s *Styles) ChromaTheme() chroma.StyleEntries {
 458	rules := s.Markdown.CodeBlock
 459
 460	return chroma.StyleEntries{
 461		chroma.Text:                chromaStyle(rules.Chroma.Text),
 462		chroma.TextWhitespace:      chromaStyle(rules.Chroma.Text),
 463		chroma.Other:               chromaStyle(rules.Chroma.Text),
 464		chroma.Error:               chromaStyle(rules.Chroma.Error),
 465		chroma.Comment:             chromaStyle(rules.Chroma.Comment),
 466		chroma.CommentPreproc:      chromaStyle(rules.Chroma.CommentPreproc),
 467		chroma.Keyword:             chromaStyle(rules.Chroma.Keyword),
 468		chroma.KeywordReserved:     chromaStyle(rules.Chroma.KeywordReserved),
 469		chroma.KeywordNamespace:    chromaStyle(rules.Chroma.KeywordNamespace),
 470		chroma.KeywordType:         chromaStyle(rules.Chroma.KeywordType),
 471		chroma.Operator:            chromaStyle(rules.Chroma.Operator),
 472		chroma.Punctuation:         chromaStyle(rules.Chroma.Punctuation),
 473		chroma.Name:                chromaStyle(rules.Chroma.Name),
 474		chroma.NameBuiltin:         chromaStyle(rules.Chroma.NameBuiltin),
 475		chroma.NameTag:             chromaStyle(rules.Chroma.NameTag),
 476		chroma.NameAttribute:       chromaStyle(rules.Chroma.NameAttribute),
 477		chroma.NameClass:           chromaStyle(rules.Chroma.NameClass),
 478		chroma.NameConstant:        chromaStyle(rules.Chroma.NameConstant),
 479		chroma.NameDecorator:       chromaStyle(rules.Chroma.NameDecorator),
 480		chroma.NameException:       chromaStyle(rules.Chroma.NameException),
 481		chroma.NameFunction:        chromaStyle(rules.Chroma.NameFunction),
 482		chroma.NameOther:           chromaStyle(rules.Chroma.NameOther),
 483		chroma.Literal:             chromaStyle(rules.Chroma.Literal),
 484		chroma.LiteralNumber:       chromaStyle(rules.Chroma.LiteralNumber),
 485		chroma.LiteralDate:         chromaStyle(rules.Chroma.LiteralDate),
 486		chroma.LiteralString:       chromaStyle(rules.Chroma.LiteralString),
 487		chroma.LiteralStringEscape: chromaStyle(rules.Chroma.LiteralStringEscape),
 488		chroma.LiteralOther:        chromaStyle(rules.Chroma.Text),
 489		chroma.GenericDeleted:      chromaStyle(rules.Chroma.GenericDeleted),
 490		chroma.GenericEmph:         chromaStyle(rules.Chroma.GenericEmph),
 491		chroma.GenericInserted:     chromaStyle(rules.Chroma.GenericInserted),
 492		chroma.GenericStrong:       chromaStyle(rules.Chroma.GenericStrong),
 493		chroma.GenericSubheading:   chromaStyle(rules.Chroma.GenericSubheading),
 494		chroma.Background:          chromaStyle(rules.Chroma.Background),
 495		// Additional Chroma token types that map to parent categories
 496		// chroma.KeywordConstant:        chromaStyle(rules.Chroma.Keyword),
 497		// chroma.KeywordDeclaration:     chromaStyle(rules.Chroma.Keyword),
 498		// chroma.KeywordPseudo:          chromaStyle(rules.Chroma.Keyword),
 499		// chroma.NameVariable:           chromaStyle(rules.Chroma.Name),
 500		// chroma.NameLabel:              chromaStyle(rules.Chroma.Name),
 501		// chroma.NameNamespace:          chromaStyle(rules.Chroma.Name),
 502		// chroma.NameProperty:           chromaStyle(rules.Chroma.Name),
 503		// chroma.NameEntity:             chromaStyle(rules.Chroma.Name),
 504		// chroma.NameKeyword:            chromaStyle(rules.Chroma.Keyword),
 505		// chroma.NameOperator:           chromaStyle(rules.Chroma.Operator),
 506		// chroma.OperatorWord:           chromaStyle(rules.Chroma.Operator),
 507		// chroma.CommentHashbang:        chromaStyle(rules.Chroma.Comment),
 508		// chroma.CommentMultiline:       chromaStyle(rules.Chroma.Comment),
 509		// chroma.CommentSingle:          chromaStyle(rules.Chroma.Comment),
 510		// chroma.CommentSpecial:         chromaStyle(rules.Chroma.Comment),
 511		// chroma.LiteralStringAffix:     chromaStyle(rules.Chroma.LiteralString),
 512		// chroma.LiteralStringBacktick:  chromaStyle(rules.Chroma.LiteralString),
 513		// chroma.LiteralStringChar:      chromaStyle(rules.Chroma.LiteralString),
 514		// chroma.LiteralStringDelimiter: chromaStyle(rules.Chroma.LiteralString),
 515		// chroma.LiteralStringDoc:       chromaStyle(rules.Chroma.LiteralString),
 516		// chroma.LiteralStringDouble:    chromaStyle(rules.Chroma.LiteralString),
 517		// chroma.LiteralStringHeredoc:   chromaStyle(rules.Chroma.LiteralString),
 518		// chroma.LiteralStringInterpol:  chromaStyle(rules.Chroma.LiteralString),
 519		// chroma.LiteralStringName:      chromaStyle(rules.Chroma.LiteralString),
 520		// chroma.LiteralStringOther:     chromaStyle(rules.Chroma.LiteralString),
 521		// chroma.LiteralStringRegex:     chromaStyle(rules.Chroma.LiteralString),
 522		// chroma.LiteralStringSingle:    chromaStyle(rules.Chroma.LiteralString),
 523		// chroma.LiteralStringSymbol:    chromaStyle(rules.Chroma.LiteralString),
 524		// chroma.LiteralNumberBin:       chromaStyle(rules.Chroma.LiteralNumber),
 525		// chroma.LiteralNumberFloat:     chromaStyle(rules.Chroma.LiteralNumber),
 526		// chroma.LiteralNumberHex:       chromaStyle(rules.Chroma.LiteralNumber),
 527		// chroma.LiteralNumberInteger:   chromaStyle(rules.Chroma.LiteralNumber),
 528		// chroma.LiteralNumberOct:       chromaStyle(rules.Chroma.LiteralNumber),
 529		// chroma.LiteralNumberByte:      chromaStyle(rules.Chroma.LiteralNumber),
 530	}
 531}
 532
 533// DialogHelpStyles returns the styles for dialog help.
 534func (s *Styles) DialogHelpStyles() help.Styles {
 535	return help.Styles(s.Dialog.Help)
 536}
 537
 538// DefaultStyles returns the default styles for the UI.
 539func DefaultStyles() Styles {
 540	var (
 541		primary   = charmtone.Charple
 542		secondary = charmtone.Dolly
 543		tertiary  = charmtone.Bok
 544		// accent    = charmtone.Zest
 545
 546		// Backgrounds
 547		bgBase        = charmtone.Pepper
 548		bgBaseLighter = charmtone.BBQ
 549		bgSubtle      = charmtone.Charcoal
 550		bgOverlay     = charmtone.Iron
 551
 552		// Foregrounds
 553		fgBase      = charmtone.Ash
 554		fgMuted     = charmtone.Squid
 555		fgHalfMuted = charmtone.Smoke
 556		fgSubtle    = charmtone.Oyster
 557		// fgSelected  = charmtone.Salt
 558
 559		// Borders
 560		border      = charmtone.Charcoal
 561		borderFocus = charmtone.Charple
 562
 563		// Status
 564		error   = charmtone.Sriracha
 565		warning = charmtone.Zest
 566		info    = charmtone.Malibu
 567
 568		// Colors
 569		white = charmtone.Butter
 570
 571		blueLight = charmtone.Sardine
 572		blue      = charmtone.Malibu
 573		blueDark  = charmtone.Damson
 574
 575		// yellow = charmtone.Mustard
 576		yellow = charmtone.Mustard
 577		// citron = charmtone.Citron
 578
 579		greenLight = charmtone.Bok
 580		green      = charmtone.Julep
 581		greenDark  = charmtone.Guac
 582		// greenLight = charmtone.Bok
 583
 584		red     = charmtone.Coral
 585		redDark = charmtone.Sriracha
 586		// redLight = charmtone.Salmon
 587		// cherry   = charmtone.Cherry
 588	)
 589
 590	normalBorder := lipgloss.NormalBorder()
 591
 592	base := lipgloss.NewStyle().Foreground(fgBase)
 593
 594	s := Styles{}
 595
 596	s.Background = bgBase
 597
 598	// Populate color fields
 599	s.Primary = primary
 600	s.Secondary = secondary
 601	s.Tertiary = tertiary
 602	s.BgBase = bgBase
 603	s.BgBaseLighter = bgBaseLighter
 604	s.BgSubtle = bgSubtle
 605	s.BgOverlay = bgOverlay
 606	s.FgBase = fgBase
 607	s.FgMuted = fgMuted
 608	s.FgHalfMuted = fgHalfMuted
 609	s.FgSubtle = fgSubtle
 610	s.Border = border
 611	s.BorderColor = borderFocus
 612	s.Error = error
 613	s.Warning = warning
 614	s.Info = info
 615	s.White = white
 616	s.BlueLight = blueLight
 617	s.Blue = blue
 618	s.BlueDark = blueDark
 619	s.GreenLight = greenLight
 620	s.Green = green
 621	s.GreenDark = greenDark
 622	s.Red = red
 623	s.RedDark = redDark
 624	s.Yellow = yellow
 625
 626	s.TextInput = textinput.Styles{
 627		Focused: textinput.StyleState{
 628			Text:        base,
 629			Placeholder: base.Foreground(fgSubtle),
 630			Prompt:      base.Foreground(tertiary),
 631			Suggestion:  base.Foreground(fgSubtle),
 632		},
 633		Blurred: textinput.StyleState{
 634			Text:        base.Foreground(fgMuted),
 635			Placeholder: base.Foreground(fgSubtle),
 636			Prompt:      base.Foreground(fgMuted),
 637			Suggestion:  base.Foreground(fgSubtle),
 638		},
 639		Cursor: textinput.CursorStyle{
 640			Color: secondary,
 641			Shape: tea.CursorBlock,
 642			Blink: true,
 643		},
 644	}
 645
 646	s.TextArea = textarea.Styles{
 647		Focused: textarea.StyleState{
 648			Base:             base,
 649			Text:             base,
 650			LineNumber:       base.Foreground(fgSubtle),
 651			CursorLine:       base,
 652			CursorLineNumber: base.Foreground(fgSubtle),
 653			Placeholder:      base.Foreground(fgSubtle),
 654			Prompt:           base.Foreground(tertiary),
 655		},
 656		Blurred: textarea.StyleState{
 657			Base:             base,
 658			Text:             base.Foreground(fgMuted),
 659			LineNumber:       base.Foreground(fgMuted),
 660			CursorLine:       base,
 661			CursorLineNumber: base.Foreground(fgMuted),
 662			Placeholder:      base.Foreground(fgSubtle),
 663			Prompt:           base.Foreground(fgMuted),
 664		},
 665		Cursor: textarea.CursorStyle{
 666			Color: secondary,
 667			Shape: tea.CursorBlock,
 668			Blink: true,
 669		},
 670	}
 671
 672	s.Markdown = ansi.StyleConfig{
 673		Document: ansi.StyleBlock{
 674			StylePrimitive: ansi.StylePrimitive{
 675				// BlockPrefix: "\n",
 676				// BlockSuffix: "\n",
 677				Color: new(charmtone.Smoke.Hex()),
 678			},
 679			// Margin: new(uint(defaultMargin)),
 680		},
 681		BlockQuote: ansi.StyleBlock{
 682			StylePrimitive: ansi.StylePrimitive{
 683				Color: new(charmtone.Smoke.Hex()),
 684			},
 685			Indent:      new(uint(1)),
 686			IndentToken: new("β”‚ "),
 687		},
 688		Paragraph: ansi.StyleBlock{
 689			StylePrimitive: ansi.StylePrimitive{
 690				Color: new(charmtone.Smoke.Hex()),
 691			},
 692		},
 693		List: ansi.StyleList{
 694			LevelIndent: defaultListIndent,
 695		},
 696		Heading: ansi.StyleBlock{
 697			StylePrimitive: ansi.StylePrimitive{
 698				BlockSuffix: "\n",
 699				Color:       new(charmtone.Malibu.Hex()),
 700				Bold:        new(true),
 701			},
 702		},
 703		H1: ansi.StyleBlock{
 704			StylePrimitive: ansi.StylePrimitive{
 705				Prefix:          " ",
 706				Suffix:          " ",
 707				Color:           new(charmtone.Zest.Hex()),
 708				BackgroundColor: new(charmtone.Charple.Hex()),
 709				Bold:            new(true),
 710			},
 711		},
 712		H2: ansi.StyleBlock{
 713			StylePrimitive: ansi.StylePrimitive{
 714				Prefix: "## ",
 715			},
 716		},
 717		H3: ansi.StyleBlock{
 718			StylePrimitive: ansi.StylePrimitive{
 719				Prefix: "### ",
 720			},
 721		},
 722		H4: ansi.StyleBlock{
 723			StylePrimitive: ansi.StylePrimitive{
 724				Prefix: "#### ",
 725			},
 726		},
 727		H5: ansi.StyleBlock{
 728			StylePrimitive: ansi.StylePrimitive{
 729				Prefix: "##### ",
 730			},
 731		},
 732		H6: ansi.StyleBlock{
 733			StylePrimitive: ansi.StylePrimitive{
 734				Prefix: "###### ",
 735				Color:  new(charmtone.Guac.Hex()),
 736				Bold:   new(false),
 737			},
 738		},
 739		Strikethrough: ansi.StylePrimitive{
 740			CrossedOut: new(true),
 741			Color:      new(charmtone.Smoke.Hex()),
 742		},
 743		Emph: ansi.StylePrimitive{
 744			Italic: new(true),
 745			Color:  new(charmtone.Smoke.Hex()),
 746		},
 747		Strong: ansi.StylePrimitive{
 748			Bold:  new(true),
 749			Color: new(charmtone.Smoke.Hex()),
 750		},
 751		HorizontalRule: ansi.StylePrimitive{
 752			Color:  new(charmtone.Charcoal.Hex()),
 753			Format: "\n--------\n",
 754		},
 755		Item: ansi.StylePrimitive{
 756			BlockPrefix: "β€’ ",
 757			Color:       new(charmtone.Smoke.Hex()),
 758		},
 759		Enumeration: ansi.StylePrimitive{
 760			BlockPrefix: ". ",
 761			Color:       new(charmtone.Smoke.Hex()),
 762		},
 763		Text: ansi.StylePrimitive{
 764			Color: new(charmtone.Smoke.Hex()),
 765		},
 766		Task: ansi.StyleTask{
 767			StylePrimitive: ansi.StylePrimitive{
 768				Color: new(charmtone.Smoke.Hex()),
 769			},
 770			Ticked:   "[βœ“] ",
 771			Unticked: "[ ] ",
 772		},
 773		Link: ansi.StylePrimitive{
 774			Color:     new(charmtone.Zinc.Hex()),
 775			Underline: new(true),
 776		},
 777		LinkText: ansi.StylePrimitive{
 778			Color: new(charmtone.Guac.Hex()),
 779			Bold:  new(true),
 780		},
 781		Image: ansi.StylePrimitive{
 782			Color:     new(charmtone.Cheeky.Hex()),
 783			Underline: new(true),
 784		},
 785		ImageText: ansi.StylePrimitive{
 786			Color:  new(charmtone.Squid.Hex()),
 787			Format: "Image: {{.text}} β†’",
 788		},
 789		Code: ansi.StyleBlock{
 790			StylePrimitive: ansi.StylePrimitive{
 791				Prefix:          " ",
 792				Suffix:          " ",
 793				Color:           new(charmtone.Coral.Hex()),
 794				BackgroundColor: new(charmtone.Charcoal.Hex()),
 795			},
 796		},
 797		CodeBlock: ansi.StyleCodeBlock{
 798			StyleBlock: ansi.StyleBlock{
 799				StylePrimitive: ansi.StylePrimitive{
 800					Color: new(charmtone.Smoke.Hex()),
 801				},
 802				Margin: new(uint(defaultMargin)),
 803			},
 804			Chroma: &ansi.Chroma{
 805				Text: ansi.StylePrimitive{
 806					Color: new(charmtone.Smoke.Hex()),
 807				},
 808				Error: ansi.StylePrimitive{
 809					Color:           new(charmtone.Butter.Hex()),
 810					BackgroundColor: new(charmtone.Sriracha.Hex()),
 811				},
 812				Comment: ansi.StylePrimitive{
 813					Color: new(charmtone.Oyster.Hex()),
 814				},
 815				CommentPreproc: ansi.StylePrimitive{
 816					Color: new(charmtone.Bengal.Hex()),
 817				},
 818				Keyword: ansi.StylePrimitive{
 819					Color: new(charmtone.Malibu.Hex()),
 820				},
 821				KeywordReserved: ansi.StylePrimitive{
 822					Color: new(charmtone.Pony.Hex()),
 823				},
 824				KeywordNamespace: ansi.StylePrimitive{
 825					Color: new(charmtone.Pony.Hex()),
 826				},
 827				KeywordType: ansi.StylePrimitive{
 828					Color: new(charmtone.Guppy.Hex()),
 829				},
 830				Operator: ansi.StylePrimitive{
 831					Color: new(charmtone.Salmon.Hex()),
 832				},
 833				Punctuation: ansi.StylePrimitive{
 834					Color: new(charmtone.Zest.Hex()),
 835				},
 836				Name: ansi.StylePrimitive{
 837					Color: new(charmtone.Smoke.Hex()),
 838				},
 839				NameBuiltin: ansi.StylePrimitive{
 840					Color: new(charmtone.Cheeky.Hex()),
 841				},
 842				NameTag: ansi.StylePrimitive{
 843					Color: new(charmtone.Mauve.Hex()),
 844				},
 845				NameAttribute: ansi.StylePrimitive{
 846					Color: new(charmtone.Hazy.Hex()),
 847				},
 848				NameClass: ansi.StylePrimitive{
 849					Color:     new(charmtone.Salt.Hex()),
 850					Underline: new(true),
 851					Bold:      new(true),
 852				},
 853				NameDecorator: ansi.StylePrimitive{
 854					Color: new(charmtone.Citron.Hex()),
 855				},
 856				NameFunction: ansi.StylePrimitive{
 857					Color: new(charmtone.Guac.Hex()),
 858				},
 859				LiteralNumber: ansi.StylePrimitive{
 860					Color: new(charmtone.Julep.Hex()),
 861				},
 862				LiteralString: ansi.StylePrimitive{
 863					Color: new(charmtone.Cumin.Hex()),
 864				},
 865				LiteralStringEscape: ansi.StylePrimitive{
 866					Color: new(charmtone.Bok.Hex()),
 867				},
 868				GenericDeleted: ansi.StylePrimitive{
 869					Color: new(charmtone.Coral.Hex()),
 870				},
 871				GenericEmph: ansi.StylePrimitive{
 872					Italic: new(true),
 873				},
 874				GenericInserted: ansi.StylePrimitive{
 875					Color: new(charmtone.Guac.Hex()),
 876				},
 877				GenericStrong: ansi.StylePrimitive{
 878					Bold: new(true),
 879				},
 880				GenericSubheading: ansi.StylePrimitive{
 881					Color: new(charmtone.Squid.Hex()),
 882				},
 883				Background: ansi.StylePrimitive{
 884					BackgroundColor: new(charmtone.Charcoal.Hex()),
 885				},
 886			},
 887		},
 888		Table: ansi.StyleTable{
 889			StyleBlock: ansi.StyleBlock{
 890				StylePrimitive: ansi.StylePrimitive{
 891					Color: new(charmtone.Smoke.Hex()),
 892				},
 893			},
 894		},
 895		DefinitionDescription: ansi.StylePrimitive{
 896			BlockPrefix: "\n ",
 897			Color:       new(charmtone.Smoke.Hex()),
 898		},
 899		HTMLBlock: ansi.StyleBlock{
 900			StylePrimitive: ansi.StylePrimitive{
 901				Color: new(charmtone.Smoke.Hex()),
 902			},
 903		},
 904		HTMLSpan: ansi.StyleBlock{
 905			StylePrimitive: ansi.StylePrimitive{
 906				Color: new(charmtone.Smoke.Hex()),
 907			},
 908		},
 909	}
 910
 911	// PlainMarkdown style - muted colors on subtle background for thinking content.
 912	plainBg := new(bgBaseLighter.Hex())
 913	plainFg := new(fgMuted.Hex())
 914	s.PlainMarkdown = ansi.StyleConfig{
 915		Document: ansi.StyleBlock{
 916			StylePrimitive: ansi.StylePrimitive{
 917				Color:           plainFg,
 918				BackgroundColor: plainBg,
 919			},
 920		},
 921		BlockQuote: ansi.StyleBlock{
 922			StylePrimitive: ansi.StylePrimitive{
 923				Color:           plainFg,
 924				BackgroundColor: plainBg,
 925			},
 926			Indent:      new(uint(1)),
 927			IndentToken: new("β”‚ "),
 928		},
 929		Paragraph: ansi.StyleBlock{
 930			StylePrimitive: ansi.StylePrimitive{
 931				Color:           plainFg,
 932				BackgroundColor: plainBg,
 933			},
 934		},
 935		List: ansi.StyleList{
 936			LevelIndent: defaultListIndent,
 937		},
 938		Heading: ansi.StyleBlock{
 939			StylePrimitive: ansi.StylePrimitive{
 940				BlockSuffix:     "\n",
 941				Bold:            new(true),
 942				Color:           plainFg,
 943				BackgroundColor: plainBg,
 944			},
 945		},
 946		H1: ansi.StyleBlock{
 947			StylePrimitive: ansi.StylePrimitive{
 948				Prefix:          " ",
 949				Suffix:          " ",
 950				Bold:            new(true),
 951				Color:           plainFg,
 952				BackgroundColor: plainBg,
 953			},
 954		},
 955		H2: ansi.StyleBlock{
 956			StylePrimitive: ansi.StylePrimitive{
 957				Prefix:          "## ",
 958				Color:           plainFg,
 959				BackgroundColor: plainBg,
 960			},
 961		},
 962		H3: ansi.StyleBlock{
 963			StylePrimitive: ansi.StylePrimitive{
 964				Prefix:          "### ",
 965				Color:           plainFg,
 966				BackgroundColor: plainBg,
 967			},
 968		},
 969		H4: ansi.StyleBlock{
 970			StylePrimitive: ansi.StylePrimitive{
 971				Prefix:          "#### ",
 972				Color:           plainFg,
 973				BackgroundColor: plainBg,
 974			},
 975		},
 976		H5: ansi.StyleBlock{
 977			StylePrimitive: ansi.StylePrimitive{
 978				Prefix:          "##### ",
 979				Color:           plainFg,
 980				BackgroundColor: plainBg,
 981			},
 982		},
 983		H6: ansi.StyleBlock{
 984			StylePrimitive: ansi.StylePrimitive{
 985				Prefix:          "###### ",
 986				Color:           plainFg,
 987				BackgroundColor: plainBg,
 988			},
 989		},
 990		Strikethrough: ansi.StylePrimitive{
 991			CrossedOut:      new(true),
 992			Color:           plainFg,
 993			BackgroundColor: plainBg,
 994		},
 995		Emph: ansi.StylePrimitive{
 996			Italic:          new(true),
 997			Color:           plainFg,
 998			BackgroundColor: plainBg,
 999		},
1000		Strong: ansi.StylePrimitive{
1001			Bold:            new(true),
1002			Color:           plainFg,
1003			BackgroundColor: plainBg,
1004		},
1005		HorizontalRule: ansi.StylePrimitive{
1006			Format:          "\n--------\n",
1007			Color:           plainFg,
1008			BackgroundColor: plainBg,
1009		},
1010		Item: ansi.StylePrimitive{
1011			BlockPrefix:     "β€’ ",
1012			Color:           plainFg,
1013			BackgroundColor: plainBg,
1014		},
1015		Enumeration: ansi.StylePrimitive{
1016			BlockPrefix:     ". ",
1017			Color:           plainFg,
1018			BackgroundColor: plainBg,
1019		},
1020		Text: ansi.StylePrimitive{
1021			Color:           plainFg,
1022			BackgroundColor: plainBg,
1023		},
1024		Task: ansi.StyleTask{
1025			StylePrimitive: ansi.StylePrimitive{
1026				Color:           plainFg,
1027				BackgroundColor: plainBg,
1028			},
1029			Ticked:   "[βœ“] ",
1030			Unticked: "[ ] ",
1031		},
1032		Link: ansi.StylePrimitive{
1033			Underline:       new(true),
1034			Color:           plainFg,
1035			BackgroundColor: plainBg,
1036		},
1037		LinkText: ansi.StylePrimitive{
1038			Bold:            new(true),
1039			Color:           plainFg,
1040			BackgroundColor: plainBg,
1041		},
1042		Image: ansi.StylePrimitive{
1043			Underline:       new(true),
1044			Color:           plainFg,
1045			BackgroundColor: plainBg,
1046		},
1047		ImageText: ansi.StylePrimitive{
1048			Format:          "Image: {{.text}} β†’",
1049			Color:           plainFg,
1050			BackgroundColor: plainBg,
1051		},
1052		Code: ansi.StyleBlock{
1053			StylePrimitive: ansi.StylePrimitive{
1054				Prefix:          " ",
1055				Suffix:          " ",
1056				Color:           plainFg,
1057				BackgroundColor: plainBg,
1058			},
1059		},
1060		CodeBlock: ansi.StyleCodeBlock{
1061			StyleBlock: ansi.StyleBlock{
1062				StylePrimitive: ansi.StylePrimitive{
1063					BackgroundColor: plainBg,
1064				},
1065				Margin: new(uint(defaultMargin)),
1066			},
1067			Chroma: &ansi.Chroma{
1068				Text: ansi.StylePrimitive{
1069					Color: plainFg,
1070				},
1071				Error: ansi.StylePrimitive{
1072					Color:           new(charmtone.Butter.Hex()),
1073					BackgroundColor: new(charmtone.Sriracha.Hex()),
1074				},
1075				Comment: ansi.StylePrimitive{
1076					Color: plainFg,
1077				},
1078				CommentPreproc: ansi.StylePrimitive{
1079					Color: plainFg,
1080				},
1081				Keyword: ansi.StylePrimitive{
1082					Color: plainFg,
1083				},
1084				KeywordReserved: ansi.StylePrimitive{
1085					Color: plainFg,
1086				},
1087				KeywordNamespace: ansi.StylePrimitive{
1088					Color: plainFg,
1089				},
1090				KeywordType: ansi.StylePrimitive{
1091					Color: plainFg,
1092				},
1093				Operator: ansi.StylePrimitive{
1094					Color: plainFg,
1095				},
1096				Punctuation: ansi.StylePrimitive{
1097					Color: plainFg,
1098				},
1099				Name: ansi.StylePrimitive{
1100					Color: plainFg,
1101				},
1102				NameBuiltin: ansi.StylePrimitive{
1103					Color: plainFg,
1104				},
1105				NameTag: ansi.StylePrimitive{
1106					Color: plainFg,
1107				},
1108				NameAttribute: ansi.StylePrimitive{
1109					Color: plainFg,
1110				},
1111				NameClass: ansi.StylePrimitive{
1112					Color: plainFg,
1113				},
1114				NameDecorator: ansi.StylePrimitive{
1115					Color: plainFg,
1116				},
1117				NameFunction: ansi.StylePrimitive{
1118					Color: plainFg,
1119				},
1120				LiteralNumber: ansi.StylePrimitive{
1121					Color: plainFg,
1122				},
1123				LiteralString: ansi.StylePrimitive{
1124					Color: plainFg,
1125				},
1126				LiteralStringEscape: ansi.StylePrimitive{
1127					Color: plainFg,
1128				},
1129				GenericDeleted: ansi.StylePrimitive{
1130					Color: plainFg,
1131				},
1132				GenericEmph: ansi.StylePrimitive{
1133					Italic: new(true),
1134				},
1135				GenericInserted: ansi.StylePrimitive{
1136					Color: plainFg,
1137				},
1138				GenericStrong: ansi.StylePrimitive{
1139					Bold: new(true),
1140				},
1141				GenericSubheading: ansi.StylePrimitive{
1142					Color: plainFg,
1143				},
1144				Background: ansi.StylePrimitive{
1145					BackgroundColor: plainBg,
1146				},
1147			},
1148		},
1149		Table: ansi.StyleTable{
1150			StyleBlock: ansi.StyleBlock{
1151				StylePrimitive: ansi.StylePrimitive{
1152					Color:           plainFg,
1153					BackgroundColor: plainBg,
1154				},
1155			},
1156		},
1157		DefinitionDescription: ansi.StylePrimitive{
1158			BlockPrefix:     "\n ",
1159			Color:           plainFg,
1160			BackgroundColor: plainBg,
1161		},
1162		HTMLBlock: ansi.StyleBlock{
1163			StylePrimitive: ansi.StylePrimitive{
1164				Color:           plainFg,
1165				BackgroundColor: plainBg,
1166			},
1167		},
1168		HTMLSpan: ansi.StyleBlock{
1169			StylePrimitive: ansi.StylePrimitive{
1170				Color:           plainFg,
1171				BackgroundColor: plainBg,
1172			},
1173		},
1174	}
1175
1176	s.Help = help.Styles{
1177		ShortKey:       base.Foreground(fgMuted),
1178		ShortDesc:      base.Foreground(fgSubtle),
1179		ShortSeparator: base.Foreground(border),
1180		Ellipsis:       base.Foreground(border),
1181		FullKey:        base.Foreground(fgMuted),
1182		FullDesc:       base.Foreground(fgSubtle),
1183		FullSeparator:  base.Foreground(border),
1184	}
1185
1186	s.Diff = diffview.Style{
1187		DividerLine: diffview.LineStyle{
1188			LineNumber: lipgloss.NewStyle().
1189				Foreground(fgHalfMuted).
1190				Background(bgBaseLighter),
1191			Code: lipgloss.NewStyle().
1192				Foreground(fgHalfMuted).
1193				Background(bgBaseLighter),
1194		},
1195		MissingLine: diffview.LineStyle{
1196			LineNumber: lipgloss.NewStyle().
1197				Background(bgBaseLighter),
1198			Code: lipgloss.NewStyle().
1199				Background(bgBaseLighter),
1200		},
1201		EqualLine: diffview.LineStyle{
1202			LineNumber: lipgloss.NewStyle().
1203				Foreground(fgMuted).
1204				Background(bgBase),
1205			Code: lipgloss.NewStyle().
1206				Foreground(fgMuted).
1207				Background(bgBase),
1208		},
1209		InsertLine: diffview.LineStyle{
1210			LineNumber: lipgloss.NewStyle().
1211				Foreground(lipgloss.Color("#629657")).
1212				Background(lipgloss.Color("#2b322a")),
1213			Symbol: lipgloss.NewStyle().
1214				Foreground(lipgloss.Color("#629657")).
1215				Background(lipgloss.Color("#323931")),
1216			Code: lipgloss.NewStyle().
1217				Background(lipgloss.Color("#323931")),
1218		},
1219		DeleteLine: diffview.LineStyle{
1220			LineNumber: lipgloss.NewStyle().
1221				Foreground(lipgloss.Color("#a45c59")).
1222				Background(lipgloss.Color("#312929")),
1223			Symbol: lipgloss.NewStyle().
1224				Foreground(lipgloss.Color("#a45c59")).
1225				Background(lipgloss.Color("#383030")),
1226			Code: lipgloss.NewStyle().
1227				Background(lipgloss.Color("#383030")),
1228		},
1229	}
1230
1231	s.FilePicker = filepicker.Styles{
1232		DisabledCursor:   base.Foreground(fgMuted),
1233		Cursor:           base.Foreground(fgBase),
1234		Symlink:          base.Foreground(fgSubtle),
1235		Directory:        base.Foreground(primary),
1236		File:             base.Foreground(fgBase),
1237		DisabledFile:     base.Foreground(fgMuted),
1238		DisabledSelected: base.Background(bgOverlay).Foreground(fgMuted),
1239		Permission:       base.Foreground(fgMuted),
1240		Selected:         base.Background(primary).Foreground(fgBase),
1241		FileSize:         base.Foreground(fgMuted),
1242		EmptyDirectory:   base.Foreground(fgMuted).PaddingLeft(2).SetString("Empty directory"),
1243	}
1244
1245	// borders
1246	s.FocusedMessageBorder = lipgloss.Border{Left: BorderThick}
1247
1248	// text presets
1249	s.Base = lipgloss.NewStyle().Foreground(fgBase)
1250	s.Muted = lipgloss.NewStyle().Foreground(fgMuted)
1251	s.HalfMuted = lipgloss.NewStyle().Foreground(fgHalfMuted)
1252	s.Subtle = lipgloss.NewStyle().Foreground(fgSubtle)
1253
1254	s.WindowTooSmall = s.Muted
1255
1256	// tag presets
1257	s.TagBase = lipgloss.NewStyle().Padding(0, 1).Foreground(white)
1258	s.TagError = s.TagBase.Background(redDark)
1259	s.TagInfo = s.TagBase.Background(blueLight)
1260
1261	// Compact header styles
1262	s.Header.Charm = base.Foreground(secondary)
1263	s.Header.Diagonals = base.Foreground(primary)
1264	s.Header.Percentage = s.Muted
1265	s.Header.Keystroke = s.Muted
1266	s.Header.KeystrokeTip = s.Subtle
1267	s.Header.WorkingDir = s.Muted
1268	s.Header.Separator = s.Subtle
1269
1270	s.CompactDetails.Title = s.Base
1271	s.CompactDetails.View = s.Base.Padding(0, 1, 1, 1).Border(lipgloss.RoundedBorder()).BorderForeground(borderFocus)
1272	s.CompactDetails.Version = s.Muted
1273
1274	// panels
1275	s.PanelMuted = s.Muted.Background(bgBaseLighter)
1276	s.PanelBase = lipgloss.NewStyle().Background(bgBase)
1277
1278	// code line number
1279	s.LineNumber = lipgloss.NewStyle().Foreground(fgMuted).Background(bgBase).PaddingRight(1).PaddingLeft(1)
1280
1281	// Tool calls
1282	s.ToolCallPending = lipgloss.NewStyle().Foreground(greenDark).SetString(ToolPending)
1283	s.ToolCallError = lipgloss.NewStyle().Foreground(redDark).SetString(ToolError)
1284	s.ToolCallSuccess = lipgloss.NewStyle().Foreground(green).SetString(ToolSuccess)
1285	// Cancelled uses muted tone but same glyph as pending
1286	s.ToolCallCancelled = s.Muted.SetString(ToolPending)
1287	s.EarlyStateMessage = s.Subtle.PaddingLeft(2)
1288
1289	// Tool rendering styles
1290	s.Tool.IconPending = base.Foreground(greenDark).SetString(ToolPending)
1291	s.Tool.IconSuccess = base.Foreground(green).SetString(ToolSuccess)
1292	s.Tool.IconError = base.Foreground(redDark).SetString(ToolError)
1293	s.Tool.IconCancelled = s.Muted.SetString(ToolPending)
1294
1295	s.Tool.NameNormal = base.Foreground(blue)
1296	s.Tool.NameNested = base.Foreground(blue)
1297
1298	s.Tool.ParamMain = s.Subtle
1299	s.Tool.ParamKey = s.Subtle
1300
1301	// Content rendering - prepared styles that accept width parameter
1302	s.Tool.ContentLine = s.Muted.Background(bgBaseLighter)
1303	s.Tool.ContentTruncation = s.Muted.Background(bgBaseLighter)
1304	s.Tool.ContentCodeLine = s.Base.Background(bgBase).PaddingLeft(2)
1305	s.Tool.ContentCodeTruncation = s.Muted.Background(bgBase).PaddingLeft(2)
1306	s.Tool.ContentCodeBg = bgBase
1307	s.Tool.Body = base.PaddingLeft(2)
1308
1309	// Deprecated - kept for backward compatibility
1310	s.Tool.ContentBg = s.Muted.Background(bgBaseLighter)
1311	s.Tool.ContentText = s.Muted
1312	s.Tool.ContentLineNumber = base.Foreground(fgMuted).Background(bgBase).PaddingRight(1).PaddingLeft(1)
1313
1314	s.Tool.StateWaiting = base.Foreground(fgSubtle)
1315	s.Tool.StateCancelled = base.Foreground(fgSubtle)
1316
1317	s.Tool.ErrorTag = base.Padding(0, 1).Background(red).Foreground(white)
1318	s.Tool.ErrorMessage = base.Foreground(fgHalfMuted)
1319
1320	// Diff and multi-edit styles
1321	s.Tool.DiffTruncation = s.Muted.Background(bgBaseLighter).PaddingLeft(2)
1322	s.Tool.NoteTag = base.Padding(0, 1).Background(info).Foreground(white)
1323	s.Tool.NoteMessage = base.Foreground(fgHalfMuted)
1324
1325	// Job header styles
1326	s.Tool.JobIconPending = base.Foreground(greenDark)
1327	s.Tool.JobIconError = base.Foreground(redDark)
1328	s.Tool.JobIconSuccess = base.Foreground(green)
1329	s.Tool.JobToolName = base.Foreground(blue)
1330	s.Tool.JobAction = base.Foreground(blueDark)
1331	s.Tool.JobPID = s.Muted
1332	s.Tool.JobDescription = s.Subtle
1333
1334	// Agent task styles
1335	s.Tool.AgentTaskTag = base.Bold(true).Padding(0, 1).MarginLeft(2).Background(blueLight).Foreground(white)
1336	s.Tool.AgentPrompt = s.Muted
1337
1338	// Agentic fetch styles
1339	s.Tool.AgenticFetchPromptTag = base.Bold(true).Padding(0, 1).MarginLeft(2).Background(green).Foreground(border)
1340
1341	// Todo styles
1342	s.Tool.TodoRatio = base.Foreground(blueDark)
1343	s.Tool.TodoCompletedIcon = base.Foreground(green)
1344	s.Tool.TodoInProgressIcon = base.Foreground(greenDark)
1345	s.Tool.TodoPendingIcon = base.Foreground(fgMuted)
1346
1347	// MCP styles
1348	s.Tool.MCPName = base.Foreground(blue)
1349	s.Tool.MCPToolName = base.Foreground(blueDark)
1350	s.Tool.MCPArrow = base.Foreground(blue).SetString(ArrowRightIcon)
1351
1352	// Loading indicators for images, skills
1353	s.Tool.ResourceLoadedText = base.Foreground(green)
1354	s.Tool.ResourceLoadedIndicator = base.Foreground(greenDark)
1355	s.Tool.ResourceName = base
1356	s.Tool.MediaType = base
1357	s.Tool.ResourceSize = base.Foreground(fgMuted)
1358
1359	// Docker MCP styles
1360	s.Tool.DockerMCPActionAdd = base.Foreground(greenLight)
1361	s.Tool.DockerMCPActionDel = base.Foreground(red)
1362
1363	// Buttons
1364	s.ButtonFocus = lipgloss.NewStyle().Foreground(white).Background(secondary)
1365	s.ButtonBlur = s.Base.Background(bgSubtle)
1366
1367	// Borders
1368	s.BorderFocus = lipgloss.NewStyle().BorderForeground(borderFocus).Border(lipgloss.RoundedBorder()).Padding(1, 2)
1369
1370	// Editor
1371	s.EditorPromptNormalFocused = lipgloss.NewStyle().Foreground(greenDark).SetString("::: ")
1372	s.EditorPromptNormalBlurred = s.EditorPromptNormalFocused.Foreground(fgMuted)
1373	s.EditorPromptYoloIconFocused = lipgloss.NewStyle().MarginRight(1).Foreground(charmtone.Oyster).Background(charmtone.Citron).Bold(true).SetString(" ! ")
1374	s.EditorPromptYoloIconBlurred = s.EditorPromptYoloIconFocused.Foreground(charmtone.Pepper).Background(charmtone.Squid)
1375	s.EditorPromptYoloDotsFocused = lipgloss.NewStyle().MarginRight(1).Foreground(charmtone.Zest).SetString(":::")
1376	s.EditorPromptYoloDotsBlurred = s.EditorPromptYoloDotsFocused.Foreground(charmtone.Squid)
1377
1378	s.RadioOn = s.HalfMuted.SetString(RadioOn)
1379	s.RadioOff = s.HalfMuted.SetString(RadioOff)
1380
1381	// Logo colors
1382	s.LogoFieldColor = primary
1383	s.LogoTitleColorA = secondary
1384	s.LogoTitleColorB = primary
1385	s.LogoCharmColor = secondary
1386	s.LogoVersionColor = primary
1387
1388	// Section
1389	s.Section.Title = s.Subtle
1390	s.Section.Line = s.Base.Foreground(charmtone.Charcoal)
1391
1392	// Initialize
1393	s.Initialize.Header = s.Base
1394	s.Initialize.Content = s.Muted
1395	s.Initialize.Accent = s.Base.Foreground(greenDark)
1396
1397	// LSP and MCP status.
1398	s.ResourceGroupTitle = lipgloss.NewStyle().Foreground(charmtone.Oyster)
1399	s.ResourceOfflineIcon = lipgloss.NewStyle().Foreground(charmtone.Iron).SetString("●")
1400	s.ResourceBusyIcon = s.ResourceOfflineIcon.Foreground(charmtone.Citron)
1401	s.ResourceErrorIcon = s.ResourceOfflineIcon.Foreground(charmtone.Coral)
1402	s.ResourceOnlineIcon = s.ResourceOfflineIcon.Foreground(charmtone.Guac)
1403	s.ResourceName = lipgloss.NewStyle().Foreground(charmtone.Squid)
1404	s.ResourceStatus = lipgloss.NewStyle().Foreground(charmtone.Oyster)
1405	s.ResourceAdditionalText = lipgloss.NewStyle().Foreground(charmtone.Oyster)
1406
1407	// LSP
1408	s.LSP.ErrorDiagnostic = s.Base.Foreground(redDark)
1409	s.LSP.WarningDiagnostic = s.Base.Foreground(warning)
1410	s.LSP.HintDiagnostic = s.Base.Foreground(fgHalfMuted)
1411	s.LSP.InfoDiagnostic = s.Base.Foreground(info)
1412
1413	// Files
1414	s.Files.Path = s.Muted
1415	s.Files.Additions = s.Base.Foreground(greenDark)
1416	s.Files.Deletions = s.Base.Foreground(redDark)
1417
1418	// Chat
1419	messageFocussedBorder := lipgloss.Border{
1420		Left: "β–Œ",
1421	}
1422
1423	s.Chat.Message.NoContent = lipgloss.NewStyle().Foreground(fgBase)
1424	s.Chat.Message.UserBlurred = s.Chat.Message.NoContent.PaddingLeft(1).BorderLeft(true).
1425		BorderForeground(primary).BorderStyle(normalBorder)
1426	s.Chat.Message.UserFocused = s.Chat.Message.NoContent.PaddingLeft(1).BorderLeft(true).
1427		BorderForeground(primary).BorderStyle(messageFocussedBorder)
1428	s.Chat.Message.AssistantBlurred = s.Chat.Message.NoContent.PaddingLeft(2)
1429	s.Chat.Message.AssistantFocused = s.Chat.Message.NoContent.PaddingLeft(1).BorderLeft(true).
1430		BorderForeground(greenDark).BorderStyle(messageFocussedBorder)
1431	s.Chat.Message.Thinking = lipgloss.NewStyle().MaxHeight(10)
1432	s.Chat.Message.ErrorTag = lipgloss.NewStyle().Padding(0, 1).
1433		Background(red).Foreground(white)
1434	s.Chat.Message.ErrorTitle = lipgloss.NewStyle().Foreground(fgHalfMuted)
1435	s.Chat.Message.ErrorDetails = lipgloss.NewStyle().Foreground(fgSubtle)
1436
1437	// Message item styles
1438	s.Chat.Message.ToolCallFocused = s.Muted.PaddingLeft(1).
1439		BorderStyle(messageFocussedBorder).
1440		BorderLeft(true).
1441		BorderForeground(greenDark)
1442	s.Chat.Message.ToolCallBlurred = s.Muted.PaddingLeft(2)
1443	// No padding or border for compact tool calls within messages
1444	s.Chat.Message.ToolCallCompact = s.Muted
1445	s.Chat.Message.SectionHeader = s.Base.PaddingLeft(2)
1446	s.Chat.Message.AssistantInfoIcon = s.Subtle
1447	s.Chat.Message.AssistantInfoModel = s.Muted
1448	s.Chat.Message.AssistantInfoProvider = s.Subtle
1449	s.Chat.Message.AssistantInfoDuration = s.Subtle
1450
1451	// Thinking section styles
1452	s.Chat.Message.ThinkingBox = s.Subtle.Background(bgBaseLighter)
1453	s.Chat.Message.ThinkingTruncationHint = s.Muted
1454	s.Chat.Message.ThinkingFooterTitle = s.Muted
1455	s.Chat.Message.ThinkingFooterDuration = s.Subtle
1456
1457	// Text selection.
1458	s.TextSelection = lipgloss.NewStyle().Foreground(charmtone.Salt).Background(charmtone.Charple)
1459
1460	// Dialog styles
1461	s.Dialog.Title = base.Padding(0, 1).Foreground(primary)
1462	s.Dialog.TitleText = base.Foreground(primary)
1463	s.Dialog.TitleError = base.Foreground(red)
1464	s.Dialog.TitleAccent = base.Foreground(green).Bold(true)
1465	s.Dialog.View = base.Border(lipgloss.RoundedBorder()).BorderForeground(borderFocus)
1466	s.Dialog.PrimaryText = base.Padding(0, 1).Foreground(primary)
1467	s.Dialog.SecondaryText = base.Padding(0, 1).Foreground(fgSubtle)
1468	s.Dialog.HelpView = base.Padding(0, 1).AlignHorizontal(lipgloss.Left)
1469	s.Dialog.Help.ShortKey = base.Foreground(fgMuted)
1470	s.Dialog.Help.ShortDesc = base.Foreground(fgSubtle)
1471	s.Dialog.Help.ShortSeparator = base.Foreground(border)
1472	s.Dialog.Help.Ellipsis = base.Foreground(border)
1473	s.Dialog.Help.FullKey = base.Foreground(fgMuted)
1474	s.Dialog.Help.FullDesc = base.Foreground(fgSubtle)
1475	s.Dialog.Help.FullSeparator = base.Foreground(border)
1476	s.Dialog.NormalItem = base.Padding(0, 1).Foreground(fgBase)
1477	s.Dialog.SelectedItem = base.Padding(0, 1).Background(primary).Foreground(fgBase)
1478	s.Dialog.InputPrompt = base.Margin(1, 1)
1479
1480	s.Dialog.List = base.Margin(0, 0, 1, 0)
1481	s.Dialog.ContentPanel = base.Background(bgSubtle).Foreground(fgBase).Padding(1, 2)
1482	s.Dialog.Spinner = base.Foreground(secondary)
1483	s.Dialog.ScrollbarThumb = base.Foreground(secondary)
1484	s.Dialog.ScrollbarTrack = base.Foreground(border)
1485
1486	s.Dialog.ImagePreview = lipgloss.NewStyle().Padding(0, 1).Foreground(fgSubtle)
1487
1488	s.Dialog.Arguments.Content = base.Padding(1)
1489	s.Dialog.Arguments.Description = base.MarginBottom(1).MaxHeight(3)
1490	s.Dialog.Arguments.InputLabelBlurred = base.Foreground(fgMuted)
1491	s.Dialog.Arguments.InputLabelFocused = base.Bold(true)
1492	s.Dialog.Arguments.InputRequiredMarkBlurred = base.Foreground(fgMuted).SetString("*")
1493	s.Dialog.Arguments.InputRequiredMarkFocused = base.Foreground(primary).Bold(true).SetString("*")
1494
1495	s.Dialog.Sessions.DeletingTitle = s.Dialog.Title.Foreground(red)
1496	s.Dialog.Sessions.DeletingView = s.Dialog.View.BorderForeground(red)
1497	s.Dialog.Sessions.DeletingMessage = s.Base.Padding(1)
1498	s.Dialog.Sessions.DeletingTitleGradientFromColor = red
1499	s.Dialog.Sessions.DeletingTitleGradientToColor = s.Primary
1500	s.Dialog.Sessions.DeletingItemBlurred = s.Dialog.NormalItem.Foreground(fgSubtle)
1501	s.Dialog.Sessions.DeletingItemFocused = s.Dialog.SelectedItem.Background(red).Foreground(charmtone.Butter)
1502
1503	s.Dialog.Sessions.RenamingingTitle = s.Dialog.Title.Foreground(charmtone.Zest)
1504	s.Dialog.Sessions.RenamingView = s.Dialog.View.BorderForeground(charmtone.Zest)
1505	s.Dialog.Sessions.RenamingingMessage = s.Base.Padding(1)
1506	s.Dialog.Sessions.RenamingTitleGradientFromColor = charmtone.Zest
1507	s.Dialog.Sessions.RenamingTitleGradientToColor = charmtone.Bok
1508	s.Dialog.Sessions.RenamingItemBlurred = s.Dialog.NormalItem.Foreground(fgSubtle)
1509	s.Dialog.Sessions.RenamingingItemFocused = s.Dialog.SelectedItem.UnsetBackground().UnsetForeground()
1510	s.Dialog.Sessions.RenamingPlaceholder = base.Foreground(charmtone.Squid)
1511
1512	s.Status.Help = lipgloss.NewStyle().Padding(0, 1)
1513	s.Status.SuccessIndicator = base.Foreground(bgSubtle).Background(green).Padding(0, 1).Bold(true).SetString("OKAY!")
1514	s.Status.InfoIndicator = s.Status.SuccessIndicator
1515	s.Status.UpdateIndicator = s.Status.SuccessIndicator.SetString("HEY!")
1516	s.Status.WarnIndicator = s.Status.SuccessIndicator.Foreground(bgOverlay).Background(yellow).SetString("WARNING")
1517	s.Status.ErrorIndicator = s.Status.SuccessIndicator.Foreground(bgBase).Background(red).SetString("ERROR")
1518	s.Status.SuccessMessage = base.Foreground(bgSubtle).Background(greenDark).Padding(0, 1)
1519	s.Status.InfoMessage = s.Status.SuccessMessage
1520	s.Status.UpdateMessage = s.Status.SuccessMessage
1521	s.Status.WarnMessage = s.Status.SuccessMessage.Foreground(bgOverlay).Background(warning)
1522	s.Status.ErrorMessage = s.Status.SuccessMessage.Foreground(white).Background(redDark)
1523
1524	// Completions styles
1525	s.Completions.Normal = base.Background(bgSubtle).Foreground(fgBase)
1526	s.Completions.Focused = base.Background(primary).Foreground(white)
1527	s.Completions.Match = base.Underline(true)
1528
1529	// Attachments styles
1530	attachmentIconStyle := base.Foreground(bgSubtle).Background(green).Padding(0, 1)
1531	s.Attachments.Image = attachmentIconStyle.SetString(ImageIcon)
1532	s.Attachments.Text = attachmentIconStyle.SetString(TextIcon)
1533	s.Attachments.Normal = base.Padding(0, 1).MarginRight(1).Background(fgMuted).Foreground(fgBase)
1534	s.Attachments.Deleting = base.Padding(0, 1).Bold(true).Background(red).Foreground(fgBase)
1535
1536	// Pills styles
1537	s.Pills.Base = base.Padding(0, 1)
1538	s.Pills.Focused = base.Padding(0, 1).BorderStyle(lipgloss.RoundedBorder()).BorderForeground(bgOverlay)
1539	s.Pills.Blurred = base.Padding(0, 1).BorderStyle(lipgloss.HiddenBorder())
1540	s.Pills.QueueItemPrefix = s.Muted.SetString("  β€’")
1541	s.Pills.HelpKey = s.Muted
1542	s.Pills.HelpText = s.Subtle
1543	s.Pills.Area = base
1544	s.Pills.TodoSpinner = base.Foreground(greenDark)
1545
1546	return s
1547}
1548
1549func chromaStyle(style ansi.StylePrimitive) string {
1550	var s strings.Builder
1551
1552	if style.Color != nil {
1553		s.WriteString(*style.Color)
1554	}
1555	if style.BackgroundColor != nil {
1556		if s.Len() > 0 {
1557			s.WriteString(" ")
1558		}
1559		s.WriteString("bg:")
1560		s.WriteString(*style.BackgroundColor)
1561	}
1562	if style.Italic != nil && *style.Italic {
1563		if s.Len() > 0 {
1564			s.WriteString(" ")
1565		}
1566		s.WriteString("italic")
1567	}
1568	if style.Bold != nil && *style.Bold {
1569		if s.Len() > 0 {
1570			s.WriteString(" ")
1571		}
1572		s.WriteString("bold")
1573	}
1574	if style.Underline != nil && *style.Underline {
1575		if s.Len() > 0 {
1576			s.WriteString(" ")
1577		}
1578		s.WriteString("underline")
1579	}
1580
1581	return s.String()
1582}