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 // Pending operation icon
 258		IconSuccess   lipgloss.Style // Successful operation icon
 259		IconError     lipgloss.Style // Error operation icon
 260		IconCancelled lipgloss.Style // Cancelled operation icon
 261
 262		// Tool name styles
 263		NameNormal lipgloss.Style // Normal tool name
 264		NameNested lipgloss.Style // Nested tool name
 265
 266		// Parameter list styles
 267		ParamMain lipgloss.Style // Main parameter
 268		ParamKey  lipgloss.Style // Parameter keys
 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.Error:               chromaStyle(rules.Chroma.Error),
 463		chroma.Comment:             chromaStyle(rules.Chroma.Comment),
 464		chroma.CommentPreproc:      chromaStyle(rules.Chroma.CommentPreproc),
 465		chroma.Keyword:             chromaStyle(rules.Chroma.Keyword),
 466		chroma.KeywordReserved:     chromaStyle(rules.Chroma.KeywordReserved),
 467		chroma.KeywordNamespace:    chromaStyle(rules.Chroma.KeywordNamespace),
 468		chroma.KeywordType:         chromaStyle(rules.Chroma.KeywordType),
 469		chroma.Operator:            chromaStyle(rules.Chroma.Operator),
 470		chroma.Punctuation:         chromaStyle(rules.Chroma.Punctuation),
 471		chroma.Name:                chromaStyle(rules.Chroma.Name),
 472		chroma.NameBuiltin:         chromaStyle(rules.Chroma.NameBuiltin),
 473		chroma.NameTag:             chromaStyle(rules.Chroma.NameTag),
 474		chroma.NameAttribute:       chromaStyle(rules.Chroma.NameAttribute),
 475		chroma.NameClass:           chromaStyle(rules.Chroma.NameClass),
 476		chroma.NameConstant:        chromaStyle(rules.Chroma.NameConstant),
 477		chroma.NameDecorator:       chromaStyle(rules.Chroma.NameDecorator),
 478		chroma.NameException:       chromaStyle(rules.Chroma.NameException),
 479		chroma.NameFunction:        chromaStyle(rules.Chroma.NameFunction),
 480		chroma.NameOther:           chromaStyle(rules.Chroma.NameOther),
 481		chroma.Literal:             chromaStyle(rules.Chroma.Literal),
 482		chroma.LiteralNumber:       chromaStyle(rules.Chroma.LiteralNumber),
 483		chroma.LiteralDate:         chromaStyle(rules.Chroma.LiteralDate),
 484		chroma.LiteralString:       chromaStyle(rules.Chroma.LiteralString),
 485		chroma.LiteralStringEscape: chromaStyle(rules.Chroma.LiteralStringEscape),
 486		chroma.GenericDeleted:      chromaStyle(rules.Chroma.GenericDeleted),
 487		chroma.GenericEmph:         chromaStyle(rules.Chroma.GenericEmph),
 488		chroma.GenericInserted:     chromaStyle(rules.Chroma.GenericInserted),
 489		chroma.GenericStrong:       chromaStyle(rules.Chroma.GenericStrong),
 490		chroma.GenericSubheading:   chromaStyle(rules.Chroma.GenericSubheading),
 491		chroma.Background:          chromaStyle(rules.Chroma.Background),
 492	}
 493}
 494
 495// DialogHelpStyles returns the styles for dialog help.
 496func (s *Styles) DialogHelpStyles() help.Styles {
 497	return help.Styles(s.Dialog.Help)
 498}
 499
 500// DefaultStyles returns the default styles for the UI.
 501func DefaultStyles() Styles {
 502	var (
 503		primary   = charmtone.Charple
 504		secondary = charmtone.Dolly
 505		tertiary  = charmtone.Bok
 506		// accent    = charmtone.Zest
 507
 508		// Backgrounds
 509		bgBase        = charmtone.Pepper
 510		bgBaseLighter = charmtone.BBQ
 511		bgSubtle      = charmtone.Charcoal
 512		bgOverlay     = charmtone.Iron
 513
 514		// Foregrounds
 515		fgBase      = charmtone.Ash
 516		fgMuted     = charmtone.Squid
 517		fgHalfMuted = charmtone.Smoke
 518		fgSubtle    = charmtone.Oyster
 519		// fgSelected  = charmtone.Salt
 520
 521		// Borders
 522		border      = charmtone.Charcoal
 523		borderFocus = charmtone.Charple
 524
 525		// Status
 526		error   = charmtone.Sriracha
 527		warning = charmtone.Zest
 528		info    = charmtone.Malibu
 529
 530		// Colors
 531		white = charmtone.Butter
 532
 533		blueLight = charmtone.Sardine
 534		blue      = charmtone.Malibu
 535		blueDark  = charmtone.Damson
 536
 537		// yellow = charmtone.Mustard
 538		yellow = charmtone.Mustard
 539		// citron = charmtone.Citron
 540
 541		greenLight = charmtone.Bok
 542		green      = charmtone.Julep
 543		greenDark  = charmtone.Guac
 544		// greenLight = charmtone.Bok
 545
 546		red     = charmtone.Coral
 547		redDark = charmtone.Sriracha
 548		// redLight = charmtone.Salmon
 549		// cherry   = charmtone.Cherry
 550	)
 551
 552	normalBorder := lipgloss.NormalBorder()
 553
 554	base := lipgloss.NewStyle().Foreground(fgBase)
 555
 556	s := Styles{}
 557
 558	s.Background = bgBase
 559
 560	// Populate color fields
 561	s.Primary = primary
 562	s.Secondary = secondary
 563	s.Tertiary = tertiary
 564	s.BgBase = bgBase
 565	s.BgBaseLighter = bgBaseLighter
 566	s.BgSubtle = bgSubtle
 567	s.BgOverlay = bgOverlay
 568	s.FgBase = fgBase
 569	s.FgMuted = fgMuted
 570	s.FgHalfMuted = fgHalfMuted
 571	s.FgSubtle = fgSubtle
 572	s.Border = border
 573	s.BorderColor = borderFocus
 574	s.Error = error
 575	s.Warning = warning
 576	s.Info = info
 577	s.White = white
 578	s.BlueLight = blueLight
 579	s.Blue = blue
 580	s.BlueDark = blueDark
 581	s.GreenLight = greenLight
 582	s.Green = green
 583	s.GreenDark = greenDark
 584	s.Red = red
 585	s.RedDark = redDark
 586	s.Yellow = yellow
 587
 588	s.TextInput = textinput.Styles{
 589		Focused: textinput.StyleState{
 590			Text:        base,
 591			Placeholder: base.Foreground(fgSubtle),
 592			Prompt:      base.Foreground(tertiary),
 593			Suggestion:  base.Foreground(fgSubtle),
 594		},
 595		Blurred: textinput.StyleState{
 596			Text:        base.Foreground(fgMuted),
 597			Placeholder: base.Foreground(fgSubtle),
 598			Prompt:      base.Foreground(fgMuted),
 599			Suggestion:  base.Foreground(fgSubtle),
 600		},
 601		Cursor: textinput.CursorStyle{
 602			Color: secondary,
 603			Shape: tea.CursorBlock,
 604			Blink: true,
 605		},
 606	}
 607
 608	s.TextArea = textarea.Styles{
 609		Focused: textarea.StyleState{
 610			Base:             base,
 611			Text:             base,
 612			LineNumber:       base.Foreground(fgSubtle),
 613			CursorLine:       base,
 614			CursorLineNumber: base.Foreground(fgSubtle),
 615			Placeholder:      base.Foreground(fgSubtle),
 616			Prompt:           base.Foreground(tertiary),
 617		},
 618		Blurred: textarea.StyleState{
 619			Base:             base,
 620			Text:             base.Foreground(fgMuted),
 621			LineNumber:       base.Foreground(fgMuted),
 622			CursorLine:       base,
 623			CursorLineNumber: base.Foreground(fgMuted),
 624			Placeholder:      base.Foreground(fgSubtle),
 625			Prompt:           base.Foreground(fgMuted),
 626		},
 627		Cursor: textarea.CursorStyle{
 628			Color: secondary,
 629			Shape: tea.CursorBlock,
 630			Blink: true,
 631		},
 632	}
 633
 634	s.Markdown = ansi.StyleConfig{
 635		Document: ansi.StyleBlock{
 636			StylePrimitive: ansi.StylePrimitive{
 637				// BlockPrefix: "\n",
 638				// BlockSuffix: "\n",
 639				Color: stringPtr(charmtone.Smoke.Hex()),
 640			},
 641			// Margin: uintPtr(defaultMargin),
 642		},
 643		BlockQuote: ansi.StyleBlock{
 644			StylePrimitive: ansi.StylePrimitive{},
 645			Indent:         uintPtr(1),
 646			IndentToken:    stringPtr("β”‚ "),
 647		},
 648		List: ansi.StyleList{
 649			LevelIndent: defaultListIndent,
 650		},
 651		Heading: ansi.StyleBlock{
 652			StylePrimitive: ansi.StylePrimitive{
 653				BlockSuffix: "\n",
 654				Color:       stringPtr(charmtone.Malibu.Hex()),
 655				Bold:        boolPtr(true),
 656			},
 657		},
 658		H1: ansi.StyleBlock{
 659			StylePrimitive: ansi.StylePrimitive{
 660				Prefix:          " ",
 661				Suffix:          " ",
 662				Color:           stringPtr(charmtone.Zest.Hex()),
 663				BackgroundColor: stringPtr(charmtone.Charple.Hex()),
 664				Bold:            boolPtr(true),
 665			},
 666		},
 667		H2: ansi.StyleBlock{
 668			StylePrimitive: ansi.StylePrimitive{
 669				Prefix: "## ",
 670			},
 671		},
 672		H3: ansi.StyleBlock{
 673			StylePrimitive: ansi.StylePrimitive{
 674				Prefix: "### ",
 675			},
 676		},
 677		H4: ansi.StyleBlock{
 678			StylePrimitive: ansi.StylePrimitive{
 679				Prefix: "#### ",
 680			},
 681		},
 682		H5: ansi.StyleBlock{
 683			StylePrimitive: ansi.StylePrimitive{
 684				Prefix: "##### ",
 685			},
 686		},
 687		H6: ansi.StyleBlock{
 688			StylePrimitive: ansi.StylePrimitive{
 689				Prefix: "###### ",
 690				Color:  stringPtr(charmtone.Guac.Hex()),
 691				Bold:   boolPtr(false),
 692			},
 693		},
 694		Strikethrough: ansi.StylePrimitive{
 695			CrossedOut: boolPtr(true),
 696		},
 697		Emph: ansi.StylePrimitive{
 698			Italic: boolPtr(true),
 699		},
 700		Strong: ansi.StylePrimitive{
 701			Bold: boolPtr(true),
 702		},
 703		HorizontalRule: ansi.StylePrimitive{
 704			Color:  stringPtr(charmtone.Charcoal.Hex()),
 705			Format: "\n--------\n",
 706		},
 707		Item: ansi.StylePrimitive{
 708			BlockPrefix: "β€’ ",
 709		},
 710		Enumeration: ansi.StylePrimitive{
 711			BlockPrefix: ". ",
 712		},
 713		Task: ansi.StyleTask{
 714			StylePrimitive: ansi.StylePrimitive{},
 715			Ticked:         "[βœ“] ",
 716			Unticked:       "[ ] ",
 717		},
 718		Link: ansi.StylePrimitive{
 719			Color:     stringPtr(charmtone.Zinc.Hex()),
 720			Underline: boolPtr(true),
 721		},
 722		LinkText: ansi.StylePrimitive{
 723			Color: stringPtr(charmtone.Guac.Hex()),
 724			Bold:  boolPtr(true),
 725		},
 726		Image: ansi.StylePrimitive{
 727			Color:     stringPtr(charmtone.Cheeky.Hex()),
 728			Underline: boolPtr(true),
 729		},
 730		ImageText: ansi.StylePrimitive{
 731			Color:  stringPtr(charmtone.Squid.Hex()),
 732			Format: "Image: {{.text}} β†’",
 733		},
 734		Code: ansi.StyleBlock{
 735			StylePrimitive: ansi.StylePrimitive{
 736				Prefix:          " ",
 737				Suffix:          " ",
 738				Color:           stringPtr(charmtone.Coral.Hex()),
 739				BackgroundColor: stringPtr(charmtone.Charcoal.Hex()),
 740			},
 741		},
 742		CodeBlock: ansi.StyleCodeBlock{
 743			StyleBlock: ansi.StyleBlock{
 744				StylePrimitive: ansi.StylePrimitive{
 745					Color: stringPtr(charmtone.Charcoal.Hex()),
 746				},
 747				Margin: uintPtr(defaultMargin),
 748			},
 749			Chroma: &ansi.Chroma{
 750				Text: ansi.StylePrimitive{
 751					Color: stringPtr(charmtone.Smoke.Hex()),
 752				},
 753				Error: ansi.StylePrimitive{
 754					Color:           stringPtr(charmtone.Butter.Hex()),
 755					BackgroundColor: stringPtr(charmtone.Sriracha.Hex()),
 756				},
 757				Comment: ansi.StylePrimitive{
 758					Color: stringPtr(charmtone.Oyster.Hex()),
 759				},
 760				CommentPreproc: ansi.StylePrimitive{
 761					Color: stringPtr(charmtone.Bengal.Hex()),
 762				},
 763				Keyword: ansi.StylePrimitive{
 764					Color: stringPtr(charmtone.Malibu.Hex()),
 765				},
 766				KeywordReserved: ansi.StylePrimitive{
 767					Color: stringPtr(charmtone.Pony.Hex()),
 768				},
 769				KeywordNamespace: ansi.StylePrimitive{
 770					Color: stringPtr(charmtone.Pony.Hex()),
 771				},
 772				KeywordType: ansi.StylePrimitive{
 773					Color: stringPtr(charmtone.Guppy.Hex()),
 774				},
 775				Operator: ansi.StylePrimitive{
 776					Color: stringPtr(charmtone.Salmon.Hex()),
 777				},
 778				Punctuation: ansi.StylePrimitive{
 779					Color: stringPtr(charmtone.Zest.Hex()),
 780				},
 781				Name: ansi.StylePrimitive{
 782					Color: stringPtr(charmtone.Smoke.Hex()),
 783				},
 784				NameBuiltin: ansi.StylePrimitive{
 785					Color: stringPtr(charmtone.Cheeky.Hex()),
 786				},
 787				NameTag: ansi.StylePrimitive{
 788					Color: stringPtr(charmtone.Mauve.Hex()),
 789				},
 790				NameAttribute: ansi.StylePrimitive{
 791					Color: stringPtr(charmtone.Hazy.Hex()),
 792				},
 793				NameClass: ansi.StylePrimitive{
 794					Color:     stringPtr(charmtone.Salt.Hex()),
 795					Underline: boolPtr(true),
 796					Bold:      boolPtr(true),
 797				},
 798				NameDecorator: ansi.StylePrimitive{
 799					Color: stringPtr(charmtone.Citron.Hex()),
 800				},
 801				NameFunction: ansi.StylePrimitive{
 802					Color: stringPtr(charmtone.Guac.Hex()),
 803				},
 804				LiteralNumber: ansi.StylePrimitive{
 805					Color: stringPtr(charmtone.Julep.Hex()),
 806				},
 807				LiteralString: ansi.StylePrimitive{
 808					Color: stringPtr(charmtone.Cumin.Hex()),
 809				},
 810				LiteralStringEscape: ansi.StylePrimitive{
 811					Color: stringPtr(charmtone.Bok.Hex()),
 812				},
 813				GenericDeleted: ansi.StylePrimitive{
 814					Color: stringPtr(charmtone.Coral.Hex()),
 815				},
 816				GenericEmph: ansi.StylePrimitive{
 817					Italic: boolPtr(true),
 818				},
 819				GenericInserted: ansi.StylePrimitive{
 820					Color: stringPtr(charmtone.Guac.Hex()),
 821				},
 822				GenericStrong: ansi.StylePrimitive{
 823					Bold: boolPtr(true),
 824				},
 825				GenericSubheading: ansi.StylePrimitive{
 826					Color: stringPtr(charmtone.Squid.Hex()),
 827				},
 828				Background: ansi.StylePrimitive{
 829					BackgroundColor: stringPtr(charmtone.Charcoal.Hex()),
 830				},
 831			},
 832		},
 833		Table: ansi.StyleTable{
 834			StyleBlock: ansi.StyleBlock{
 835				StylePrimitive: ansi.StylePrimitive{},
 836			},
 837		},
 838		DefinitionDescription: ansi.StylePrimitive{
 839			BlockPrefix: "\n ",
 840		},
 841	}
 842
 843	// PlainMarkdown style - muted colors on subtle background for thinking content.
 844	plainBg := stringPtr(bgBaseLighter.Hex())
 845	plainFg := stringPtr(fgMuted.Hex())
 846	s.PlainMarkdown = ansi.StyleConfig{
 847		Document: ansi.StyleBlock{
 848			StylePrimitive: ansi.StylePrimitive{
 849				Color:           plainFg,
 850				BackgroundColor: plainBg,
 851			},
 852		},
 853		BlockQuote: ansi.StyleBlock{
 854			StylePrimitive: ansi.StylePrimitive{
 855				Color:           plainFg,
 856				BackgroundColor: plainBg,
 857			},
 858			Indent:      uintPtr(1),
 859			IndentToken: stringPtr("β”‚ "),
 860		},
 861		List: ansi.StyleList{
 862			LevelIndent: defaultListIndent,
 863		},
 864		Heading: ansi.StyleBlock{
 865			StylePrimitive: ansi.StylePrimitive{
 866				BlockSuffix:     "\n",
 867				Bold:            boolPtr(true),
 868				Color:           plainFg,
 869				BackgroundColor: plainBg,
 870			},
 871		},
 872		H1: ansi.StyleBlock{
 873			StylePrimitive: ansi.StylePrimitive{
 874				Prefix:          " ",
 875				Suffix:          " ",
 876				Bold:            boolPtr(true),
 877				Color:           plainFg,
 878				BackgroundColor: plainBg,
 879			},
 880		},
 881		H2: ansi.StyleBlock{
 882			StylePrimitive: ansi.StylePrimitive{
 883				Prefix:          "## ",
 884				Color:           plainFg,
 885				BackgroundColor: plainBg,
 886			},
 887		},
 888		H3: ansi.StyleBlock{
 889			StylePrimitive: ansi.StylePrimitive{
 890				Prefix:          "### ",
 891				Color:           plainFg,
 892				BackgroundColor: plainBg,
 893			},
 894		},
 895		H4: ansi.StyleBlock{
 896			StylePrimitive: ansi.StylePrimitive{
 897				Prefix:          "#### ",
 898				Color:           plainFg,
 899				BackgroundColor: plainBg,
 900			},
 901		},
 902		H5: ansi.StyleBlock{
 903			StylePrimitive: ansi.StylePrimitive{
 904				Prefix:          "##### ",
 905				Color:           plainFg,
 906				BackgroundColor: plainBg,
 907			},
 908		},
 909		H6: ansi.StyleBlock{
 910			StylePrimitive: ansi.StylePrimitive{
 911				Prefix:          "###### ",
 912				Color:           plainFg,
 913				BackgroundColor: plainBg,
 914			},
 915		},
 916		Strikethrough: ansi.StylePrimitive{
 917			CrossedOut:      boolPtr(true),
 918			Color:           plainFg,
 919			BackgroundColor: plainBg,
 920		},
 921		Emph: ansi.StylePrimitive{
 922			Italic:          boolPtr(true),
 923			Color:           plainFg,
 924			BackgroundColor: plainBg,
 925		},
 926		Strong: ansi.StylePrimitive{
 927			Bold:            boolPtr(true),
 928			Color:           plainFg,
 929			BackgroundColor: plainBg,
 930		},
 931		HorizontalRule: ansi.StylePrimitive{
 932			Format:          "\n--------\n",
 933			Color:           plainFg,
 934			BackgroundColor: plainBg,
 935		},
 936		Item: ansi.StylePrimitive{
 937			BlockPrefix:     "β€’ ",
 938			Color:           plainFg,
 939			BackgroundColor: plainBg,
 940		},
 941		Enumeration: ansi.StylePrimitive{
 942			BlockPrefix:     ". ",
 943			Color:           plainFg,
 944			BackgroundColor: plainBg,
 945		},
 946		Task: ansi.StyleTask{
 947			StylePrimitive: ansi.StylePrimitive{
 948				Color:           plainFg,
 949				BackgroundColor: plainBg,
 950			},
 951			Ticked:   "[βœ“] ",
 952			Unticked: "[ ] ",
 953		},
 954		Link: ansi.StylePrimitive{
 955			Underline:       boolPtr(true),
 956			Color:           plainFg,
 957			BackgroundColor: plainBg,
 958		},
 959		LinkText: ansi.StylePrimitive{
 960			Bold:            boolPtr(true),
 961			Color:           plainFg,
 962			BackgroundColor: plainBg,
 963		},
 964		Image: ansi.StylePrimitive{
 965			Underline:       boolPtr(true),
 966			Color:           plainFg,
 967			BackgroundColor: plainBg,
 968		},
 969		ImageText: ansi.StylePrimitive{
 970			Format:          "Image: {{.text}} β†’",
 971			Color:           plainFg,
 972			BackgroundColor: plainBg,
 973		},
 974		Code: ansi.StyleBlock{
 975			StylePrimitive: ansi.StylePrimitive{
 976				Prefix:          " ",
 977				Suffix:          " ",
 978				Color:           plainFg,
 979				BackgroundColor: plainBg,
 980			},
 981		},
 982		CodeBlock: ansi.StyleCodeBlock{
 983			StyleBlock: ansi.StyleBlock{
 984				StylePrimitive: ansi.StylePrimitive{
 985					Color:           plainFg,
 986					BackgroundColor: plainBg,
 987				},
 988				Margin: uintPtr(defaultMargin),
 989			},
 990		},
 991		Table: ansi.StyleTable{
 992			StyleBlock: ansi.StyleBlock{
 993				StylePrimitive: ansi.StylePrimitive{
 994					Color:           plainFg,
 995					BackgroundColor: plainBg,
 996				},
 997			},
 998		},
 999		DefinitionDescription: ansi.StylePrimitive{
1000			BlockPrefix:     "\n ",
1001			Color:           plainFg,
1002			BackgroundColor: plainBg,
1003		},
1004	}
1005
1006	s.Help = help.Styles{
1007		ShortKey:       base.Foreground(fgMuted),
1008		ShortDesc:      base.Foreground(fgSubtle),
1009		ShortSeparator: base.Foreground(border),
1010		Ellipsis:       base.Foreground(border),
1011		FullKey:        base.Foreground(fgMuted),
1012		FullDesc:       base.Foreground(fgSubtle),
1013		FullSeparator:  base.Foreground(border),
1014	}
1015
1016	s.Diff = diffview.Style{
1017		DividerLine: diffview.LineStyle{
1018			LineNumber: lipgloss.NewStyle().
1019				Foreground(fgHalfMuted).
1020				Background(bgBaseLighter),
1021			Code: lipgloss.NewStyle().
1022				Foreground(fgHalfMuted).
1023				Background(bgBaseLighter),
1024		},
1025		MissingLine: diffview.LineStyle{
1026			LineNumber: lipgloss.NewStyle().
1027				Background(bgBaseLighter),
1028			Code: lipgloss.NewStyle().
1029				Background(bgBaseLighter),
1030		},
1031		EqualLine: diffview.LineStyle{
1032			LineNumber: lipgloss.NewStyle().
1033				Foreground(fgMuted).
1034				Background(bgBase),
1035			Code: lipgloss.NewStyle().
1036				Foreground(fgMuted).
1037				Background(bgBase),
1038		},
1039		InsertLine: diffview.LineStyle{
1040			LineNumber: lipgloss.NewStyle().
1041				Foreground(lipgloss.Color("#629657")).
1042				Background(lipgloss.Color("#2b322a")),
1043			Symbol: lipgloss.NewStyle().
1044				Foreground(lipgloss.Color("#629657")).
1045				Background(lipgloss.Color("#323931")),
1046			Code: lipgloss.NewStyle().
1047				Background(lipgloss.Color("#323931")),
1048		},
1049		DeleteLine: diffview.LineStyle{
1050			LineNumber: lipgloss.NewStyle().
1051				Foreground(lipgloss.Color("#a45c59")).
1052				Background(lipgloss.Color("#312929")),
1053			Symbol: lipgloss.NewStyle().
1054				Foreground(lipgloss.Color("#a45c59")).
1055				Background(lipgloss.Color("#383030")),
1056			Code: lipgloss.NewStyle().
1057				Background(lipgloss.Color("#383030")),
1058		},
1059	}
1060
1061	s.FilePicker = filepicker.Styles{
1062		DisabledCursor:   base.Foreground(fgMuted),
1063		Cursor:           base.Foreground(fgBase),
1064		Symlink:          base.Foreground(fgSubtle),
1065		Directory:        base.Foreground(primary),
1066		File:             base.Foreground(fgBase),
1067		DisabledFile:     base.Foreground(fgMuted),
1068		DisabledSelected: base.Background(bgOverlay).Foreground(fgMuted),
1069		Permission:       base.Foreground(fgMuted),
1070		Selected:         base.Background(primary).Foreground(fgBase),
1071		FileSize:         base.Foreground(fgMuted),
1072		EmptyDirectory:   base.Foreground(fgMuted).PaddingLeft(2).SetString("Empty directory"),
1073	}
1074
1075	// borders
1076	s.FocusedMessageBorder = lipgloss.Border{Left: BorderThick}
1077
1078	// text presets
1079	s.Base = lipgloss.NewStyle().Foreground(fgBase)
1080	s.Muted = lipgloss.NewStyle().Foreground(fgMuted)
1081	s.HalfMuted = lipgloss.NewStyle().Foreground(fgHalfMuted)
1082	s.Subtle = lipgloss.NewStyle().Foreground(fgSubtle)
1083
1084	s.WindowTooSmall = s.Muted
1085
1086	// tag presets
1087	s.TagBase = lipgloss.NewStyle().Padding(0, 1).Foreground(white)
1088	s.TagError = s.TagBase.Background(redDark)
1089	s.TagInfo = s.TagBase.Background(blueLight)
1090
1091	// Compact header styles
1092	s.Header.Charm = base.Foreground(secondary)
1093	s.Header.Diagonals = base.Foreground(primary)
1094	s.Header.Percentage = s.Muted
1095	s.Header.Keystroke = s.Muted
1096	s.Header.KeystrokeTip = s.Subtle
1097	s.Header.WorkingDir = s.Muted
1098	s.Header.Separator = s.Subtle
1099
1100	s.CompactDetails.Title = s.Base
1101	s.CompactDetails.View = s.Base.Padding(0, 1, 1, 1).Border(lipgloss.RoundedBorder()).BorderForeground(borderFocus)
1102	s.CompactDetails.Version = s.Muted
1103
1104	// panels
1105	s.PanelMuted = s.Muted.Background(bgBaseLighter)
1106	s.PanelBase = lipgloss.NewStyle().Background(bgBase)
1107
1108	// code line number
1109	s.LineNumber = lipgloss.NewStyle().Foreground(fgMuted).Background(bgBase).PaddingRight(1).PaddingLeft(1)
1110
1111	// Tool calls
1112	s.ToolCallPending = lipgloss.NewStyle().Foreground(greenDark).SetString(ToolPending)
1113	s.ToolCallError = lipgloss.NewStyle().Foreground(redDark).SetString(ToolError)
1114	s.ToolCallSuccess = lipgloss.NewStyle().Foreground(green).SetString(ToolSuccess)
1115	// Cancelled uses muted tone but same glyph as pending
1116	s.ToolCallCancelled = s.Muted.SetString(ToolPending)
1117	s.EarlyStateMessage = s.Subtle.PaddingLeft(2)
1118
1119	// Tool rendering styles
1120	s.Tool.IconPending = base.Foreground(greenDark).SetString(ToolPending)
1121	s.Tool.IconSuccess = base.Foreground(green).SetString(ToolSuccess)
1122	s.Tool.IconError = base.Foreground(redDark).SetString(ToolError)
1123	s.Tool.IconCancelled = s.Muted.SetString(ToolPending)
1124
1125	s.Tool.NameNormal = base.Foreground(blue)
1126	s.Tool.NameNested = base.Foreground(fgHalfMuted)
1127
1128	s.Tool.ParamMain = s.Subtle
1129	s.Tool.ParamKey = s.Subtle
1130
1131	// Content rendering - prepared styles that accept width parameter
1132	s.Tool.ContentLine = s.Muted.Background(bgBaseLighter)
1133	s.Tool.ContentTruncation = s.Muted.Background(bgBaseLighter)
1134	s.Tool.ContentCodeLine = s.Base.Background(bgBase).PaddingLeft(2)
1135	s.Tool.ContentCodeTruncation = s.Muted.Background(bgBase).PaddingLeft(2)
1136	s.Tool.ContentCodeBg = bgBase
1137	s.Tool.Body = base.PaddingLeft(2)
1138
1139	// Deprecated - kept for backward compatibility
1140	s.Tool.ContentBg = s.Muted.Background(bgBaseLighter)
1141	s.Tool.ContentText = s.Muted
1142	s.Tool.ContentLineNumber = base.Foreground(fgMuted).Background(bgBase).PaddingRight(1).PaddingLeft(1)
1143
1144	s.Tool.StateWaiting = base.Foreground(fgSubtle)
1145	s.Tool.StateCancelled = base.Foreground(fgSubtle)
1146
1147	s.Tool.ErrorTag = base.Padding(0, 1).Background(red).Foreground(white)
1148	s.Tool.ErrorMessage = base.Foreground(fgHalfMuted)
1149
1150	// Diff and multi-edit styles
1151	s.Tool.DiffTruncation = s.Muted.Background(bgBaseLighter).PaddingLeft(2)
1152	s.Tool.NoteTag = base.Padding(0, 1).Background(info).Foreground(white)
1153	s.Tool.NoteMessage = base.Foreground(fgHalfMuted)
1154
1155	// Job header styles
1156	s.Tool.JobIconPending = base.Foreground(greenDark)
1157	s.Tool.JobIconError = base.Foreground(redDark)
1158	s.Tool.JobIconSuccess = base.Foreground(green)
1159	s.Tool.JobToolName = base.Foreground(blue)
1160	s.Tool.JobAction = base.Foreground(blueDark)
1161	s.Tool.JobPID = s.Muted
1162	s.Tool.JobDescription = s.Subtle
1163
1164	// Agent task styles
1165	s.Tool.AgentTaskTag = base.Bold(true).Padding(0, 1).MarginLeft(2).Background(blueLight).Foreground(white)
1166	s.Tool.AgentPrompt = s.Muted
1167
1168	// Agentic fetch styles
1169	s.Tool.AgenticFetchPromptTag = base.Bold(true).Padding(0, 1).MarginLeft(2).Background(green).Foreground(border)
1170
1171	// Todo styles
1172	s.Tool.TodoRatio = base.Foreground(blueDark)
1173	s.Tool.TodoCompletedIcon = base.Foreground(green)
1174	s.Tool.TodoInProgressIcon = base.Foreground(greenDark)
1175	s.Tool.TodoPendingIcon = base.Foreground(fgMuted)
1176
1177	// MCP styles
1178	s.Tool.MCPName = base.Foreground(blue)
1179	s.Tool.MCPToolName = base.Foreground(blueDark)
1180	s.Tool.MCPArrow = base.Foreground(blue).SetString(ArrowRightIcon)
1181
1182	// Loading indicators for images, skills
1183	s.Tool.ResourceLoadedText = base.Foreground(green)
1184	s.Tool.ResourceLoadedIndicator = base.Foreground(greenDark)
1185	s.Tool.ResourceName = base
1186	s.Tool.MediaType = base
1187	s.Tool.ResourceSize = base.Foreground(fgMuted)
1188
1189	// Docker MCP styles
1190	s.Tool.DockerMCPActionAdd = base.Foreground(greenLight)
1191	s.Tool.DockerMCPActionDel = base.Foreground(red)
1192
1193	// Buttons
1194	s.ButtonFocus = lipgloss.NewStyle().Foreground(white).Background(secondary)
1195	s.ButtonBlur = s.Base.Background(bgSubtle)
1196
1197	// Borders
1198	s.BorderFocus = lipgloss.NewStyle().BorderForeground(borderFocus).Border(lipgloss.RoundedBorder()).Padding(1, 2)
1199
1200	// Editor
1201	s.EditorPromptNormalFocused = lipgloss.NewStyle().Foreground(greenDark).SetString("::: ")
1202	s.EditorPromptNormalBlurred = s.EditorPromptNormalFocused.Foreground(fgMuted)
1203	s.EditorPromptYoloIconFocused = lipgloss.NewStyle().MarginRight(1).Foreground(charmtone.Oyster).Background(charmtone.Citron).Bold(true).SetString(" ! ")
1204	s.EditorPromptYoloIconBlurred = s.EditorPromptYoloIconFocused.Foreground(charmtone.Pepper).Background(charmtone.Squid)
1205	s.EditorPromptYoloDotsFocused = lipgloss.NewStyle().MarginRight(1).Foreground(charmtone.Zest).SetString(":::")
1206	s.EditorPromptYoloDotsBlurred = s.EditorPromptYoloDotsFocused.Foreground(charmtone.Squid)
1207
1208	s.RadioOn = s.HalfMuted.SetString(RadioOn)
1209	s.RadioOff = s.HalfMuted.SetString(RadioOff)
1210
1211	// Logo colors
1212	s.LogoFieldColor = primary
1213	s.LogoTitleColorA = secondary
1214	s.LogoTitleColorB = primary
1215	s.LogoCharmColor = secondary
1216	s.LogoVersionColor = primary
1217
1218	// Section
1219	s.Section.Title = s.Subtle
1220	s.Section.Line = s.Base.Foreground(charmtone.Charcoal)
1221
1222	// Initialize
1223	s.Initialize.Header = s.Base
1224	s.Initialize.Content = s.Muted
1225	s.Initialize.Accent = s.Base.Foreground(greenDark)
1226
1227	// LSP and MCP status.
1228	s.ResourceGroupTitle = lipgloss.NewStyle().Foreground(charmtone.Oyster)
1229	s.ResourceOfflineIcon = lipgloss.NewStyle().Foreground(charmtone.Iron).SetString("●")
1230	s.ResourceBusyIcon = s.ResourceOfflineIcon.Foreground(charmtone.Citron)
1231	s.ResourceErrorIcon = s.ResourceOfflineIcon.Foreground(charmtone.Coral)
1232	s.ResourceOnlineIcon = s.ResourceOfflineIcon.Foreground(charmtone.Guac)
1233	s.ResourceName = lipgloss.NewStyle().Foreground(charmtone.Squid)
1234	s.ResourceStatus = lipgloss.NewStyle().Foreground(charmtone.Oyster)
1235	s.ResourceAdditionalText = lipgloss.NewStyle().Foreground(charmtone.Oyster)
1236
1237	// LSP
1238	s.LSP.ErrorDiagnostic = s.Base.Foreground(redDark)
1239	s.LSP.WarningDiagnostic = s.Base.Foreground(warning)
1240	s.LSP.HintDiagnostic = s.Base.Foreground(fgHalfMuted)
1241	s.LSP.InfoDiagnostic = s.Base.Foreground(info)
1242
1243	// Files
1244	s.Files.Path = s.Muted
1245	s.Files.Additions = s.Base.Foreground(greenDark)
1246	s.Files.Deletions = s.Base.Foreground(redDark)
1247
1248	// Chat
1249	messageFocussedBorder := lipgloss.Border{
1250		Left: "β–Œ",
1251	}
1252
1253	s.Chat.Message.NoContent = lipgloss.NewStyle().Foreground(fgBase)
1254	s.Chat.Message.UserBlurred = s.Chat.Message.NoContent.PaddingLeft(1).BorderLeft(true).
1255		BorderForeground(primary).BorderStyle(normalBorder)
1256	s.Chat.Message.UserFocused = s.Chat.Message.NoContent.PaddingLeft(1).BorderLeft(true).
1257		BorderForeground(primary).BorderStyle(messageFocussedBorder)
1258	s.Chat.Message.AssistantBlurred = s.Chat.Message.NoContent.PaddingLeft(2)
1259	s.Chat.Message.AssistantFocused = s.Chat.Message.NoContent.PaddingLeft(1).BorderLeft(true).
1260		BorderForeground(greenDark).BorderStyle(messageFocussedBorder)
1261	s.Chat.Message.Thinking = lipgloss.NewStyle().MaxHeight(10)
1262	s.Chat.Message.ErrorTag = lipgloss.NewStyle().Padding(0, 1).
1263		Background(red).Foreground(white)
1264	s.Chat.Message.ErrorTitle = lipgloss.NewStyle().Foreground(fgHalfMuted)
1265	s.Chat.Message.ErrorDetails = lipgloss.NewStyle().Foreground(fgSubtle)
1266
1267	// Message item styles
1268	s.Chat.Message.ToolCallFocused = s.Muted.PaddingLeft(1).
1269		BorderStyle(messageFocussedBorder).
1270		BorderLeft(true).
1271		BorderForeground(greenDark)
1272	s.Chat.Message.ToolCallBlurred = s.Muted.PaddingLeft(2)
1273	// No padding or border for compact tool calls within messages
1274	s.Chat.Message.ToolCallCompact = s.Muted
1275	s.Chat.Message.SectionHeader = s.Base.PaddingLeft(2)
1276	s.Chat.Message.AssistantInfoIcon = s.Subtle
1277	s.Chat.Message.AssistantInfoModel = s.Muted
1278	s.Chat.Message.AssistantInfoProvider = s.Subtle
1279	s.Chat.Message.AssistantInfoDuration = s.Subtle
1280
1281	// Thinking section styles
1282	s.Chat.Message.ThinkingBox = s.Subtle.Background(bgBaseLighter)
1283	s.Chat.Message.ThinkingTruncationHint = s.Muted
1284	s.Chat.Message.ThinkingFooterTitle = s.Muted
1285	s.Chat.Message.ThinkingFooterDuration = s.Subtle
1286
1287	// Text selection.
1288	s.TextSelection = lipgloss.NewStyle().Foreground(charmtone.Salt).Background(charmtone.Charple)
1289
1290	// Dialog styles
1291	s.Dialog.Title = base.Padding(0, 1).Foreground(primary)
1292	s.Dialog.TitleText = base.Foreground(primary)
1293	s.Dialog.TitleError = base.Foreground(red)
1294	s.Dialog.TitleAccent = base.Foreground(green).Bold(true)
1295	s.Dialog.View = base.Border(lipgloss.RoundedBorder()).BorderForeground(borderFocus)
1296	s.Dialog.PrimaryText = base.Padding(0, 1).Foreground(primary)
1297	s.Dialog.SecondaryText = base.Padding(0, 1).Foreground(fgSubtle)
1298	s.Dialog.HelpView = base.Padding(0, 1).AlignHorizontal(lipgloss.Left)
1299	s.Dialog.Help.ShortKey = base.Foreground(fgMuted)
1300	s.Dialog.Help.ShortDesc = base.Foreground(fgSubtle)
1301	s.Dialog.Help.ShortSeparator = base.Foreground(border)
1302	s.Dialog.Help.Ellipsis = base.Foreground(border)
1303	s.Dialog.Help.FullKey = base.Foreground(fgMuted)
1304	s.Dialog.Help.FullDesc = base.Foreground(fgSubtle)
1305	s.Dialog.Help.FullSeparator = base.Foreground(border)
1306	s.Dialog.NormalItem = base.Padding(0, 1).Foreground(fgBase)
1307	s.Dialog.SelectedItem = base.Padding(0, 1).Background(primary).Foreground(fgBase)
1308	s.Dialog.InputPrompt = base.Margin(1, 1)
1309
1310	s.Dialog.List = base.Margin(0, 0, 1, 0)
1311	s.Dialog.ContentPanel = base.Background(bgSubtle).Foreground(fgBase).Padding(1, 2)
1312	s.Dialog.Spinner = base.Foreground(secondary)
1313	s.Dialog.ScrollbarThumb = base.Foreground(secondary)
1314	s.Dialog.ScrollbarTrack = base.Foreground(border)
1315
1316	s.Dialog.ImagePreview = lipgloss.NewStyle().Padding(0, 1).Foreground(fgSubtle)
1317
1318	s.Dialog.Arguments.Content = base.Padding(1)
1319	s.Dialog.Arguments.Description = base.MarginBottom(1).MaxHeight(3)
1320	s.Dialog.Arguments.InputLabelBlurred = base.Foreground(fgMuted)
1321	s.Dialog.Arguments.InputLabelFocused = base.Bold(true)
1322	s.Dialog.Arguments.InputRequiredMarkBlurred = base.Foreground(fgMuted).SetString("*")
1323	s.Dialog.Arguments.InputRequiredMarkFocused = base.Foreground(primary).Bold(true).SetString("*")
1324
1325	s.Dialog.Sessions.DeletingTitle = s.Dialog.Title.Foreground(red)
1326	s.Dialog.Sessions.DeletingView = s.Dialog.View.BorderForeground(red)
1327	s.Dialog.Sessions.DeletingMessage = s.Base.Padding(1)
1328	s.Dialog.Sessions.DeletingTitleGradientFromColor = red
1329	s.Dialog.Sessions.DeletingTitleGradientToColor = s.Primary
1330	s.Dialog.Sessions.DeletingItemBlurred = s.Dialog.NormalItem.Foreground(fgSubtle)
1331	s.Dialog.Sessions.DeletingItemFocused = s.Dialog.SelectedItem.Background(red).Foreground(charmtone.Butter)
1332
1333	s.Dialog.Sessions.RenamingingTitle = s.Dialog.Title.Foreground(charmtone.Zest)
1334	s.Dialog.Sessions.RenamingView = s.Dialog.View.BorderForeground(charmtone.Zest)
1335	s.Dialog.Sessions.RenamingingMessage = s.Base.Padding(1)
1336	s.Dialog.Sessions.RenamingTitleGradientFromColor = charmtone.Zest
1337	s.Dialog.Sessions.RenamingTitleGradientToColor = charmtone.Bok
1338	s.Dialog.Sessions.RenamingItemBlurred = s.Dialog.NormalItem.Foreground(fgSubtle)
1339	s.Dialog.Sessions.RenamingingItemFocused = s.Dialog.SelectedItem.UnsetBackground().UnsetForeground()
1340	s.Dialog.Sessions.RenamingPlaceholder = base.Foreground(charmtone.Squid)
1341
1342	s.Status.Help = lipgloss.NewStyle().Padding(0, 1)
1343	s.Status.SuccessIndicator = base.Foreground(bgSubtle).Background(green).Padding(0, 1).Bold(true).SetString("OKAY!")
1344	s.Status.InfoIndicator = s.Status.SuccessIndicator
1345	s.Status.UpdateIndicator = s.Status.SuccessIndicator.SetString("HEY!")
1346	s.Status.WarnIndicator = s.Status.SuccessIndicator.Foreground(bgOverlay).Background(yellow).SetString("WARNING")
1347	s.Status.ErrorIndicator = s.Status.SuccessIndicator.Foreground(bgBase).Background(red).SetString("ERROR")
1348	s.Status.SuccessMessage = base.Foreground(bgSubtle).Background(greenDark).Padding(0, 1)
1349	s.Status.InfoMessage = s.Status.SuccessMessage
1350	s.Status.UpdateMessage = s.Status.SuccessMessage
1351	s.Status.WarnMessage = s.Status.SuccessMessage.Foreground(bgOverlay).Background(warning)
1352	s.Status.ErrorMessage = s.Status.SuccessMessage.Foreground(white).Background(redDark)
1353
1354	// Completions styles
1355	s.Completions.Normal = base.Background(bgSubtle).Foreground(fgBase)
1356	s.Completions.Focused = base.Background(primary).Foreground(white)
1357	s.Completions.Match = base.Underline(true)
1358
1359	// Attachments styles
1360	attachmentIconStyle := base.Foreground(bgSubtle).Background(green).Padding(0, 1)
1361	s.Attachments.Image = attachmentIconStyle.SetString(ImageIcon)
1362	s.Attachments.Text = attachmentIconStyle.SetString(TextIcon)
1363	s.Attachments.Normal = base.Padding(0, 1).MarginRight(1).Background(fgMuted).Foreground(fgBase)
1364	s.Attachments.Deleting = base.Padding(0, 1).Bold(true).Background(red).Foreground(fgBase)
1365
1366	// Pills styles
1367	s.Pills.Base = base.Padding(0, 1)
1368	s.Pills.Focused = base.Padding(0, 1).BorderStyle(lipgloss.RoundedBorder()).BorderForeground(bgOverlay)
1369	s.Pills.Blurred = base.Padding(0, 1).BorderStyle(lipgloss.HiddenBorder())
1370	s.Pills.QueueItemPrefix = s.Muted.SetString("  β€’")
1371	s.Pills.HelpKey = s.Muted
1372	s.Pills.HelpText = s.Subtle
1373	s.Pills.Area = base
1374	s.Pills.TodoSpinner = base.Foreground(greenDark)
1375
1376	return s
1377}
1378
1379// Helper functions for style pointers
1380func boolPtr(b bool) *bool       { return &b }
1381func stringPtr(s string) *string { return &s }
1382func uintPtr(u uint) *uint       { return &u }
1383func chromaStyle(style ansi.StylePrimitive) string {
1384	var s strings.Builder
1385
1386	if style.Color != nil {
1387		s.WriteString(*style.Color)
1388	}
1389	if style.BackgroundColor != nil {
1390		if s.Len() > 0 {
1391			s.WriteString(" ")
1392		}
1393		s.WriteString("bg:")
1394		s.WriteString(*style.BackgroundColor)
1395	}
1396	if style.Italic != nil && *style.Italic {
1397		if s.Len() > 0 {
1398			s.WriteString(" ")
1399		}
1400		s.WriteString("italic")
1401	}
1402	if style.Bold != nil && *style.Bold {
1403		if s.Len() > 0 {
1404			s.WriteString(" ")
1405		}
1406		s.WriteString("bold")
1407	}
1408	if style.Underline != nil && *style.Underline {
1409		if s.Len() > 0 {
1410			s.WriteString(" ")
1411		}
1412		s.WriteString("underline")
1413	}
1414
1415	return s.String()
1416}