styles.go

   1package styles
   2
   3import (
   4	"image/color"
   5
   6	"charm.land/bubbles/v2/filepicker"
   7	"charm.land/bubbles/v2/help"
   8	"charm.land/bubbles/v2/textarea"
   9	"charm.land/bubbles/v2/textinput"
  10	tea "charm.land/bubbletea/v2"
  11	"charm.land/glamour/v2/ansi"
  12	"charm.land/lipgloss/v2"
  13	"github.com/alecthomas/chroma/v2"
  14	"github.com/charmbracelet/crush/internal/tui/exp/diffview"
  15	"github.com/charmbracelet/x/exp/charmtone"
  16)
  17
  18const (
  19	CheckIcon   string = "✓"
  20	ErrorIcon   string = "×"
  21	WarningIcon string = "⚠"
  22	InfoIcon    string = "ⓘ"
  23	HintIcon    string = "∵"
  24	SpinnerIcon string = "..."
  25	LoadingIcon string = "⟳"
  26	ModelIcon   string = "◇"
  27
  28	ArrowRightIcon string = "→"
  29
  30	ToolPending string = "●"
  31	ToolSuccess string = "✓"
  32	ToolError   string = "×"
  33
  34	RadioOn  string = "◉"
  35	RadioOff string = "○"
  36
  37	BorderThin  string = "│"
  38	BorderThick string = "▌"
  39
  40	SectionSeparator string = "─"
  41
  42	TodoCompletedIcon  string = "✓"
  43	TodoPendingIcon    string = "•"
  44	TodoInProgressIcon string = "→"
  45
  46	ImageIcon string = "■"
  47	TextIcon  string = "≡"
  48)
  49
  50const (
  51	defaultMargin     = 2
  52	defaultListIndent = 2
  53)
  54
  55type Styles struct {
  56	WindowTooSmall lipgloss.Style
  57
  58	// Reusable text styles
  59	Base      lipgloss.Style
  60	Muted     lipgloss.Style
  61	HalfMuted lipgloss.Style
  62	Subtle    lipgloss.Style
  63
  64	// Tags
  65	TagBase  lipgloss.Style
  66	TagError lipgloss.Style
  67	TagInfo  lipgloss.Style
  68
  69	// Headers
  70	HeaderTool       lipgloss.Style
  71	HeaderToolNested lipgloss.Style
  72
  73	// Panels
  74	PanelMuted lipgloss.Style
  75	PanelBase  lipgloss.Style
  76
  77	// Line numbers for code blocks
  78	LineNumber lipgloss.Style
  79
  80	// Message borders
  81	FocusedMessageBorder lipgloss.Border
  82
  83	// Tool calls
  84	ToolCallPending   lipgloss.Style
  85	ToolCallError     lipgloss.Style
  86	ToolCallSuccess   lipgloss.Style
  87	ToolCallCancelled lipgloss.Style
  88	EarlyStateMessage lipgloss.Style
  89
  90	// Text selection
  91	TextSelection lipgloss.Style
  92
  93	// LSP and MCP status indicators
  94	ItemOfflineIcon lipgloss.Style
  95	ItemBusyIcon    lipgloss.Style
  96	ItemErrorIcon   lipgloss.Style
  97	ItemOnlineIcon  lipgloss.Style
  98
  99	// Markdown & Chroma
 100	Markdown      ansi.StyleConfig
 101	PlainMarkdown ansi.StyleConfig
 102
 103	// Inputs
 104	TextInput textinput.Styles
 105	TextArea  textarea.Styles
 106
 107	// Help
 108	Help help.Styles
 109
 110	// Diff
 111	Diff diffview.Style
 112
 113	// FilePicker
 114	FilePicker filepicker.Styles
 115
 116	// Buttons
 117	ButtonFocus lipgloss.Style
 118	ButtonBlur  lipgloss.Style
 119
 120	// Borders
 121	BorderFocus lipgloss.Style
 122	BorderBlur  lipgloss.Style
 123
 124	// Editor
 125	EditorPromptNormalFocused   lipgloss.Style
 126	EditorPromptNormalBlurred   lipgloss.Style
 127	EditorPromptYoloIconFocused lipgloss.Style
 128	EditorPromptYoloIconBlurred lipgloss.Style
 129	EditorPromptYoloDotsFocused lipgloss.Style
 130	EditorPromptYoloDotsBlurred lipgloss.Style
 131
 132	// Radio
 133	RadioOn  lipgloss.Style
 134	RadioOff lipgloss.Style
 135
 136	// Background
 137	Background color.Color
 138
 139	// Logo
 140	LogoFieldColor   color.Color
 141	LogoTitleColorA  color.Color
 142	LogoTitleColorB  color.Color
 143	LogoCharmColor   color.Color
 144	LogoVersionColor color.Color
 145
 146	// Colors - semantic colors for tool rendering.
 147	Primary       color.Color
 148	Secondary     color.Color
 149	Tertiary      color.Color
 150	BgBase        color.Color
 151	BgBaseLighter color.Color
 152	BgSubtle      color.Color
 153	BgOverlay     color.Color
 154	FgBase        color.Color
 155	FgMuted       color.Color
 156	FgHalfMuted   color.Color
 157	FgSubtle      color.Color
 158	Border        color.Color
 159	BorderColor   color.Color // Border focus color
 160	Warning       color.Color
 161	Info          color.Color
 162	White         color.Color
 163	BlueLight     color.Color
 164	Blue          color.Color
 165	BlueDark      color.Color
 166	Green         color.Color
 167	GreenDark     color.Color
 168	Red           color.Color
 169	RedDark       color.Color
 170	Yellow        color.Color
 171
 172	// Section Title
 173	Section struct {
 174		Title lipgloss.Style
 175		Line  lipgloss.Style
 176	}
 177
 178	// Initialize
 179	Initialize struct {
 180		Header  lipgloss.Style
 181		Content lipgloss.Style
 182		Accent  lipgloss.Style
 183	}
 184
 185	// LSP
 186	LSP struct {
 187		ErrorDiagnostic   lipgloss.Style
 188		WarningDiagnostic lipgloss.Style
 189		HintDiagnostic    lipgloss.Style
 190		InfoDiagnostic    lipgloss.Style
 191	}
 192
 193	// Files
 194	Files struct {
 195		Path      lipgloss.Style
 196		Additions lipgloss.Style
 197		Deletions lipgloss.Style
 198	}
 199
 200	// Chat
 201	Chat struct {
 202		// Message item styles
 203		Message struct {
 204			UserBlurred      lipgloss.Style
 205			UserFocused      lipgloss.Style
 206			AssistantBlurred lipgloss.Style
 207			AssistantFocused lipgloss.Style
 208			NoContent        lipgloss.Style
 209			Thinking         lipgloss.Style
 210			ErrorTag         lipgloss.Style
 211			ErrorTitle       lipgloss.Style
 212			ErrorDetails     lipgloss.Style
 213			ToolCallFocused  lipgloss.Style
 214			ToolCallCompact  lipgloss.Style
 215			ToolCallBlurred  lipgloss.Style
 216			SectionHeader    lipgloss.Style
 217
 218			// Thinking section styles
 219			ThinkingBox            lipgloss.Style // Background for thinking content
 220			ThinkingTruncationHint lipgloss.Style // "… (N lines hidden)" hint
 221			ThinkingFooterTitle    lipgloss.Style // "Thought for" text
 222			ThinkingFooterDuration lipgloss.Style // Duration value
 223		}
 224	}
 225
 226	// Tool - styles for tool call rendering
 227	Tool struct {
 228		// Icon styles with tool status
 229		IconPending   lipgloss.Style // Pending operation icon
 230		IconSuccess   lipgloss.Style // Successful operation icon
 231		IconError     lipgloss.Style // Error operation icon
 232		IconCancelled lipgloss.Style // Cancelled operation icon
 233
 234		// Tool name styles
 235		NameNormal lipgloss.Style // Normal tool name
 236		NameNested lipgloss.Style // Nested tool name
 237
 238		// Parameter list styles
 239		ParamMain lipgloss.Style // Main parameter
 240		ParamKey  lipgloss.Style // Parameter keys
 241
 242		// Content rendering styles
 243		ContentLine           lipgloss.Style // Individual content line with background and width
 244		ContentTruncation     lipgloss.Style // Truncation message "… (N lines)"
 245		ContentCodeLine       lipgloss.Style // Code line with background and width
 246		ContentCodeTruncation lipgloss.Style // Code truncation message with bgBase
 247		ContentCodeBg         color.Color    // Background color for syntax highlighting
 248		Body                  lipgloss.Style // Body content padding (PaddingLeft(2))
 249
 250		// Deprecated - kept for backward compatibility
 251		ContentBg         lipgloss.Style // Content background
 252		ContentText       lipgloss.Style // Content text
 253		ContentLineNumber lipgloss.Style // Line numbers in code
 254
 255		// State message styles
 256		StateWaiting   lipgloss.Style // "Waiting for tool response..."
 257		StateCancelled lipgloss.Style // "Canceled."
 258
 259		// Error styles
 260		ErrorTag     lipgloss.Style // ERROR tag
 261		ErrorMessage lipgloss.Style // Error message text
 262
 263		// Diff styles
 264		DiffTruncation lipgloss.Style // Diff truncation message with padding
 265
 266		// Multi-edit note styles
 267		NoteTag     lipgloss.Style // NOTE tag (yellow background)
 268		NoteMessage lipgloss.Style // Note message text
 269
 270		// Job header styles (for bash jobs)
 271		JobIconPending lipgloss.Style // Pending job icon (green dark)
 272		JobIconError   lipgloss.Style // Error job icon (red dark)
 273		JobIconSuccess lipgloss.Style // Success job icon (green)
 274		JobToolName    lipgloss.Style // Job tool name "Bash" (blue)
 275		JobAction      lipgloss.Style // Action text (Start, Output, Kill)
 276		JobPID         lipgloss.Style // PID text
 277		JobDescription lipgloss.Style // Description text
 278
 279		// Agent task styles
 280		AgentTaskTag lipgloss.Style // Agent task tag (blue background, bold)
 281		AgentPrompt  lipgloss.Style // Agent prompt text
 282
 283		// Agentic fetch styles
 284		AgenticFetchPromptTag lipgloss.Style // Agentic fetch prompt tag (green background, bold)
 285
 286		// Todo styles
 287		TodoRatio          lipgloss.Style // Todo ratio (e.g., "2/5")
 288		TodoCompletedIcon  lipgloss.Style // Completed todo icon
 289		TodoInProgressIcon lipgloss.Style // In-progress todo icon
 290		TodoPendingIcon    lipgloss.Style // Pending todo icon
 291	}
 292
 293	// Dialog styles
 294	Dialog struct {
 295		Title lipgloss.Style
 296		// View is the main content area style.
 297		View lipgloss.Style
 298		// HelpView is the line that contains the help.
 299		HelpView lipgloss.Style
 300		Help     struct {
 301			Ellipsis       lipgloss.Style
 302			ShortKey       lipgloss.Style
 303			ShortDesc      lipgloss.Style
 304			ShortSeparator lipgloss.Style
 305			FullKey        lipgloss.Style
 306			FullDesc       lipgloss.Style
 307			FullSeparator  lipgloss.Style
 308		}
 309		NormalItem   lipgloss.Style
 310		SelectedItem lipgloss.Style
 311		InputPrompt  lipgloss.Style
 312
 313		List lipgloss.Style
 314
 315		Commands struct{}
 316	}
 317
 318	// Status bar and help
 319	Status struct {
 320		Help lipgloss.Style
 321
 322		ErrorIndicator   lipgloss.Style
 323		WarnIndicator    lipgloss.Style
 324		InfoIndicator    lipgloss.Style
 325		UpdateIndicator  lipgloss.Style
 326		SuccessIndicator lipgloss.Style
 327
 328		ErrorMessage   lipgloss.Style
 329		WarnMessage    lipgloss.Style
 330		InfoMessage    lipgloss.Style
 331		UpdateMessage  lipgloss.Style
 332		SuccessMessage lipgloss.Style
 333	}
 334
 335	// Completions popup styles
 336	Completions struct {
 337		Normal  lipgloss.Style
 338		Focused lipgloss.Style
 339		Match   lipgloss.Style
 340	}
 341
 342	// Attachments styles
 343	Attachments struct {
 344		Normal   lipgloss.Style
 345		Image    lipgloss.Style
 346		Text     lipgloss.Style
 347		Deleting lipgloss.Style
 348	}
 349}
 350
 351// ChromaTheme converts the current markdown chroma styles to a chroma
 352// StyleEntries map.
 353func (s *Styles) ChromaTheme() chroma.StyleEntries {
 354	rules := s.Markdown.CodeBlock
 355
 356	return chroma.StyleEntries{
 357		chroma.Text:                chromaStyle(rules.Chroma.Text),
 358		chroma.Error:               chromaStyle(rules.Chroma.Error),
 359		chroma.Comment:             chromaStyle(rules.Chroma.Comment),
 360		chroma.CommentPreproc:      chromaStyle(rules.Chroma.CommentPreproc),
 361		chroma.Keyword:             chromaStyle(rules.Chroma.Keyword),
 362		chroma.KeywordReserved:     chromaStyle(rules.Chroma.KeywordReserved),
 363		chroma.KeywordNamespace:    chromaStyle(rules.Chroma.KeywordNamespace),
 364		chroma.KeywordType:         chromaStyle(rules.Chroma.KeywordType),
 365		chroma.Operator:            chromaStyle(rules.Chroma.Operator),
 366		chroma.Punctuation:         chromaStyle(rules.Chroma.Punctuation),
 367		chroma.Name:                chromaStyle(rules.Chroma.Name),
 368		chroma.NameBuiltin:         chromaStyle(rules.Chroma.NameBuiltin),
 369		chroma.NameTag:             chromaStyle(rules.Chroma.NameTag),
 370		chroma.NameAttribute:       chromaStyle(rules.Chroma.NameAttribute),
 371		chroma.NameClass:           chromaStyle(rules.Chroma.NameClass),
 372		chroma.NameConstant:        chromaStyle(rules.Chroma.NameConstant),
 373		chroma.NameDecorator:       chromaStyle(rules.Chroma.NameDecorator),
 374		chroma.NameException:       chromaStyle(rules.Chroma.NameException),
 375		chroma.NameFunction:        chromaStyle(rules.Chroma.NameFunction),
 376		chroma.NameOther:           chromaStyle(rules.Chroma.NameOther),
 377		chroma.Literal:             chromaStyle(rules.Chroma.Literal),
 378		chroma.LiteralNumber:       chromaStyle(rules.Chroma.LiteralNumber),
 379		chroma.LiteralDate:         chromaStyle(rules.Chroma.LiteralDate),
 380		chroma.LiteralString:       chromaStyle(rules.Chroma.LiteralString),
 381		chroma.LiteralStringEscape: chromaStyle(rules.Chroma.LiteralStringEscape),
 382		chroma.GenericDeleted:      chromaStyle(rules.Chroma.GenericDeleted),
 383		chroma.GenericEmph:         chromaStyle(rules.Chroma.GenericEmph),
 384		chroma.GenericInserted:     chromaStyle(rules.Chroma.GenericInserted),
 385		chroma.GenericStrong:       chromaStyle(rules.Chroma.GenericStrong),
 386		chroma.GenericSubheading:   chromaStyle(rules.Chroma.GenericSubheading),
 387		chroma.Background:          chromaStyle(rules.Chroma.Background),
 388	}
 389}
 390
 391// DialogHelpStyles returns the styles for dialog help.
 392func (s *Styles) DialogHelpStyles() help.Styles {
 393	return help.Styles(s.Dialog.Help)
 394}
 395
 396// DefaultStyles returns the default styles for the UI.
 397func DefaultStyles() Styles {
 398	var (
 399		primary   = charmtone.Charple
 400		secondary = charmtone.Dolly
 401		tertiary  = charmtone.Bok
 402		// accent    = charmtone.Zest
 403
 404		// Backgrounds
 405		bgBase        = charmtone.Pepper
 406		bgBaseLighter = charmtone.BBQ
 407		bgSubtle      = charmtone.Charcoal
 408		bgOverlay     = charmtone.Iron
 409
 410		// Foregrounds
 411		fgBase      = charmtone.Ash
 412		fgMuted     = charmtone.Squid
 413		fgHalfMuted = charmtone.Smoke
 414		fgSubtle    = charmtone.Oyster
 415		// fgSelected  = charmtone.Salt
 416
 417		// Borders
 418		border      = charmtone.Charcoal
 419		borderFocus = charmtone.Charple
 420
 421		// Status
 422		warning = charmtone.Zest
 423		info    = charmtone.Malibu
 424
 425		// Colors
 426		white = charmtone.Butter
 427
 428		blueLight = charmtone.Sardine
 429		blue      = charmtone.Malibu
 430		blueDark  = charmtone.Damson
 431
 432		// yellow = charmtone.Mustard
 433		yellow = charmtone.Mustard
 434		// citron = charmtone.Citron
 435
 436		green     = charmtone.Julep
 437		greenDark = charmtone.Guac
 438		// greenLight = charmtone.Bok
 439
 440		red     = charmtone.Coral
 441		redDark = charmtone.Sriracha
 442		// redLight = charmtone.Salmon
 443		// cherry   = charmtone.Cherry
 444	)
 445
 446	normalBorder := lipgloss.NormalBorder()
 447
 448	base := lipgloss.NewStyle().Foreground(fgBase)
 449
 450	s := Styles{}
 451
 452	s.Background = bgBase
 453
 454	// Populate color fields
 455	s.Primary = primary
 456	s.Secondary = secondary
 457	s.Tertiary = tertiary
 458	s.BgBase = bgBase
 459	s.BgBaseLighter = bgBaseLighter
 460	s.BgSubtle = bgSubtle
 461	s.BgOverlay = bgOverlay
 462	s.FgBase = fgBase
 463	s.FgMuted = fgMuted
 464	s.FgHalfMuted = fgHalfMuted
 465	s.FgSubtle = fgSubtle
 466	s.Border = border
 467	s.BorderColor = borderFocus
 468	s.Warning = warning
 469	s.Info = info
 470	s.White = white
 471	s.BlueLight = blueLight
 472	s.Blue = blue
 473	s.BlueDark = blueDark
 474	s.Green = green
 475	s.GreenDark = greenDark
 476	s.Red = red
 477	s.RedDark = redDark
 478	s.Yellow = yellow
 479
 480	s.TextInput = textinput.Styles{
 481		Focused: textinput.StyleState{
 482			Text:        base,
 483			Placeholder: base.Foreground(fgSubtle),
 484			Prompt:      base.Foreground(tertiary),
 485			Suggestion:  base.Foreground(fgSubtle),
 486		},
 487		Blurred: textinput.StyleState{
 488			Text:        base.Foreground(fgMuted),
 489			Placeholder: base.Foreground(fgSubtle),
 490			Prompt:      base.Foreground(fgMuted),
 491			Suggestion:  base.Foreground(fgSubtle),
 492		},
 493		Cursor: textinput.CursorStyle{
 494			Color: secondary,
 495			Shape: tea.CursorBlock,
 496			Blink: true,
 497		},
 498	}
 499
 500	s.TextArea = textarea.Styles{
 501		Focused: textarea.StyleState{
 502			Base:             base,
 503			Text:             base,
 504			LineNumber:       base.Foreground(fgSubtle),
 505			CursorLine:       base,
 506			CursorLineNumber: base.Foreground(fgSubtle),
 507			Placeholder:      base.Foreground(fgSubtle),
 508			Prompt:           base.Foreground(tertiary),
 509		},
 510		Blurred: textarea.StyleState{
 511			Base:             base,
 512			Text:             base.Foreground(fgMuted),
 513			LineNumber:       base.Foreground(fgMuted),
 514			CursorLine:       base,
 515			CursorLineNumber: base.Foreground(fgMuted),
 516			Placeholder:      base.Foreground(fgSubtle),
 517			Prompt:           base.Foreground(fgMuted),
 518		},
 519		Cursor: textarea.CursorStyle{
 520			Color: secondary,
 521			Shape: tea.CursorBlock,
 522			Blink: true,
 523		},
 524	}
 525
 526	s.Markdown = ansi.StyleConfig{
 527		Document: ansi.StyleBlock{
 528			StylePrimitive: ansi.StylePrimitive{
 529				// BlockPrefix: "\n",
 530				// BlockSuffix: "\n",
 531				Color: stringPtr(charmtone.Smoke.Hex()),
 532			},
 533			// Margin: uintPtr(defaultMargin),
 534		},
 535		BlockQuote: ansi.StyleBlock{
 536			StylePrimitive: ansi.StylePrimitive{},
 537			Indent:         uintPtr(1),
 538			IndentToken:    stringPtr("│ "),
 539		},
 540		List: ansi.StyleList{
 541			LevelIndent: defaultListIndent,
 542		},
 543		Heading: ansi.StyleBlock{
 544			StylePrimitive: ansi.StylePrimitive{
 545				BlockSuffix: "\n",
 546				Color:       stringPtr(charmtone.Malibu.Hex()),
 547				Bold:        boolPtr(true),
 548			},
 549		},
 550		H1: ansi.StyleBlock{
 551			StylePrimitive: ansi.StylePrimitive{
 552				Prefix:          " ",
 553				Suffix:          " ",
 554				Color:           stringPtr(charmtone.Zest.Hex()),
 555				BackgroundColor: stringPtr(charmtone.Charple.Hex()),
 556				Bold:            boolPtr(true),
 557			},
 558		},
 559		H2: ansi.StyleBlock{
 560			StylePrimitive: ansi.StylePrimitive{
 561				Prefix: "## ",
 562			},
 563		},
 564		H3: ansi.StyleBlock{
 565			StylePrimitive: ansi.StylePrimitive{
 566				Prefix: "### ",
 567			},
 568		},
 569		H4: ansi.StyleBlock{
 570			StylePrimitive: ansi.StylePrimitive{
 571				Prefix: "#### ",
 572			},
 573		},
 574		H5: ansi.StyleBlock{
 575			StylePrimitive: ansi.StylePrimitive{
 576				Prefix: "##### ",
 577			},
 578		},
 579		H6: ansi.StyleBlock{
 580			StylePrimitive: ansi.StylePrimitive{
 581				Prefix: "###### ",
 582				Color:  stringPtr(charmtone.Guac.Hex()),
 583				Bold:   boolPtr(false),
 584			},
 585		},
 586		Strikethrough: ansi.StylePrimitive{
 587			CrossedOut: boolPtr(true),
 588		},
 589		Emph: ansi.StylePrimitive{
 590			Italic: boolPtr(true),
 591		},
 592		Strong: ansi.StylePrimitive{
 593			Bold: boolPtr(true),
 594		},
 595		HorizontalRule: ansi.StylePrimitive{
 596			Color:  stringPtr(charmtone.Charcoal.Hex()),
 597			Format: "\n--------\n",
 598		},
 599		Item: ansi.StylePrimitive{
 600			BlockPrefix: "• ",
 601		},
 602		Enumeration: ansi.StylePrimitive{
 603			BlockPrefix: ". ",
 604		},
 605		Task: ansi.StyleTask{
 606			StylePrimitive: ansi.StylePrimitive{},
 607			Ticked:         "[✓] ",
 608			Unticked:       "[ ] ",
 609		},
 610		Link: ansi.StylePrimitive{
 611			Color:     stringPtr(charmtone.Zinc.Hex()),
 612			Underline: boolPtr(true),
 613		},
 614		LinkText: ansi.StylePrimitive{
 615			Color: stringPtr(charmtone.Guac.Hex()),
 616			Bold:  boolPtr(true),
 617		},
 618		Image: ansi.StylePrimitive{
 619			Color:     stringPtr(charmtone.Cheeky.Hex()),
 620			Underline: boolPtr(true),
 621		},
 622		ImageText: ansi.StylePrimitive{
 623			Color:  stringPtr(charmtone.Squid.Hex()),
 624			Format: "Image: {{.text}} →",
 625		},
 626		Code: ansi.StyleBlock{
 627			StylePrimitive: ansi.StylePrimitive{
 628				Prefix:          " ",
 629				Suffix:          " ",
 630				Color:           stringPtr(charmtone.Coral.Hex()),
 631				BackgroundColor: stringPtr(charmtone.Charcoal.Hex()),
 632			},
 633		},
 634		CodeBlock: ansi.StyleCodeBlock{
 635			StyleBlock: ansi.StyleBlock{
 636				StylePrimitive: ansi.StylePrimitive{
 637					Color: stringPtr(charmtone.Charcoal.Hex()),
 638				},
 639				Margin: uintPtr(defaultMargin),
 640			},
 641			Chroma: &ansi.Chroma{
 642				Text: ansi.StylePrimitive{
 643					Color: stringPtr(charmtone.Smoke.Hex()),
 644				},
 645				Error: ansi.StylePrimitive{
 646					Color:           stringPtr(charmtone.Butter.Hex()),
 647					BackgroundColor: stringPtr(charmtone.Sriracha.Hex()),
 648				},
 649				Comment: ansi.StylePrimitive{
 650					Color: stringPtr(charmtone.Oyster.Hex()),
 651				},
 652				CommentPreproc: ansi.StylePrimitive{
 653					Color: stringPtr(charmtone.Bengal.Hex()),
 654				},
 655				Keyword: ansi.StylePrimitive{
 656					Color: stringPtr(charmtone.Malibu.Hex()),
 657				},
 658				KeywordReserved: ansi.StylePrimitive{
 659					Color: stringPtr(charmtone.Pony.Hex()),
 660				},
 661				KeywordNamespace: ansi.StylePrimitive{
 662					Color: stringPtr(charmtone.Pony.Hex()),
 663				},
 664				KeywordType: ansi.StylePrimitive{
 665					Color: stringPtr(charmtone.Guppy.Hex()),
 666				},
 667				Operator: ansi.StylePrimitive{
 668					Color: stringPtr(charmtone.Salmon.Hex()),
 669				},
 670				Punctuation: ansi.StylePrimitive{
 671					Color: stringPtr(charmtone.Zest.Hex()),
 672				},
 673				Name: ansi.StylePrimitive{
 674					Color: stringPtr(charmtone.Smoke.Hex()),
 675				},
 676				NameBuiltin: ansi.StylePrimitive{
 677					Color: stringPtr(charmtone.Cheeky.Hex()),
 678				},
 679				NameTag: ansi.StylePrimitive{
 680					Color: stringPtr(charmtone.Mauve.Hex()),
 681				},
 682				NameAttribute: ansi.StylePrimitive{
 683					Color: stringPtr(charmtone.Hazy.Hex()),
 684				},
 685				NameClass: ansi.StylePrimitive{
 686					Color:     stringPtr(charmtone.Salt.Hex()),
 687					Underline: boolPtr(true),
 688					Bold:      boolPtr(true),
 689				},
 690				NameDecorator: ansi.StylePrimitive{
 691					Color: stringPtr(charmtone.Citron.Hex()),
 692				},
 693				NameFunction: ansi.StylePrimitive{
 694					Color: stringPtr(charmtone.Guac.Hex()),
 695				},
 696				LiteralNumber: ansi.StylePrimitive{
 697					Color: stringPtr(charmtone.Julep.Hex()),
 698				},
 699				LiteralString: ansi.StylePrimitive{
 700					Color: stringPtr(charmtone.Cumin.Hex()),
 701				},
 702				LiteralStringEscape: ansi.StylePrimitive{
 703					Color: stringPtr(charmtone.Bok.Hex()),
 704				},
 705				GenericDeleted: ansi.StylePrimitive{
 706					Color: stringPtr(charmtone.Coral.Hex()),
 707				},
 708				GenericEmph: ansi.StylePrimitive{
 709					Italic: boolPtr(true),
 710				},
 711				GenericInserted: ansi.StylePrimitive{
 712					Color: stringPtr(charmtone.Guac.Hex()),
 713				},
 714				GenericStrong: ansi.StylePrimitive{
 715					Bold: boolPtr(true),
 716				},
 717				GenericSubheading: ansi.StylePrimitive{
 718					Color: stringPtr(charmtone.Squid.Hex()),
 719				},
 720				Background: ansi.StylePrimitive{
 721					BackgroundColor: stringPtr(charmtone.Charcoal.Hex()),
 722				},
 723			},
 724		},
 725		Table: ansi.StyleTable{
 726			StyleBlock: ansi.StyleBlock{
 727				StylePrimitive: ansi.StylePrimitive{},
 728			},
 729		},
 730		DefinitionDescription: ansi.StylePrimitive{
 731			BlockPrefix: "\n ",
 732		},
 733	}
 734
 735	// PlainMarkdown style - muted colors on subtle background for thinking content.
 736	plainBg := stringPtr(bgBaseLighter.Hex())
 737	plainFg := stringPtr(fgMuted.Hex())
 738	s.PlainMarkdown = ansi.StyleConfig{
 739		Document: ansi.StyleBlock{
 740			StylePrimitive: ansi.StylePrimitive{
 741				Color:           plainFg,
 742				BackgroundColor: plainBg,
 743			},
 744		},
 745		BlockQuote: ansi.StyleBlock{
 746			StylePrimitive: ansi.StylePrimitive{
 747				Color:           plainFg,
 748				BackgroundColor: plainBg,
 749			},
 750			Indent:      uintPtr(1),
 751			IndentToken: stringPtr("│ "),
 752		},
 753		List: ansi.StyleList{
 754			LevelIndent: defaultListIndent,
 755		},
 756		Heading: ansi.StyleBlock{
 757			StylePrimitive: ansi.StylePrimitive{
 758				BlockSuffix:     "\n",
 759				Bold:            boolPtr(true),
 760				Color:           plainFg,
 761				BackgroundColor: plainBg,
 762			},
 763		},
 764		H1: ansi.StyleBlock{
 765			StylePrimitive: ansi.StylePrimitive{
 766				Prefix:          " ",
 767				Suffix:          " ",
 768				Bold:            boolPtr(true),
 769				Color:           plainFg,
 770				BackgroundColor: plainBg,
 771			},
 772		},
 773		H2: ansi.StyleBlock{
 774			StylePrimitive: ansi.StylePrimitive{
 775				Prefix:          "## ",
 776				Color:           plainFg,
 777				BackgroundColor: plainBg,
 778			},
 779		},
 780		H3: ansi.StyleBlock{
 781			StylePrimitive: ansi.StylePrimitive{
 782				Prefix:          "### ",
 783				Color:           plainFg,
 784				BackgroundColor: plainBg,
 785			},
 786		},
 787		H4: ansi.StyleBlock{
 788			StylePrimitive: ansi.StylePrimitive{
 789				Prefix:          "#### ",
 790				Color:           plainFg,
 791				BackgroundColor: plainBg,
 792			},
 793		},
 794		H5: ansi.StyleBlock{
 795			StylePrimitive: ansi.StylePrimitive{
 796				Prefix:          "##### ",
 797				Color:           plainFg,
 798				BackgroundColor: plainBg,
 799			},
 800		},
 801		H6: ansi.StyleBlock{
 802			StylePrimitive: ansi.StylePrimitive{
 803				Prefix:          "###### ",
 804				Color:           plainFg,
 805				BackgroundColor: plainBg,
 806			},
 807		},
 808		Strikethrough: ansi.StylePrimitive{
 809			CrossedOut:      boolPtr(true),
 810			Color:           plainFg,
 811			BackgroundColor: plainBg,
 812		},
 813		Emph: ansi.StylePrimitive{
 814			Italic:          boolPtr(true),
 815			Color:           plainFg,
 816			BackgroundColor: plainBg,
 817		},
 818		Strong: ansi.StylePrimitive{
 819			Bold:            boolPtr(true),
 820			Color:           plainFg,
 821			BackgroundColor: plainBg,
 822		},
 823		HorizontalRule: ansi.StylePrimitive{
 824			Format:          "\n--------\n",
 825			Color:           plainFg,
 826			BackgroundColor: plainBg,
 827		},
 828		Item: ansi.StylePrimitive{
 829			BlockPrefix:     "• ",
 830			Color:           plainFg,
 831			BackgroundColor: plainBg,
 832		},
 833		Enumeration: ansi.StylePrimitive{
 834			BlockPrefix:     ". ",
 835			Color:           plainFg,
 836			BackgroundColor: plainBg,
 837		},
 838		Task: ansi.StyleTask{
 839			StylePrimitive: ansi.StylePrimitive{
 840				Color:           plainFg,
 841				BackgroundColor: plainBg,
 842			},
 843			Ticked:   "[✓] ",
 844			Unticked: "[ ] ",
 845		},
 846		Link: ansi.StylePrimitive{
 847			Underline:       boolPtr(true),
 848			Color:           plainFg,
 849			BackgroundColor: plainBg,
 850		},
 851		LinkText: ansi.StylePrimitive{
 852			Bold:            boolPtr(true),
 853			Color:           plainFg,
 854			BackgroundColor: plainBg,
 855		},
 856		Image: ansi.StylePrimitive{
 857			Underline:       boolPtr(true),
 858			Color:           plainFg,
 859			BackgroundColor: plainBg,
 860		},
 861		ImageText: ansi.StylePrimitive{
 862			Format:          "Image: {{.text}} →",
 863			Color:           plainFg,
 864			BackgroundColor: plainBg,
 865		},
 866		Code: ansi.StyleBlock{
 867			StylePrimitive: ansi.StylePrimitive{
 868				Prefix:          " ",
 869				Suffix:          " ",
 870				Color:           plainFg,
 871				BackgroundColor: plainBg,
 872			},
 873		},
 874		CodeBlock: ansi.StyleCodeBlock{
 875			StyleBlock: ansi.StyleBlock{
 876				StylePrimitive: ansi.StylePrimitive{
 877					Color:           plainFg,
 878					BackgroundColor: plainBg,
 879				},
 880				Margin: uintPtr(defaultMargin),
 881			},
 882		},
 883		Table: ansi.StyleTable{
 884			StyleBlock: ansi.StyleBlock{
 885				StylePrimitive: ansi.StylePrimitive{
 886					Color:           plainFg,
 887					BackgroundColor: plainBg,
 888				},
 889			},
 890		},
 891		DefinitionDescription: ansi.StylePrimitive{
 892			BlockPrefix:     "\n ",
 893			Color:           plainFg,
 894			BackgroundColor: plainBg,
 895		},
 896	}
 897
 898	s.Help = help.Styles{
 899		ShortKey:       base.Foreground(fgMuted),
 900		ShortDesc:      base.Foreground(fgSubtle),
 901		ShortSeparator: base.Foreground(border),
 902		Ellipsis:       base.Foreground(border),
 903		FullKey:        base.Foreground(fgMuted),
 904		FullDesc:       base.Foreground(fgSubtle),
 905		FullSeparator:  base.Foreground(border),
 906	}
 907
 908	s.Diff = diffview.Style{
 909		DividerLine: diffview.LineStyle{
 910			LineNumber: lipgloss.NewStyle().
 911				Foreground(fgHalfMuted).
 912				Background(bgBaseLighter),
 913			Code: lipgloss.NewStyle().
 914				Foreground(fgHalfMuted).
 915				Background(bgBaseLighter),
 916		},
 917		MissingLine: diffview.LineStyle{
 918			LineNumber: lipgloss.NewStyle().
 919				Background(bgBaseLighter),
 920			Code: lipgloss.NewStyle().
 921				Background(bgBaseLighter),
 922		},
 923		EqualLine: diffview.LineStyle{
 924			LineNumber: lipgloss.NewStyle().
 925				Foreground(fgMuted).
 926				Background(bgBase),
 927			Code: lipgloss.NewStyle().
 928				Foreground(fgMuted).
 929				Background(bgBase),
 930		},
 931		InsertLine: diffview.LineStyle{
 932			LineNumber: lipgloss.NewStyle().
 933				Foreground(lipgloss.Color("#629657")).
 934				Background(lipgloss.Color("#2b322a")),
 935			Symbol: lipgloss.NewStyle().
 936				Foreground(lipgloss.Color("#629657")).
 937				Background(lipgloss.Color("#323931")),
 938			Code: lipgloss.NewStyle().
 939				Background(lipgloss.Color("#323931")),
 940		},
 941		DeleteLine: diffview.LineStyle{
 942			LineNumber: lipgloss.NewStyle().
 943				Foreground(lipgloss.Color("#a45c59")).
 944				Background(lipgloss.Color("#312929")),
 945			Symbol: lipgloss.NewStyle().
 946				Foreground(lipgloss.Color("#a45c59")).
 947				Background(lipgloss.Color("#383030")),
 948			Code: lipgloss.NewStyle().
 949				Background(lipgloss.Color("#383030")),
 950		},
 951	}
 952
 953	s.FilePicker = filepicker.Styles{
 954		DisabledCursor:   base.Foreground(fgMuted),
 955		Cursor:           base.Foreground(fgBase),
 956		Symlink:          base.Foreground(fgSubtle),
 957		Directory:        base.Foreground(primary),
 958		File:             base.Foreground(fgBase),
 959		DisabledFile:     base.Foreground(fgMuted),
 960		DisabledSelected: base.Background(bgOverlay).Foreground(fgMuted),
 961		Permission:       base.Foreground(fgMuted),
 962		Selected:         base.Background(primary).Foreground(fgBase),
 963		FileSize:         base.Foreground(fgMuted),
 964		EmptyDirectory:   base.Foreground(fgMuted).PaddingLeft(2).SetString("Empty directory"),
 965	}
 966
 967	// borders
 968	s.FocusedMessageBorder = lipgloss.Border{Left: BorderThick}
 969
 970	// text presets
 971	s.Base = lipgloss.NewStyle().Foreground(fgBase)
 972	s.Muted = lipgloss.NewStyle().Foreground(fgMuted)
 973	s.HalfMuted = lipgloss.NewStyle().Foreground(fgHalfMuted)
 974	s.Subtle = lipgloss.NewStyle().Foreground(fgSubtle)
 975
 976	s.WindowTooSmall = s.Muted
 977
 978	// tag presets
 979	s.TagBase = lipgloss.NewStyle().Padding(0, 1).Foreground(white)
 980	s.TagError = s.TagBase.Background(redDark)
 981	s.TagInfo = s.TagBase.Background(blueLight)
 982
 983	// headers
 984	s.HeaderTool = lipgloss.NewStyle().Foreground(blue)
 985	s.HeaderToolNested = lipgloss.NewStyle().Foreground(fgHalfMuted)
 986
 987	// panels
 988	s.PanelMuted = s.Muted.Background(bgBaseLighter)
 989	s.PanelBase = lipgloss.NewStyle().Background(bgBase)
 990
 991	// code line number
 992	s.LineNumber = lipgloss.NewStyle().Foreground(fgMuted).Background(bgBase).PaddingRight(1).PaddingLeft(1)
 993
 994	// Tool calls
 995	s.ToolCallPending = lipgloss.NewStyle().Foreground(greenDark).SetString(ToolPending)
 996	s.ToolCallError = lipgloss.NewStyle().Foreground(redDark).SetString(ToolError)
 997	s.ToolCallSuccess = lipgloss.NewStyle().Foreground(green).SetString(ToolSuccess)
 998	// Cancelled uses muted tone but same glyph as pending
 999	s.ToolCallCancelled = s.Muted.SetString(ToolPending)
1000	s.EarlyStateMessage = s.Subtle.PaddingLeft(2)
1001
1002	// Tool rendering styles
1003	s.Tool.IconPending = base.Foreground(greenDark).SetString(ToolPending)
1004	s.Tool.IconSuccess = base.Foreground(green).SetString(ToolSuccess)
1005	s.Tool.IconError = base.Foreground(redDark).SetString(ToolError)
1006	s.Tool.IconCancelled = s.Muted.SetString(ToolPending)
1007
1008	s.Tool.NameNormal = base.Foreground(blue)
1009	s.Tool.NameNested = base.Foreground(fgHalfMuted)
1010
1011	s.Tool.ParamMain = s.Subtle
1012	s.Tool.ParamKey = s.Subtle
1013
1014	// Content rendering - prepared styles that accept width parameter
1015	s.Tool.ContentLine = s.Muted.Background(bgBaseLighter)
1016	s.Tool.ContentTruncation = s.Muted.Background(bgBaseLighter)
1017	s.Tool.ContentCodeLine = s.Base.Background(bgBase)
1018	s.Tool.ContentCodeTruncation = s.Muted.Background(bgBase).PaddingLeft(2)
1019	s.Tool.ContentCodeBg = bgBase
1020	s.Tool.Body = base.PaddingLeft(2)
1021
1022	// Deprecated - kept for backward compatibility
1023	s.Tool.ContentBg = s.Muted.Background(bgBaseLighter)
1024	s.Tool.ContentText = s.Muted
1025	s.Tool.ContentLineNumber = base.Foreground(fgMuted).Background(bgBase).PaddingRight(1).PaddingLeft(1)
1026
1027	s.Tool.StateWaiting = base.Foreground(fgSubtle)
1028	s.Tool.StateCancelled = base.Foreground(fgSubtle)
1029
1030	s.Tool.ErrorTag = base.Padding(0, 1).Background(red).Foreground(white)
1031	s.Tool.ErrorMessage = base.Foreground(fgHalfMuted)
1032
1033	// Diff and multi-edit styles
1034	s.Tool.DiffTruncation = s.Muted.Background(bgBaseLighter).PaddingLeft(2)
1035	s.Tool.NoteTag = base.Padding(0, 1).Background(info).Foreground(white)
1036	s.Tool.NoteMessage = base.Foreground(fgHalfMuted)
1037
1038	// Job header styles
1039	s.Tool.JobIconPending = base.Foreground(greenDark)
1040	s.Tool.JobIconError = base.Foreground(redDark)
1041	s.Tool.JobIconSuccess = base.Foreground(green)
1042	s.Tool.JobToolName = base.Foreground(blue)
1043	s.Tool.JobAction = base.Foreground(blueDark)
1044	s.Tool.JobPID = s.Muted
1045	s.Tool.JobDescription = s.Subtle
1046
1047	// Agent task styles
1048	s.Tool.AgentTaskTag = base.Bold(true).Padding(0, 1).MarginLeft(2).Background(blueLight).Foreground(white)
1049	s.Tool.AgentPrompt = s.Muted
1050
1051	// Agentic fetch styles
1052	s.Tool.AgenticFetchPromptTag = base.Bold(true).Padding(0, 1).MarginLeft(2).Background(green).Foreground(border)
1053
1054	// Todo styles
1055	s.Tool.TodoRatio = base.Foreground(blueDark)
1056	s.Tool.TodoCompletedIcon = base.Foreground(green)
1057	s.Tool.TodoInProgressIcon = base.Foreground(greenDark)
1058	s.Tool.TodoPendingIcon = base.Foreground(fgMuted)
1059
1060	// Buttons
1061	s.ButtonFocus = lipgloss.NewStyle().Foreground(white).Background(secondary)
1062	s.ButtonBlur = s.Base.Background(bgSubtle)
1063
1064	// Borders
1065	s.BorderFocus = lipgloss.NewStyle().BorderForeground(borderFocus).Border(lipgloss.RoundedBorder()).Padding(1, 2)
1066
1067	// Editor
1068	s.EditorPromptNormalFocused = lipgloss.NewStyle().Foreground(greenDark).SetString("::: ")
1069	s.EditorPromptNormalBlurred = s.EditorPromptNormalFocused.Foreground(fgMuted)
1070	s.EditorPromptYoloIconFocused = lipgloss.NewStyle().MarginRight(1).Foreground(charmtone.Oyster).Background(charmtone.Citron).Bold(true).SetString(" ! ")
1071	s.EditorPromptYoloIconBlurred = s.EditorPromptYoloIconFocused.Foreground(charmtone.Pepper).Background(charmtone.Squid)
1072	s.EditorPromptYoloDotsFocused = lipgloss.NewStyle().MarginRight(1).Foreground(charmtone.Zest).SetString(":::")
1073	s.EditorPromptYoloDotsBlurred = s.EditorPromptYoloDotsFocused.Foreground(charmtone.Squid)
1074
1075	s.RadioOn = s.HalfMuted.SetString(RadioOn)
1076	s.RadioOff = s.HalfMuted.SetString(RadioOff)
1077
1078	// Logo colors
1079	s.LogoFieldColor = primary
1080	s.LogoTitleColorA = secondary
1081	s.LogoTitleColorB = primary
1082	s.LogoCharmColor = secondary
1083	s.LogoVersionColor = primary
1084
1085	// Section
1086	s.Section.Title = s.Subtle
1087	s.Section.Line = s.Base.Foreground(charmtone.Charcoal)
1088
1089	// Initialize
1090	s.Initialize.Header = s.Base
1091	s.Initialize.Content = s.Muted
1092	s.Initialize.Accent = s.Base.Foreground(greenDark)
1093
1094	// LSP and MCP status.
1095	s.ItemOfflineIcon = lipgloss.NewStyle().Foreground(charmtone.Squid).SetString("●")
1096	s.ItemBusyIcon = s.ItemOfflineIcon.Foreground(charmtone.Citron)
1097	s.ItemErrorIcon = s.ItemOfflineIcon.Foreground(charmtone.Coral)
1098	s.ItemOnlineIcon = s.ItemOfflineIcon.Foreground(charmtone.Guac)
1099
1100	// LSP
1101	s.LSP.ErrorDiagnostic = s.Base.Foreground(redDark)
1102	s.LSP.WarningDiagnostic = s.Base.Foreground(warning)
1103	s.LSP.HintDiagnostic = s.Base.Foreground(fgHalfMuted)
1104	s.LSP.InfoDiagnostic = s.Base.Foreground(info)
1105
1106	// Files
1107	s.Files.Path = s.Muted
1108	s.Files.Additions = s.Base.Foreground(greenDark)
1109	s.Files.Deletions = s.Base.Foreground(redDark)
1110
1111	// Chat
1112	messageFocussedBorder := lipgloss.Border{
1113		Left: "▌",
1114	}
1115
1116	s.Chat.Message.NoContent = lipgloss.NewStyle().Foreground(fgBase)
1117	s.Chat.Message.UserBlurred = s.Chat.Message.NoContent.PaddingLeft(1).BorderLeft(true).
1118		BorderForeground(primary).BorderStyle(normalBorder)
1119	s.Chat.Message.UserFocused = s.Chat.Message.NoContent.PaddingLeft(1).BorderLeft(true).
1120		BorderForeground(primary).BorderStyle(messageFocussedBorder)
1121	s.Chat.Message.AssistantBlurred = s.Chat.Message.NoContent.PaddingLeft(2)
1122	s.Chat.Message.AssistantFocused = s.Chat.Message.NoContent.PaddingLeft(1).BorderLeft(true).
1123		BorderForeground(greenDark).BorderStyle(messageFocussedBorder)
1124	s.Chat.Message.Thinking = lipgloss.NewStyle().MaxHeight(10)
1125	s.Chat.Message.ErrorTag = lipgloss.NewStyle().Padding(0, 1).
1126		Background(red).Foreground(white)
1127	s.Chat.Message.ErrorTitle = lipgloss.NewStyle().Foreground(fgHalfMuted)
1128	s.Chat.Message.ErrorDetails = lipgloss.NewStyle().Foreground(fgSubtle)
1129
1130	// Message item styles
1131	s.Chat.Message.ToolCallFocused = s.Muted.PaddingLeft(1).
1132		BorderStyle(messageFocussedBorder).
1133		BorderLeft(true).
1134		BorderForeground(greenDark)
1135	s.Chat.Message.ToolCallBlurred = s.Muted.PaddingLeft(2)
1136	// No padding or border for compact tool calls within messages
1137	s.Chat.Message.ToolCallCompact = s.Muted
1138	s.Chat.Message.SectionHeader = s.Base.PaddingLeft(2)
1139
1140	// Thinking section styles
1141	s.Chat.Message.ThinkingBox = s.Subtle.Background(bgBaseLighter)
1142	s.Chat.Message.ThinkingTruncationHint = s.Muted
1143	s.Chat.Message.ThinkingFooterTitle = s.Muted
1144	s.Chat.Message.ThinkingFooterDuration = s.Subtle
1145
1146	// Text selection.
1147	s.TextSelection = lipgloss.NewStyle().Foreground(charmtone.Salt).Background(charmtone.Charple)
1148
1149	// Dialog styles
1150	s.Dialog.Title = base.Padding(0, 1).Foreground(primary)
1151	s.Dialog.View = base.Border(lipgloss.RoundedBorder()).BorderForeground(borderFocus)
1152	s.Dialog.HelpView = base.Padding(0, 1).AlignHorizontal(lipgloss.Left)
1153	s.Dialog.Help.ShortKey = base.Foreground(fgMuted)
1154	s.Dialog.Help.ShortDesc = base.Foreground(fgSubtle)
1155	s.Dialog.Help.ShortSeparator = base.Foreground(border)
1156	s.Dialog.Help.Ellipsis = base.Foreground(border)
1157	s.Dialog.Help.FullKey = base.Foreground(fgMuted)
1158	s.Dialog.Help.FullDesc = base.Foreground(fgSubtle)
1159	s.Dialog.Help.FullSeparator = base.Foreground(border)
1160	s.Dialog.NormalItem = base.Padding(0, 1).Foreground(fgBase)
1161	s.Dialog.SelectedItem = base.Padding(0, 1).Background(primary).Foreground(fgBase)
1162	s.Dialog.InputPrompt = base.Margin(1, 1)
1163
1164	s.Dialog.List = base.Margin(0, 0, 1, 0)
1165
1166	s.Status.Help = lipgloss.NewStyle().Padding(0, 1)
1167	s.Status.SuccessIndicator = base.Foreground(bgSubtle).Background(green).Padding(0, 1).Bold(true).SetString("OKAY!")
1168	s.Status.InfoIndicator = s.Status.SuccessIndicator
1169	s.Status.UpdateIndicator = s.Status.SuccessIndicator.SetString("HEY!")
1170	s.Status.WarnIndicator = s.Status.SuccessIndicator.Foreground(bgOverlay).Background(yellow).SetString("WARNING")
1171	s.Status.ErrorIndicator = s.Status.SuccessIndicator.Foreground(bgBase).Background(red).SetString("ERROR")
1172	s.Status.SuccessMessage = base.Foreground(bgSubtle).Background(greenDark).Padding(0, 1)
1173	s.Status.InfoMessage = s.Status.SuccessMessage
1174	s.Status.UpdateMessage = s.Status.SuccessMessage
1175	s.Status.WarnMessage = s.Status.SuccessMessage.Foreground(bgOverlay).Background(warning)
1176	s.Status.ErrorMessage = s.Status.SuccessMessage.Foreground(white).Background(redDark)
1177
1178	// Completions styles
1179	s.Completions.Normal = base.Background(bgSubtle).Foreground(fgBase)
1180	s.Completions.Focused = base.Background(primary).Foreground(white)
1181	s.Completions.Match = base.Underline(true)
1182
1183	// Attachments styles
1184	attachmentIconStyle := base.Foreground(bgSubtle).Background(green).Padding(0, 1)
1185	s.Attachments.Image = attachmentIconStyle.SetString(ImageIcon)
1186	s.Attachments.Text = attachmentIconStyle.SetString(TextIcon)
1187	s.Attachments.Normal = base.Padding(0, 1).MarginRight(1).Background(fgMuted).Foreground(fgBase)
1188	s.Attachments.Deleting = base.Padding(0, 1).Bold(true).Background(red).Foreground(fgBase)
1189
1190	return s
1191}
1192
1193// Helper functions for style pointers
1194func boolPtr(b bool) *bool       { return &b }
1195func stringPtr(s string) *string { return &s }
1196func uintPtr(u uint) *uint       { return &u }
1197func chromaStyle(style ansi.StylePrimitive) string {
1198	var s string
1199
1200	if style.Color != nil {
1201		s = *style.Color
1202	}
1203	if style.BackgroundColor != nil {
1204		if s != "" {
1205			s += " "
1206		}
1207		s += "bg:" + *style.BackgroundColor
1208	}
1209	if style.Italic != nil && *style.Italic {
1210		if s != "" {
1211			s += " "
1212		}
1213		s += "italic"
1214	}
1215	if style.Bold != nil && *style.Bold {
1216		if s != "" {
1217			s += " "
1218		}
1219		s += "bold"
1220	}
1221	if style.Underline != nil && *style.Underline {
1222		if s != "" {
1223			s += " "
1224		}
1225		s += "underline"
1226	}
1227
1228	return s
1229}