styles.go

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