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