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