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