styles.go

   1package styles
   2
   3import (
   4	"image/color"
   5	"strings"
   6
   7	"charm.land/bubbles/v2/filepicker"
   8	"charm.land/bubbles/v2/help"
   9	"charm.land/bubbles/v2/textarea"
  10	"charm.land/bubbles/v2/textinput"
  11	tea "charm.land/bubbletea/v2"
  12	"charm.land/glamour/v2/ansi"
  13	"charm.land/lipgloss/v2"
  14	"github.com/alecthomas/chroma/v2"
  15	"github.com/charmbracelet/crush/internal/ui/diffview"
  16	"github.com/charmbracelet/x/exp/charmtone"
  17)
  18
  19const (
  20	CheckIcon   string = "βœ“"
  21	SpinnerIcon string = "β‹―"
  22	LoadingIcon string = "⟳"
  23	ModelIcon   string = "β—‡"
  24
  25	ArrowRightIcon string = "β†’"
  26
  27	ToolPending string = "●"
  28	ToolSuccess string = "βœ“"
  29	ToolError   string = "Γ—"
  30
  31	RadioOn  string = "β—‰"
  32	RadioOff string = "β—‹"
  33
  34	BorderThin  string = "β”‚"
  35	BorderThick string = "β–Œ"
  36
  37	SectionSeparator string = "─"
  38
  39	TodoCompletedIcon  string = "βœ“"
  40	TodoPendingIcon    string = "β€’"
  41	TodoInProgressIcon string = "β†’"
  42
  43	ImageIcon string = "β– "
  44	TextIcon  string = "≑"
  45
  46	ScrollbarThumb string = "┃"
  47	ScrollbarTrack string = "β”‚"
  48
  49	LSPErrorIcon   string = "E"
  50	LSPWarningIcon string = "W"
  51	LSPInfoIcon    string = "I"
  52	LSPHintIcon    string = "H"
  53)
  54
  55const (
  56	defaultMargin     = 2
  57	defaultListIndent = 2
  58)
  59
  60type Styles struct {
  61	WindowTooSmall lipgloss.Style
  62
  63	// Reusable text styles
  64	Base      lipgloss.Style
  65	Muted     lipgloss.Style
  66	HalfMuted lipgloss.Style
  67	Subtle    lipgloss.Style
  68
  69	// Tags
  70	TagBase  lipgloss.Style
  71	TagError lipgloss.Style
  72	TagInfo  lipgloss.Style
  73
  74	// Header
  75	Header struct {
  76		Charm        lipgloss.Style // Style for "Charmβ„’" label
  77		Diagonals    lipgloss.Style // Style for diagonal separators (β•±)
  78		Percentage   lipgloss.Style // Style for context percentage
  79		Keystroke    lipgloss.Style // Style for keystroke hints (e.g., "ctrl+d")
  80		KeystrokeTip lipgloss.Style // Style for keystroke action text (e.g., "open", "close")
  81		WorkingDir   lipgloss.Style // Style for current working directory
  82		Separator    lipgloss.Style // Style for separator dots (β€’)
  83	}
  84
  85	CompactDetails struct {
  86		View    lipgloss.Style
  87		Version lipgloss.Style
  88		Title   lipgloss.Style
  89	}
  90
  91	// Panels
  92	PanelMuted lipgloss.Style
  93	PanelBase  lipgloss.Style
  94
  95	// Line numbers for code blocks
  96	LineNumber lipgloss.Style
  97
  98	// Message borders
  99	FocusedMessageBorder lipgloss.Border
 100
 101	// Tool calls
 102	ToolCallPending   lipgloss.Style
 103	ToolCallError     lipgloss.Style
 104	ToolCallSuccess   lipgloss.Style
 105	ToolCallCancelled lipgloss.Style
 106	EarlyStateMessage lipgloss.Style
 107
 108	// Text selection
 109	TextSelection lipgloss.Style
 110
 111	// LSP and MCP status indicators
 112	ResourceGroupTitle     lipgloss.Style
 113	ResourceOfflineIcon    lipgloss.Style
 114	ResourceBusyIcon       lipgloss.Style
 115	ResourceErrorIcon      lipgloss.Style
 116	ResourceOnlineIcon     lipgloss.Style
 117	ResourceName           lipgloss.Style
 118	ResourceStatus         lipgloss.Style
 119	ResourceAdditionalText lipgloss.Style
 120
 121	// Markdown & Chroma
 122	Markdown      ansi.StyleConfig
 123	PlainMarkdown ansi.StyleConfig
 124
 125	// Inputs
 126	TextInput textinput.Styles
 127	TextArea  textarea.Styles
 128
 129	// Help
 130	Help help.Styles
 131
 132	// Diff
 133	Diff diffview.Style
 134
 135	// FilePicker
 136	FilePicker filepicker.Styles
 137
 138	// Buttons
 139	ButtonFocus lipgloss.Style
 140	ButtonBlur  lipgloss.Style
 141
 142	// Borders
 143	BorderFocus lipgloss.Style
 144	BorderBlur  lipgloss.Style
 145
 146	// Editor
 147	EditorPromptNormalFocused   lipgloss.Style
 148	EditorPromptNormalBlurred   lipgloss.Style
 149	EditorPromptYoloIconFocused lipgloss.Style
 150	EditorPromptYoloIconBlurred lipgloss.Style
 151	EditorPromptYoloDotsFocused lipgloss.Style
 152	EditorPromptYoloDotsBlurred lipgloss.Style
 153
 154	// Radio
 155	RadioOn  lipgloss.Style
 156	RadioOff lipgloss.Style
 157
 158	// Background
 159	Background color.Color
 160
 161	// Logo
 162	LogoFieldColor   color.Color
 163	LogoTitleColorA  color.Color
 164	LogoTitleColorB  color.Color
 165	LogoCharmColor   color.Color
 166	LogoVersionColor color.Color
 167
 168	// Colors - semantic colors for tool rendering.
 169	Primary       color.Color
 170	Secondary     color.Color
 171	Tertiary      color.Color
 172	BgBase        color.Color
 173	BgBaseLighter color.Color
 174	BgSubtle      color.Color
 175	BgOverlay     color.Color
 176	FgBase        color.Color
 177	FgMuted       color.Color
 178	FgHalfMuted   color.Color
 179	FgSubtle      color.Color
 180	Border        color.Color
 181	BorderColor   color.Color // Border focus color
 182	Error         color.Color
 183	Warning       color.Color
 184	Info          color.Color
 185	White         color.Color
 186	BlueLight     color.Color
 187	Blue          color.Color
 188	BlueDark      color.Color
 189	GreenLight    color.Color
 190	Green         color.Color
 191	GreenDark     color.Color
 192	Red           color.Color
 193	RedDark       color.Color
 194	Yellow        color.Color
 195
 196	// Section Title
 197	Section struct {
 198		Title lipgloss.Style
 199		Line  lipgloss.Style
 200	}
 201
 202	// Initialize
 203	Initialize struct {
 204		Header  lipgloss.Style
 205		Content lipgloss.Style
 206		Accent  lipgloss.Style
 207	}
 208
 209	// LSP
 210	LSP struct {
 211		ErrorDiagnostic   lipgloss.Style
 212		WarningDiagnostic lipgloss.Style
 213		HintDiagnostic    lipgloss.Style
 214		InfoDiagnostic    lipgloss.Style
 215	}
 216
 217	// Files
 218	Files struct {
 219		Path      lipgloss.Style
 220		Additions lipgloss.Style
 221		Deletions lipgloss.Style
 222	}
 223
 224	// Chat
 225	Chat struct {
 226		// Message item styles
 227		Message struct {
 228			UserBlurred      lipgloss.Style
 229			UserFocused      lipgloss.Style
 230			AssistantBlurred lipgloss.Style
 231			AssistantFocused lipgloss.Style
 232			NoContent        lipgloss.Style
 233			Thinking         lipgloss.Style
 234			ErrorTag         lipgloss.Style
 235			ErrorTitle       lipgloss.Style
 236			ErrorDetails     lipgloss.Style
 237			ToolCallFocused  lipgloss.Style
 238			ToolCallCompact  lipgloss.Style
 239			ToolCallBlurred  lipgloss.Style
 240			SectionHeader    lipgloss.Style
 241
 242			// Thinking section styles
 243			ThinkingBox            lipgloss.Style // Background for thinking content
 244			ThinkingTruncationHint lipgloss.Style // "… (N lines hidden)" hint
 245			ThinkingFooterTitle    lipgloss.Style // "Thought for" text
 246			ThinkingFooterDuration lipgloss.Style // Duration value
 247			AssistantInfoIcon      lipgloss.Style
 248			AssistantInfoModel     lipgloss.Style
 249			AssistantInfoProvider  lipgloss.Style
 250			AssistantInfoDuration  lipgloss.Style
 251		}
 252	}
 253
 254	// Tool - styles for tool call rendering
 255	Tool struct {
 256		// Icon styles with tool status
 257		IconPending   lipgloss.Style
 258		IconSuccess   lipgloss.Style
 259		IconError     lipgloss.Style
 260		IconCancelled lipgloss.Style
 261
 262		// Tool name styles
 263		NameNormal lipgloss.Style // Top-level tool name
 264		NameNested lipgloss.Style // Nested child tool name (inside Agent/Agentic Fetch)
 265
 266		// Parameter list styles
 267		ParamMain lipgloss.Style
 268		ParamKey  lipgloss.Style
 269
 270		// Content rendering styles
 271		ContentLine           lipgloss.Style // Individual content line with background and width
 272		ContentTruncation     lipgloss.Style // Truncation message "… (N lines)"
 273		ContentCodeLine       lipgloss.Style // Code line with background and width
 274		ContentCodeTruncation lipgloss.Style // Code truncation message with bgBase
 275		ContentCodeBg         color.Color    // Background color for syntax highlighting
 276		Body                  lipgloss.Style // Body content padding (PaddingLeft(2))
 277
 278		// Deprecated - kept for backward compatibility
 279		ContentBg         lipgloss.Style // Content background
 280		ContentText       lipgloss.Style // Content text
 281		ContentLineNumber lipgloss.Style // Line numbers in code
 282
 283		// State message styles
 284		StateWaiting   lipgloss.Style // "Waiting for tool response..."
 285		StateCancelled lipgloss.Style // "Canceled."
 286
 287		// Error styles
 288		ErrorTag     lipgloss.Style // ERROR tag
 289		ErrorMessage lipgloss.Style // Error message text
 290
 291		// Diff styles
 292		DiffTruncation lipgloss.Style // Diff truncation message with padding
 293
 294		// Multi-edit note styles
 295		NoteTag     lipgloss.Style // NOTE tag (yellow background)
 296		NoteMessage lipgloss.Style // Note message text
 297
 298		// Job header styles (for bash jobs)
 299		JobIconPending lipgloss.Style // Pending job icon (green dark)
 300		JobIconError   lipgloss.Style // Error job icon (red dark)
 301		JobIconSuccess lipgloss.Style // Success job icon (green)
 302		JobToolName    lipgloss.Style // Job tool name "Bash" (blue)
 303		JobAction      lipgloss.Style // Action text (Start, Output, Kill)
 304		JobPID         lipgloss.Style // PID text
 305		JobDescription lipgloss.Style // Description text
 306
 307		// Agent task styles
 308		AgentTaskTag lipgloss.Style // Agent task tag (blue background, bold)
 309		AgentPrompt  lipgloss.Style // Agent prompt text
 310
 311		// Agentic fetch styles
 312		AgenticFetchPromptTag lipgloss.Style // Agentic fetch prompt tag (green background, bold)
 313
 314		// Todo styles
 315		TodoRatio          lipgloss.Style // Todo ratio (e.g., "2/5")
 316		TodoCompletedIcon  lipgloss.Style // Completed todo icon
 317		TodoInProgressIcon lipgloss.Style // In-progress todo icon
 318		TodoPendingIcon    lipgloss.Style // Pending todo icon
 319
 320		// MCP tools
 321		MCPName     lipgloss.Style // The mcp name
 322		MCPToolName lipgloss.Style // The mcp tool name
 323		MCPArrow    lipgloss.Style // The mcp arrow icon
 324
 325		// Images and external resources
 326		ResourceLoadedText      lipgloss.Style
 327		ResourceLoadedIndicator lipgloss.Style
 328		ResourceName            lipgloss.Style
 329		ResourceSize            lipgloss.Style
 330		MediaType               lipgloss.Style
 331
 332		// Docker MCP tools
 333		DockerMCPActionAdd lipgloss.Style // Docker MCP add action (green)
 334		DockerMCPActionDel lipgloss.Style // Docker MCP remove action (red)
 335	}
 336
 337	// Dialog styles
 338	Dialog struct {
 339		Title       lipgloss.Style
 340		TitleText   lipgloss.Style
 341		TitleError  lipgloss.Style
 342		TitleAccent lipgloss.Style
 343		// View is the main content area style.
 344		View          lipgloss.Style
 345		PrimaryText   lipgloss.Style
 346		SecondaryText lipgloss.Style
 347		// HelpView is the line that contains the help.
 348		HelpView lipgloss.Style
 349		Help     struct {
 350			Ellipsis       lipgloss.Style
 351			ShortKey       lipgloss.Style
 352			ShortDesc      lipgloss.Style
 353			ShortSeparator lipgloss.Style
 354			FullKey        lipgloss.Style
 355			FullDesc       lipgloss.Style
 356			FullSeparator  lipgloss.Style
 357		}
 358
 359		NormalItem   lipgloss.Style
 360		SelectedItem lipgloss.Style
 361		InputPrompt  lipgloss.Style
 362
 363		List lipgloss.Style
 364
 365		Spinner lipgloss.Style
 366
 367		// ContentPanel is used for content blocks with subtle background.
 368		ContentPanel lipgloss.Style
 369
 370		// Scrollbar styles for scrollable content.
 371		ScrollbarThumb lipgloss.Style
 372		ScrollbarTrack lipgloss.Style
 373
 374		// Arguments
 375		Arguments struct {
 376			Content                  lipgloss.Style
 377			Description              lipgloss.Style
 378			InputLabelBlurred        lipgloss.Style
 379			InputLabelFocused        lipgloss.Style
 380			InputRequiredMarkBlurred lipgloss.Style
 381			InputRequiredMarkFocused lipgloss.Style
 382		}
 383
 384		Commands struct{}
 385
 386		ImagePreview lipgloss.Style
 387
 388		Sessions struct {
 389			// styles for when we are in delete mode
 390			DeletingView                   lipgloss.Style
 391			DeletingItemFocused            lipgloss.Style
 392			DeletingItemBlurred            lipgloss.Style
 393			DeletingTitle                  lipgloss.Style
 394			DeletingMessage                lipgloss.Style
 395			DeletingTitleGradientFromColor color.Color
 396			DeletingTitleGradientToColor   color.Color
 397
 398			// styles for when we are in update mode
 399			RenamingView                   lipgloss.Style
 400			RenamingingItemFocused         lipgloss.Style
 401			RenamingItemBlurred            lipgloss.Style
 402			RenamingingTitle               lipgloss.Style
 403			RenamingingMessage             lipgloss.Style
 404			RenamingTitleGradientFromColor color.Color
 405			RenamingTitleGradientToColor   color.Color
 406			RenamingPlaceholder            lipgloss.Style
 407		}
 408	}
 409
 410	// Status bar and help
 411	Status struct {
 412		Help lipgloss.Style
 413
 414		ErrorIndicator   lipgloss.Style
 415		WarnIndicator    lipgloss.Style
 416		InfoIndicator    lipgloss.Style
 417		UpdateIndicator  lipgloss.Style
 418		SuccessIndicator lipgloss.Style
 419
 420		ErrorMessage   lipgloss.Style
 421		WarnMessage    lipgloss.Style
 422		InfoMessage    lipgloss.Style
 423		UpdateMessage  lipgloss.Style
 424		SuccessMessage lipgloss.Style
 425	}
 426
 427	// Completions popup styles
 428	Completions struct {
 429		Normal  lipgloss.Style
 430		Focused lipgloss.Style
 431		Match   lipgloss.Style
 432	}
 433
 434	// Attachments styles
 435	Attachments struct {
 436		Normal   lipgloss.Style
 437		Image    lipgloss.Style
 438		Text     lipgloss.Style
 439		Deleting lipgloss.Style
 440	}
 441
 442	// Pills styles for todo/queue pills
 443	Pills struct {
 444		Base            lipgloss.Style // Base pill style with padding
 445		Focused         lipgloss.Style // Focused pill with visible border
 446		Blurred         lipgloss.Style // Blurred pill with hidden border
 447		QueueItemPrefix lipgloss.Style // Prefix for queue list items
 448		HelpKey         lipgloss.Style // Keystroke hint style
 449		HelpText        lipgloss.Style // Help action text style
 450		Area            lipgloss.Style // Pills area container
 451		TodoSpinner     lipgloss.Style // Todo spinner style
 452	}
 453}
 454
 455// ChromaTheme converts the current markdown chroma styles to a chroma
 456// StyleEntries map.
 457func (s *Styles) ChromaTheme() chroma.StyleEntries {
 458	rules := s.Markdown.CodeBlock
 459
 460	return chroma.StyleEntries{
 461		chroma.Text:                chromaStyle(rules.Chroma.Text),
 462		chroma.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: new(charmtone.Smoke.Hex()),
 640			},
 641			// Margin: new(uint(defaultMargin)),
 642		},
 643		BlockQuote: ansi.StyleBlock{
 644			StylePrimitive: ansi.StylePrimitive{},
 645			Indent:         new(uint(1)),
 646			IndentToken:    new("β”‚ "),
 647		},
 648		List: ansi.StyleList{
 649			LevelIndent: defaultListIndent,
 650		},
 651		Heading: ansi.StyleBlock{
 652			StylePrimitive: ansi.StylePrimitive{
 653				BlockSuffix: "\n",
 654				Color:       new(charmtone.Malibu.Hex()),
 655				Bold:        new(true),
 656			},
 657		},
 658		H1: ansi.StyleBlock{
 659			StylePrimitive: ansi.StylePrimitive{
 660				Prefix:          " ",
 661				Suffix:          " ",
 662				Color:           new(charmtone.Zest.Hex()),
 663				BackgroundColor: new(charmtone.Charple.Hex()),
 664				Bold:            new(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:  new(charmtone.Guac.Hex()),
 691				Bold:   new(false),
 692			},
 693		},
 694		Strikethrough: ansi.StylePrimitive{
 695			CrossedOut: new(true),
 696		},
 697		Emph: ansi.StylePrimitive{
 698			Italic: new(true),
 699		},
 700		Strong: ansi.StylePrimitive{
 701			Bold: new(true),
 702		},
 703		HorizontalRule: ansi.StylePrimitive{
 704			Color:  new(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:     new(charmtone.Zinc.Hex()),
 720			Underline: new(true),
 721		},
 722		LinkText: ansi.StylePrimitive{
 723			Color: new(charmtone.Guac.Hex()),
 724			Bold:  new(true),
 725		},
 726		Image: ansi.StylePrimitive{
 727			Color:     new(charmtone.Cheeky.Hex()),
 728			Underline: new(true),
 729		},
 730		ImageText: ansi.StylePrimitive{
 731			Color:  new(charmtone.Squid.Hex()),
 732			Format: "Image: {{.text}} β†’",
 733		},
 734		Code: ansi.StyleBlock{
 735			StylePrimitive: ansi.StylePrimitive{
 736				Prefix:          " ",
 737				Suffix:          " ",
 738				Color:           new(charmtone.Coral.Hex()),
 739				BackgroundColor: new(charmtone.Charcoal.Hex()),
 740			},
 741		},
 742		CodeBlock: ansi.StyleCodeBlock{
 743			StyleBlock: ansi.StyleBlock{
 744				StylePrimitive: ansi.StylePrimitive{
 745					Color: new(charmtone.Charcoal.Hex()),
 746				},
 747				Margin: new(uint(defaultMargin)),
 748			},
 749			Chroma: &ansi.Chroma{
 750				Text: ansi.StylePrimitive{
 751					Color: new(charmtone.Smoke.Hex()),
 752				},
 753				Error: ansi.StylePrimitive{
 754					Color:           new(charmtone.Butter.Hex()),
 755					BackgroundColor: new(charmtone.Sriracha.Hex()),
 756				},
 757				Comment: ansi.StylePrimitive{
 758					Color: new(charmtone.Oyster.Hex()),
 759				},
 760				CommentPreproc: ansi.StylePrimitive{
 761					Color: new(charmtone.Bengal.Hex()),
 762				},
 763				Keyword: ansi.StylePrimitive{
 764					Color: new(charmtone.Malibu.Hex()),
 765				},
 766				KeywordReserved: ansi.StylePrimitive{
 767					Color: new(charmtone.Pony.Hex()),
 768				},
 769				KeywordNamespace: ansi.StylePrimitive{
 770					Color: new(charmtone.Pony.Hex()),
 771				},
 772				KeywordType: ansi.StylePrimitive{
 773					Color: new(charmtone.Guppy.Hex()),
 774				},
 775				Operator: ansi.StylePrimitive{
 776					Color: new(charmtone.Salmon.Hex()),
 777				},
 778				Punctuation: ansi.StylePrimitive{
 779					Color: new(charmtone.Zest.Hex()),
 780				},
 781				Name: ansi.StylePrimitive{
 782					Color: new(charmtone.Smoke.Hex()),
 783				},
 784				NameBuiltin: ansi.StylePrimitive{
 785					Color: new(charmtone.Cheeky.Hex()),
 786				},
 787				NameTag: ansi.StylePrimitive{
 788					Color: new(charmtone.Mauve.Hex()),
 789				},
 790				NameAttribute: ansi.StylePrimitive{
 791					Color: new(charmtone.Hazy.Hex()),
 792				},
 793				NameClass: ansi.StylePrimitive{
 794					Color:     new(charmtone.Salt.Hex()),
 795					Underline: new(true),
 796					Bold:      new(true),
 797				},
 798				NameDecorator: ansi.StylePrimitive{
 799					Color: new(charmtone.Citron.Hex()),
 800				},
 801				NameFunction: ansi.StylePrimitive{
 802					Color: new(charmtone.Guac.Hex()),
 803				},
 804				LiteralNumber: ansi.StylePrimitive{
 805					Color: new(charmtone.Julep.Hex()),
 806				},
 807				LiteralString: ansi.StylePrimitive{
 808					Color: new(charmtone.Cumin.Hex()),
 809				},
 810				LiteralStringEscape: ansi.StylePrimitive{
 811					Color: new(charmtone.Bok.Hex()),
 812				},
 813				GenericDeleted: ansi.StylePrimitive{
 814					Color: new(charmtone.Coral.Hex()),
 815				},
 816				GenericEmph: ansi.StylePrimitive{
 817					Italic: new(true),
 818				},
 819				GenericInserted: ansi.StylePrimitive{
 820					Color: new(charmtone.Guac.Hex()),
 821				},
 822				GenericStrong: ansi.StylePrimitive{
 823					Bold: new(true),
 824				},
 825				GenericSubheading: ansi.StylePrimitive{
 826					Color: new(charmtone.Squid.Hex()),
 827				},
 828				Background: ansi.StylePrimitive{
 829					BackgroundColor: new(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 := new(bgBaseLighter.Hex())
 845	plainFg := new(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:      new(uint(1)),
 859			IndentToken: new("β”‚ "),
 860		},
 861		List: ansi.StyleList{
 862			LevelIndent: defaultListIndent,
 863		},
 864		Heading: ansi.StyleBlock{
 865			StylePrimitive: ansi.StylePrimitive{
 866				BlockSuffix:     "\n",
 867				Bold:            new(true),
 868				Color:           plainFg,
 869				BackgroundColor: plainBg,
 870			},
 871		},
 872		H1: ansi.StyleBlock{
 873			StylePrimitive: ansi.StylePrimitive{
 874				Prefix:          " ",
 875				Suffix:          " ",
 876				Bold:            new(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:      new(true),
 918			Color:           plainFg,
 919			BackgroundColor: plainBg,
 920		},
 921		Emph: ansi.StylePrimitive{
 922			Italic:          new(true),
 923			Color:           plainFg,
 924			BackgroundColor: plainBg,
 925		},
 926		Strong: ansi.StylePrimitive{
 927			Bold:            new(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:       new(true),
 956			Color:           plainFg,
 957			BackgroundColor: plainBg,
 958		},
 959		LinkText: ansi.StylePrimitive{
 960			Bold:            new(true),
 961			Color:           plainFg,
 962			BackgroundColor: plainBg,
 963		},
 964		Image: ansi.StylePrimitive{
 965			Underline:       new(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: new(uint(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		Filename: diffview.LineStyle{
1060			LineNumber: lipgloss.NewStyle().
1061				Foreground(fgHalfMuted).
1062				Background(bgBaseLighter),
1063			Code: lipgloss.NewStyle().
1064				Foreground(fgHalfMuted).
1065				Background(bgBaseLighter),
1066		},
1067	}
1068
1069	s.FilePicker = filepicker.Styles{
1070		DisabledCursor:   base.Foreground(fgMuted),
1071		Cursor:           base.Foreground(fgBase),
1072		Symlink:          base.Foreground(fgSubtle),
1073		Directory:        base.Foreground(primary),
1074		File:             base.Foreground(fgBase),
1075		DisabledFile:     base.Foreground(fgMuted),
1076		DisabledSelected: base.Background(bgOverlay).Foreground(fgMuted),
1077		Permission:       base.Foreground(fgMuted),
1078		Selected:         base.Background(primary).Foreground(fgBase),
1079		FileSize:         base.Foreground(fgMuted),
1080		EmptyDirectory:   base.Foreground(fgMuted).PaddingLeft(2).SetString("Empty directory"),
1081	}
1082
1083	// borders
1084	s.FocusedMessageBorder = lipgloss.Border{Left: BorderThick}
1085
1086	// text presets
1087	s.Base = lipgloss.NewStyle().Foreground(fgBase)
1088	s.Muted = lipgloss.NewStyle().Foreground(fgMuted)
1089	s.HalfMuted = lipgloss.NewStyle().Foreground(fgHalfMuted)
1090	s.Subtle = lipgloss.NewStyle().Foreground(fgSubtle)
1091
1092	s.WindowTooSmall = s.Muted
1093
1094	// tag presets
1095	s.TagBase = lipgloss.NewStyle().Padding(0, 1).Foreground(white)
1096	s.TagError = s.TagBase.Background(redDark)
1097	s.TagInfo = s.TagBase.Background(blueLight)
1098
1099	// Compact header styles
1100	s.Header.Charm = base.Foreground(secondary)
1101	s.Header.Diagonals = base.Foreground(primary)
1102	s.Header.Percentage = s.Muted
1103	s.Header.Keystroke = s.Muted
1104	s.Header.KeystrokeTip = s.Subtle
1105	s.Header.WorkingDir = s.Muted
1106	s.Header.Separator = s.Subtle
1107
1108	s.CompactDetails.Title = s.Base
1109	s.CompactDetails.View = s.Base.Padding(0, 1, 1, 1).Border(lipgloss.RoundedBorder()).BorderForeground(borderFocus)
1110	s.CompactDetails.Version = s.Muted
1111
1112	// panels
1113	s.PanelMuted = s.Muted.Background(bgBaseLighter)
1114	s.PanelBase = lipgloss.NewStyle().Background(bgBase)
1115
1116	// code line number
1117	s.LineNumber = lipgloss.NewStyle().Foreground(fgMuted).Background(bgBase).PaddingRight(1).PaddingLeft(1)
1118
1119	// Tool calls
1120	s.ToolCallPending = lipgloss.NewStyle().Foreground(greenDark).SetString(ToolPending)
1121	s.ToolCallError = lipgloss.NewStyle().Foreground(redDark).SetString(ToolError)
1122	s.ToolCallSuccess = lipgloss.NewStyle().Foreground(green).SetString(ToolSuccess)
1123	// Cancelled uses muted tone but same glyph as pending
1124	s.ToolCallCancelled = s.Muted.SetString(ToolPending)
1125	s.EarlyStateMessage = s.Subtle.PaddingLeft(2)
1126
1127	// Tool rendering styles
1128	s.Tool.IconPending = base.Foreground(greenDark).SetString(ToolPending)
1129	s.Tool.IconSuccess = base.Foreground(green).SetString(ToolSuccess)
1130	s.Tool.IconError = base.Foreground(redDark).SetString(ToolError)
1131	s.Tool.IconCancelled = s.Muted.SetString(ToolPending)
1132
1133	s.Tool.NameNormal = base.Foreground(blue)
1134	s.Tool.NameNested = base.Foreground(blue)
1135
1136	s.Tool.ParamMain = s.Subtle
1137	s.Tool.ParamKey = s.Subtle
1138
1139	// Content rendering - prepared styles that accept width parameter
1140	s.Tool.ContentLine = s.Muted.Background(bgBaseLighter)
1141	s.Tool.ContentTruncation = s.Muted.Background(bgBaseLighter)
1142	s.Tool.ContentCodeLine = s.Base.Background(bgBase).PaddingLeft(2)
1143	s.Tool.ContentCodeTruncation = s.Muted.Background(bgBase).PaddingLeft(2)
1144	s.Tool.ContentCodeBg = bgBase
1145	s.Tool.Body = base.PaddingLeft(2)
1146
1147	// Deprecated - kept for backward compatibility
1148	s.Tool.ContentBg = s.Muted.Background(bgBaseLighter)
1149	s.Tool.ContentText = s.Muted
1150	s.Tool.ContentLineNumber = base.Foreground(fgMuted).Background(bgBase).PaddingRight(1).PaddingLeft(1)
1151
1152	s.Tool.StateWaiting = base.Foreground(fgSubtle)
1153	s.Tool.StateCancelled = base.Foreground(fgSubtle)
1154
1155	s.Tool.ErrorTag = base.Padding(0, 1).Background(red).Foreground(white)
1156	s.Tool.ErrorMessage = base.Foreground(fgHalfMuted)
1157
1158	// Diff and multi-edit styles
1159	s.Tool.DiffTruncation = s.Muted.Background(bgBaseLighter).PaddingLeft(2)
1160	s.Tool.NoteTag = base.Padding(0, 1).Background(info).Foreground(white)
1161	s.Tool.NoteMessage = base.Foreground(fgHalfMuted)
1162
1163	// Job header styles
1164	s.Tool.JobIconPending = base.Foreground(greenDark)
1165	s.Tool.JobIconError = base.Foreground(redDark)
1166	s.Tool.JobIconSuccess = base.Foreground(green)
1167	s.Tool.JobToolName = base.Foreground(blue)
1168	s.Tool.JobAction = base.Foreground(blueDark)
1169	s.Tool.JobPID = s.Muted
1170	s.Tool.JobDescription = s.Subtle
1171
1172	// Agent task styles
1173	s.Tool.AgentTaskTag = base.Bold(true).Padding(0, 1).MarginLeft(2).Background(blueLight).Foreground(white)
1174	s.Tool.AgentPrompt = s.Muted
1175
1176	// Agentic fetch styles
1177	s.Tool.AgenticFetchPromptTag = base.Bold(true).Padding(0, 1).MarginLeft(2).Background(green).Foreground(border)
1178
1179	// Todo styles
1180	s.Tool.TodoRatio = base.Foreground(blueDark)
1181	s.Tool.TodoCompletedIcon = base.Foreground(green)
1182	s.Tool.TodoInProgressIcon = base.Foreground(greenDark)
1183	s.Tool.TodoPendingIcon = base.Foreground(fgMuted)
1184
1185	// MCP styles
1186	s.Tool.MCPName = base.Foreground(blue)
1187	s.Tool.MCPToolName = base.Foreground(blueDark)
1188	s.Tool.MCPArrow = base.Foreground(blue).SetString(ArrowRightIcon)
1189
1190	// Loading indicators for images, skills
1191	s.Tool.ResourceLoadedText = base.Foreground(green)
1192	s.Tool.ResourceLoadedIndicator = base.Foreground(greenDark)
1193	s.Tool.ResourceName = base
1194	s.Tool.MediaType = base
1195	s.Tool.ResourceSize = base.Foreground(fgMuted)
1196
1197	// Docker MCP styles
1198	s.Tool.DockerMCPActionAdd = base.Foreground(greenLight)
1199	s.Tool.DockerMCPActionDel = base.Foreground(red)
1200
1201	// Buttons
1202	s.ButtonFocus = lipgloss.NewStyle().Foreground(white).Background(secondary)
1203	s.ButtonBlur = s.Base.Background(bgSubtle)
1204
1205	// Borders
1206	s.BorderFocus = lipgloss.NewStyle().BorderForeground(borderFocus).Border(lipgloss.RoundedBorder()).Padding(1, 2)
1207
1208	// Editor
1209	s.EditorPromptNormalFocused = lipgloss.NewStyle().Foreground(greenDark).SetString("::: ")
1210	s.EditorPromptNormalBlurred = s.EditorPromptNormalFocused.Foreground(fgMuted)
1211	s.EditorPromptYoloIconFocused = lipgloss.NewStyle().MarginRight(1).Foreground(charmtone.Oyster).Background(charmtone.Citron).Bold(true).SetString(" ! ")
1212	s.EditorPromptYoloIconBlurred = s.EditorPromptYoloIconFocused.Foreground(charmtone.Pepper).Background(charmtone.Squid)
1213	s.EditorPromptYoloDotsFocused = lipgloss.NewStyle().MarginRight(1).Foreground(charmtone.Zest).SetString(":::")
1214	s.EditorPromptYoloDotsBlurred = s.EditorPromptYoloDotsFocused.Foreground(charmtone.Squid)
1215
1216	s.RadioOn = s.HalfMuted.SetString(RadioOn)
1217	s.RadioOff = s.HalfMuted.SetString(RadioOff)
1218
1219	// Logo colors
1220	s.LogoFieldColor = primary
1221	s.LogoTitleColorA = secondary
1222	s.LogoTitleColorB = primary
1223	s.LogoCharmColor = secondary
1224	s.LogoVersionColor = primary
1225
1226	// Section
1227	s.Section.Title = s.Subtle
1228	s.Section.Line = s.Base.Foreground(charmtone.Charcoal)
1229
1230	// Initialize
1231	s.Initialize.Header = s.Base
1232	s.Initialize.Content = s.Muted
1233	s.Initialize.Accent = s.Base.Foreground(greenDark)
1234
1235	// LSP and MCP status.
1236	s.ResourceGroupTitle = lipgloss.NewStyle().Foreground(charmtone.Oyster)
1237	s.ResourceOfflineIcon = lipgloss.NewStyle().Foreground(charmtone.Iron).SetString("●")
1238	s.ResourceBusyIcon = s.ResourceOfflineIcon.Foreground(charmtone.Citron)
1239	s.ResourceErrorIcon = s.ResourceOfflineIcon.Foreground(charmtone.Coral)
1240	s.ResourceOnlineIcon = s.ResourceOfflineIcon.Foreground(charmtone.Guac)
1241	s.ResourceName = lipgloss.NewStyle().Foreground(charmtone.Squid)
1242	s.ResourceStatus = lipgloss.NewStyle().Foreground(charmtone.Oyster)
1243	s.ResourceAdditionalText = lipgloss.NewStyle().Foreground(charmtone.Oyster)
1244
1245	// LSP
1246	s.LSP.ErrorDiagnostic = s.Base.Foreground(redDark)
1247	s.LSP.WarningDiagnostic = s.Base.Foreground(warning)
1248	s.LSP.HintDiagnostic = s.Base.Foreground(fgHalfMuted)
1249	s.LSP.InfoDiagnostic = s.Base.Foreground(info)
1250
1251	// Files
1252	s.Files.Path = s.Muted
1253	s.Files.Additions = s.Base.Foreground(greenDark)
1254	s.Files.Deletions = s.Base.Foreground(redDark)
1255
1256	// Chat
1257	messageFocussedBorder := lipgloss.Border{
1258		Left: "β–Œ",
1259	}
1260
1261	s.Chat.Message.NoContent = lipgloss.NewStyle().Foreground(fgBase)
1262	s.Chat.Message.UserBlurred = s.Chat.Message.NoContent.PaddingLeft(1).BorderLeft(true).
1263		BorderForeground(primary).BorderStyle(normalBorder)
1264	s.Chat.Message.UserFocused = s.Chat.Message.NoContent.PaddingLeft(1).BorderLeft(true).
1265		BorderForeground(primary).BorderStyle(messageFocussedBorder)
1266	s.Chat.Message.AssistantBlurred = s.Chat.Message.NoContent.PaddingLeft(2)
1267	s.Chat.Message.AssistantFocused = s.Chat.Message.NoContent.PaddingLeft(1).BorderLeft(true).
1268		BorderForeground(greenDark).BorderStyle(messageFocussedBorder)
1269	s.Chat.Message.Thinking = lipgloss.NewStyle().MaxHeight(10)
1270	s.Chat.Message.ErrorTag = lipgloss.NewStyle().Padding(0, 1).
1271		Background(red).Foreground(white)
1272	s.Chat.Message.ErrorTitle = lipgloss.NewStyle().Foreground(fgHalfMuted)
1273	s.Chat.Message.ErrorDetails = lipgloss.NewStyle().Foreground(fgSubtle)
1274
1275	// Message item styles
1276	s.Chat.Message.ToolCallFocused = s.Muted.PaddingLeft(1).
1277		BorderStyle(messageFocussedBorder).
1278		BorderLeft(true).
1279		BorderForeground(greenDark)
1280	s.Chat.Message.ToolCallBlurred = s.Muted.PaddingLeft(2)
1281	// No padding or border for compact tool calls within messages
1282	s.Chat.Message.ToolCallCompact = s.Muted
1283	s.Chat.Message.SectionHeader = s.Base.PaddingLeft(2)
1284	s.Chat.Message.AssistantInfoIcon = s.Subtle
1285	s.Chat.Message.AssistantInfoModel = s.Muted
1286	s.Chat.Message.AssistantInfoProvider = s.Subtle
1287	s.Chat.Message.AssistantInfoDuration = s.Subtle
1288
1289	// Thinking section styles
1290	s.Chat.Message.ThinkingBox = s.Subtle.Background(bgBaseLighter)
1291	s.Chat.Message.ThinkingTruncationHint = s.Muted
1292	s.Chat.Message.ThinkingFooterTitle = s.Muted
1293	s.Chat.Message.ThinkingFooterDuration = s.Subtle
1294
1295	// Text selection.
1296	s.TextSelection = lipgloss.NewStyle().Foreground(charmtone.Salt).Background(charmtone.Charple)
1297
1298	// Dialog styles
1299	s.Dialog.Title = base.Padding(0, 1).Foreground(primary)
1300	s.Dialog.TitleText = base.Foreground(primary)
1301	s.Dialog.TitleError = base.Foreground(red)
1302	s.Dialog.TitleAccent = base.Foreground(green).Bold(true)
1303	s.Dialog.View = base.Border(lipgloss.RoundedBorder()).BorderForeground(borderFocus)
1304	s.Dialog.PrimaryText = base.Padding(0, 1).Foreground(primary)
1305	s.Dialog.SecondaryText = base.Padding(0, 1).Foreground(fgSubtle)
1306	s.Dialog.HelpView = base.Padding(0, 1).AlignHorizontal(lipgloss.Left)
1307	s.Dialog.Help.ShortKey = base.Foreground(fgMuted)
1308	s.Dialog.Help.ShortDesc = base.Foreground(fgSubtle)
1309	s.Dialog.Help.ShortSeparator = base.Foreground(border)
1310	s.Dialog.Help.Ellipsis = base.Foreground(border)
1311	s.Dialog.Help.FullKey = base.Foreground(fgMuted)
1312	s.Dialog.Help.FullDesc = base.Foreground(fgSubtle)
1313	s.Dialog.Help.FullSeparator = base.Foreground(border)
1314	s.Dialog.NormalItem = base.Padding(0, 1).Foreground(fgBase)
1315	s.Dialog.SelectedItem = base.Padding(0, 1).Background(primary).Foreground(fgBase)
1316	s.Dialog.InputPrompt = base.Margin(1, 1)
1317
1318	s.Dialog.List = base.Margin(0, 0, 1, 0)
1319	s.Dialog.ContentPanel = base.Background(bgSubtle).Foreground(fgBase).Padding(1, 2)
1320	s.Dialog.Spinner = base.Foreground(secondary)
1321	s.Dialog.ScrollbarThumb = base.Foreground(secondary)
1322	s.Dialog.ScrollbarTrack = base.Foreground(border)
1323
1324	s.Dialog.ImagePreview = lipgloss.NewStyle().Padding(0, 1).Foreground(fgSubtle)
1325
1326	s.Dialog.Arguments.Content = base.Padding(1)
1327	s.Dialog.Arguments.Description = base.MarginBottom(1).MaxHeight(3)
1328	s.Dialog.Arguments.InputLabelBlurred = base.Foreground(fgMuted)
1329	s.Dialog.Arguments.InputLabelFocused = base.Bold(true)
1330	s.Dialog.Arguments.InputRequiredMarkBlurred = base.Foreground(fgMuted).SetString("*")
1331	s.Dialog.Arguments.InputRequiredMarkFocused = base.Foreground(primary).Bold(true).SetString("*")
1332
1333	s.Dialog.Sessions.DeletingTitle = s.Dialog.Title.Foreground(red)
1334	s.Dialog.Sessions.DeletingView = s.Dialog.View.BorderForeground(red)
1335	s.Dialog.Sessions.DeletingMessage = s.Base.Padding(1)
1336	s.Dialog.Sessions.DeletingTitleGradientFromColor = red
1337	s.Dialog.Sessions.DeletingTitleGradientToColor = s.Primary
1338	s.Dialog.Sessions.DeletingItemBlurred = s.Dialog.NormalItem.Foreground(fgSubtle)
1339	s.Dialog.Sessions.DeletingItemFocused = s.Dialog.SelectedItem.Background(red).Foreground(charmtone.Butter)
1340
1341	s.Dialog.Sessions.RenamingingTitle = s.Dialog.Title.Foreground(charmtone.Zest)
1342	s.Dialog.Sessions.RenamingView = s.Dialog.View.BorderForeground(charmtone.Zest)
1343	s.Dialog.Sessions.RenamingingMessage = s.Base.Padding(1)
1344	s.Dialog.Sessions.RenamingTitleGradientFromColor = charmtone.Zest
1345	s.Dialog.Sessions.RenamingTitleGradientToColor = charmtone.Bok
1346	s.Dialog.Sessions.RenamingItemBlurred = s.Dialog.NormalItem.Foreground(fgSubtle)
1347	s.Dialog.Sessions.RenamingingItemFocused = s.Dialog.SelectedItem.UnsetBackground().UnsetForeground()
1348	s.Dialog.Sessions.RenamingPlaceholder = base.Foreground(charmtone.Squid)
1349
1350	s.Status.Help = lipgloss.NewStyle().Padding(0, 1)
1351	s.Status.SuccessIndicator = base.Foreground(bgSubtle).Background(green).Padding(0, 1).Bold(true).SetString("OKAY!")
1352	s.Status.InfoIndicator = s.Status.SuccessIndicator
1353	s.Status.UpdateIndicator = s.Status.SuccessIndicator.SetString("HEY!")
1354	s.Status.WarnIndicator = s.Status.SuccessIndicator.Foreground(bgOverlay).Background(yellow).SetString("WARNING")
1355	s.Status.ErrorIndicator = s.Status.SuccessIndicator.Foreground(bgBase).Background(red).SetString("ERROR")
1356	s.Status.SuccessMessage = base.Foreground(bgSubtle).Background(greenDark).Padding(0, 1)
1357	s.Status.InfoMessage = s.Status.SuccessMessage
1358	s.Status.UpdateMessage = s.Status.SuccessMessage
1359	s.Status.WarnMessage = s.Status.SuccessMessage.Foreground(bgOverlay).Background(warning)
1360	s.Status.ErrorMessage = s.Status.SuccessMessage.Foreground(white).Background(redDark)
1361
1362	// Completions styles
1363	s.Completions.Normal = base.Background(bgSubtle).Foreground(fgBase)
1364	s.Completions.Focused = base.Background(primary).Foreground(white)
1365	s.Completions.Match = base.Underline(true)
1366
1367	// Attachments styles
1368	attachmentIconStyle := base.Foreground(bgSubtle).Background(green).Padding(0, 1)
1369	s.Attachments.Image = attachmentIconStyle.SetString(ImageIcon)
1370	s.Attachments.Text = attachmentIconStyle.SetString(TextIcon)
1371	s.Attachments.Normal = base.Padding(0, 1).MarginRight(1).Background(fgMuted).Foreground(fgBase)
1372	s.Attachments.Deleting = base.Padding(0, 1).Bold(true).Background(red).Foreground(fgBase)
1373
1374	// Pills styles
1375	s.Pills.Base = base.Padding(0, 1)
1376	s.Pills.Focused = base.Padding(0, 1).BorderStyle(lipgloss.RoundedBorder()).BorderForeground(bgOverlay)
1377	s.Pills.Blurred = base.Padding(0, 1).BorderStyle(lipgloss.HiddenBorder())
1378	s.Pills.QueueItemPrefix = s.Muted.SetString("  β€’")
1379	s.Pills.HelpKey = s.Muted
1380	s.Pills.HelpText = s.Subtle
1381	s.Pills.Area = base
1382	s.Pills.TodoSpinner = base.Foreground(greenDark)
1383
1384	return s
1385}
1386
1387func chromaStyle(style ansi.StylePrimitive) string {
1388	var s strings.Builder
1389
1390	if style.Color != nil {
1391		s.WriteString(*style.Color)
1392	}
1393	if style.BackgroundColor != nil {
1394		if s.Len() > 0 {
1395			s.WriteString(" ")
1396		}
1397		s.WriteString("bg:")
1398		s.WriteString(*style.BackgroundColor)
1399	}
1400	if style.Italic != nil && *style.Italic {
1401		if s.Len() > 0 {
1402			s.WriteString(" ")
1403		}
1404		s.WriteString("italic")
1405	}
1406	if style.Bold != nil && *style.Bold {
1407		if s.Len() > 0 {
1408			s.WriteString(" ")
1409		}
1410		s.WriteString("bold")
1411	}
1412	if style.Underline != nil && *style.Underline {
1413		if s.Len() > 0 {
1414			s.WriteString(" ")
1415		}
1416		s.WriteString("underline")
1417	}
1418
1419	return s.String()
1420}