styles.go

   1package styles
   2
   3import (
   4	"image/color"
   5	"strings"
   6
   7	"charm.land/bubbles/v2/filepicker"
   8	"charm.land/bubbles/v2/help"
   9	"charm.land/bubbles/v2/textarea"
  10	"charm.land/bubbles/v2/textinput"
  11	tea "charm.land/bubbletea/v2"
  12	"charm.land/glamour/v2/ansi"
  13	"charm.land/lipgloss/v2"
  14	"github.com/alecthomas/chroma/v2"
  15	"github.com/charmbracelet/crush/internal/ui/diffview"
  16	"github.com/charmbracelet/x/exp/charmtone"
  17)
  18
  19const (
  20	CheckIcon   string = "βœ“"
  21	SpinnerIcon string = "β‹―"
  22	LoadingIcon string = "⟳"
  23	ModelIcon   string = "β—‡"
  24
  25	ArrowRightIcon string = "β†’"
  26
  27	ToolPending string = "●"
  28	ToolSuccess string = "βœ“"
  29	ToolError   string = "Γ—"
  30
  31	RadioOn  string = "β—‰"
  32	RadioOff string = "β—‹"
  33
  34	BorderThin  string = "β”‚"
  35	BorderThick string = "β–Œ"
  36
  37	SectionSeparator string = "─"
  38
  39	TodoCompletedIcon  string = "βœ“"
  40	TodoPendingIcon    string = "β€’"
  41	TodoInProgressIcon string = "β†’"
  42
  43	ImageIcon string = "β– "
  44	TextIcon  string = "≑"
  45
  46	ScrollbarThumb string = "┃"
  47	ScrollbarTrack string = "β”‚"
  48
  49	LSPErrorIcon   string = "E"
  50	LSPWarningIcon string = "W"
  51	LSPInfoIcon    string = "I"
  52	LSPHintIcon    string = "H"
  53)
  54
  55const (
  56	defaultMargin     = 2
  57	defaultListIndent = 2
  58)
  59
  60type Styles struct {
  61	// Header
  62	Header struct {
  63		Charm             lipgloss.Style // Style for "Charmβ„’" label
  64		Diagonals         lipgloss.Style // Style for diagonal separators (β•±)
  65		Percentage        lipgloss.Style // Style for context percentage
  66		Keystroke         lipgloss.Style // Style for keystroke hints (e.g., "ctrl+d")
  67		KeystrokeTip      lipgloss.Style // Style for keystroke action text (e.g., "open", "close")
  68		WorkingDir        lipgloss.Style // Style for current working directory
  69		Separator         lipgloss.Style // Style for separator dots (β€’)
  70		Wrapper           lipgloss.Style // Outer container for the entire header row
  71		LogoGradCanvas    lipgloss.Style // Canvas for the compact "CRUSH" gradient
  72		LogoGradFromColor color.Color    // "CRUSH" wordmark gradient start
  73		LogoGradToColor   color.Color    // "CRUSH" wordmark gradient end
  74	}
  75
  76	CompactDetails struct {
  77		View    lipgloss.Style
  78		Version lipgloss.Style
  79		Title   lipgloss.Style
  80	}
  81
  82	// Tool calls
  83	ToolCallSuccess lipgloss.Style
  84
  85	// Text selection
  86	TextSelection lipgloss.Style
  87
  88	// Markdown & Chroma
  89	Markdown      ansi.StyleConfig
  90	QuietMarkdown ansi.StyleConfig
  91
  92	// Inputs
  93	TextInput textinput.Styles
  94
  95	// Help
  96	Help help.Styles
  97
  98	// Diff
  99	Diff diffview.Style
 100
 101	// FilePicker
 102	FilePicker filepicker.Styles
 103
 104	// Buttons
 105	Button struct {
 106		Focused lipgloss.Style
 107		Blurred lipgloss.Style
 108	}
 109
 110	// Editor
 111	Editor struct {
 112		Textarea textarea.Styles
 113
 114		// Normal mode prompt (default "::: ").
 115		PromptNormalFocused lipgloss.Style
 116		PromptNormalBlurred lipgloss.Style
 117
 118		// YOLO mode prompt (" ! " icon + ":::" dots).
 119		PromptYoloIconFocused lipgloss.Style
 120		PromptYoloIconBlurred lipgloss.Style
 121		PromptYoloDotsFocused lipgloss.Style
 122		PromptYoloDotsBlurred lipgloss.Style
 123	}
 124
 125	// Radio
 126	Radio struct {
 127		On    lipgloss.Style
 128		Off   lipgloss.Style
 129		Label lipgloss.Style // Text next to a radio button
 130	}
 131
 132	// Background
 133	Background color.Color
 134
 135	// Logo
 136	Logo struct {
 137		FieldColor         color.Color
 138		TitleColorA        color.Color
 139		TitleColorB        color.Color
 140		CharmColor         color.Color
 141		VersionColor       color.Color
 142		SmallCharm         lipgloss.Style // "Charmβ„’" label in SmallRender
 143		SmallDiagonals     lipgloss.Style // Diagonal line fill in SmallRender
 144		GradCanvas         lipgloss.Style // Blank canvas for gradient painting
 145		SmallGradFromColor color.Color    // Small "Crush" wordmark gradient start
 146		SmallGradToColor   color.Color    // Small "Crush" wordmark gradient end
 147	}
 148
 149	// Working indicator gradient (spinners/shimmers on assistant "thinking",
 150	// tool-call pending, CLI generating, startup).
 151	WorkingGradFromColor color.Color
 152	WorkingGradToColor   color.Color
 153	WorkingLabelColor    color.Color // Label text color next to the indicator
 154
 155	// Section Title
 156	Section struct {
 157		Title lipgloss.Style
 158		Line  lipgloss.Style
 159	}
 160
 161	// Initialize
 162	Initialize struct {
 163		Header  lipgloss.Style
 164		Content lipgloss.Style
 165		Accent  lipgloss.Style
 166	}
 167
 168	// LSP
 169	LSP struct {
 170		ErrorDiagnostic   lipgloss.Style
 171		WarningDiagnostic lipgloss.Style
 172		HintDiagnostic    lipgloss.Style
 173		InfoDiagnostic    lipgloss.Style
 174	}
 175
 176	// Sidebar
 177	Sidebar struct {
 178		SessionTitle lipgloss.Style // Current session title at top of sidebar
 179		WorkingDir   lipgloss.Style // Working directory path (PrettyPath)
 180	}
 181
 182	// ModelInfo (model name, provider, reasoning, token/cost summary)
 183	ModelInfo struct {
 184		Icon             lipgloss.Style // Model icon (β—‡)
 185		Name             lipgloss.Style // Model name text
 186		Provider         lipgloss.Style // "via <provider>" text
 187		ProviderFallback lipgloss.Style // Provider on its own second line
 188		Reasoning        lipgloss.Style // Reasoning effort text
 189		TokenCount       lipgloss.Style // "(42K)" token count
 190		TokenPercentage  lipgloss.Style // "42%" percent of context window
 191		Cost             lipgloss.Style // "$0.42" cost readout
 192	}
 193
 194	// Resource styles the LSP/MCP/skills sidebar lists: their heading,
 195	// each row's status icon, name, status text, and truncation hints.
 196	Resource struct {
 197		Heading         lipgloss.Style // Section header ("LSPs", "MCPs", "Skills")
 198		Name            lipgloss.Style // Resource name (e.g. "gopls")
 199		StatusText      lipgloss.Style // Row status description (e.g. "starting...")
 200		OfflineIcon     lipgloss.Style // Offline/unstarted/stopped status icon
 201		DisabledIcon    lipgloss.Style // Disabled status icon
 202		BusyIcon        lipgloss.Style // Busy/starting status icon
 203		ErrorIcon       lipgloss.Style // Error status icon
 204		OnlineIcon      lipgloss.Style // Online/ready status icon
 205		AdditionalText  lipgloss.Style // "None" and "…and N more" text
 206		CapabilityCount lipgloss.Style // "N tools" / "N prompts" / "N resources"
 207		RowTitleBase    lipgloss.Style // Base style applied over row titles in common.Status
 208		RowDescBase     lipgloss.Style // Base style applied over row descriptions in common.Status
 209		DefaultTitleFg  color.Color    // Default title color when opt is zero
 210		DefaultDescFg   color.Color    // Default description color when opt is zero
 211	}
 212
 213	// Files
 214	Files struct {
 215		Path           lipgloss.Style
 216		Additions      lipgloss.Style
 217		Deletions      lipgloss.Style
 218		SectionTitle   lipgloss.Style // "Modified Files" heading
 219		EmptyMessage   lipgloss.Style // "None" placeholder when no files
 220		TruncationHint lipgloss.Style // "…and N more" message
 221	}
 222
 223	// Chat
 224	// Messages - chat message item styles
 225	Messages struct {
 226		UserBlurred      lipgloss.Style
 227		UserFocused      lipgloss.Style
 228		AssistantBlurred lipgloss.Style
 229		AssistantFocused lipgloss.Style
 230		NoContent        lipgloss.Style
 231		Thinking         lipgloss.Style
 232		ErrorTag         lipgloss.Style
 233		ErrorTitle       lipgloss.Style
 234		ErrorDetails     lipgloss.Style
 235		ToolCallFocused  lipgloss.Style
 236		ToolCallCompact  lipgloss.Style
 237		ToolCallBlurred  lipgloss.Style
 238		SectionHeader    lipgloss.Style
 239
 240		// Thinking section styles
 241		ThinkingBox            lipgloss.Style // Background for thinking content
 242		ThinkingTruncationHint lipgloss.Style // "… (N lines hidden)" hint
 243		ThinkingFooterTitle    lipgloss.Style // "Thought for" text
 244		ThinkingFooterDuration lipgloss.Style // Duration value
 245		AssistantInfoIcon      lipgloss.Style
 246		AssistantInfoModel     lipgloss.Style
 247		AssistantInfoProvider  lipgloss.Style
 248		AssistantInfoDuration  lipgloss.Style
 249		AssistantCanceled      lipgloss.Style // Italic "Canceled" footer
 250	}
 251
 252	// Tool - styles for tool call rendering
 253	Tool struct {
 254		// Icon styles with tool status
 255		IconPending   lipgloss.Style
 256		IconSuccess   lipgloss.Style
 257		IconError     lipgloss.Style
 258		IconCancelled lipgloss.Style
 259
 260		// Tool name styles
 261		NameNormal lipgloss.Style // Top-level tool name
 262		NameNested lipgloss.Style // Nested child tool name (inside Agent/Agentic Fetch)
 263
 264		// Parameter list styles
 265		ParamMain lipgloss.Style
 266		ParamKey  lipgloss.Style
 267
 268		// Content rendering styles
 269		ContentLine           lipgloss.Style // Individual content line with background and width
 270		ContentTruncation     lipgloss.Style // Truncation message "… (N lines)"
 271		ContentCodeLine       lipgloss.Style // Code line with background and width
 272		ContentCodeTruncation lipgloss.Style // Code truncation message with bgBase
 273		ContentCodeBg         color.Color    // Background color for syntax highlighting
 274		Body                  lipgloss.Style // Body content padding (PaddingLeft(2))
 275
 276		// Deprecated - kept for backward compatibility
 277		ContentBg         lipgloss.Style // Content background
 278		ContentText       lipgloss.Style // Content text
 279		ContentLineNumber lipgloss.Style // Line numbers in code
 280
 281		// State message styles
 282		StateWaiting   lipgloss.Style // "Waiting for tool response..."
 283		StateCancelled lipgloss.Style // "Canceled."
 284
 285		// Error styles
 286		ErrorTag     lipgloss.Style // ERROR tag
 287		ErrorMessage lipgloss.Style // Error message text
 288
 289		// Diff styles
 290		DiffTruncation lipgloss.Style // Diff truncation message with padding
 291
 292		// Multi-edit note styles
 293		NoteTag     lipgloss.Style // NOTE tag (yellow background)
 294		NoteMessage lipgloss.Style // Note message text
 295
 296		// Job header styles (for bash jobs)
 297		JobIconPending lipgloss.Style // Pending job icon (green dark)
 298		JobIconError   lipgloss.Style // Error job icon (red dark)
 299		JobIconSuccess lipgloss.Style // Success job icon (green)
 300		JobToolName    lipgloss.Style // Job tool name "Bash" (blue)
 301		JobAction      lipgloss.Style // Action text (Start, Output, Kill)
 302		JobPID         lipgloss.Style // PID text
 303		JobDescription lipgloss.Style // Description text
 304
 305		// Agent task styles
 306		AgentTaskTag lipgloss.Style // Agent task tag (blue background, bold)
 307		AgentPrompt  lipgloss.Style // Agent prompt text
 308
 309		// Agentic fetch styles
 310		AgenticFetchPromptTag lipgloss.Style // Agentic fetch prompt tag (green background, bold)
 311
 312		// Todo styles
 313		TodoRatio          lipgloss.Style // Todo ratio (e.g., "2/5")
 314		TodoCompletedIcon  lipgloss.Style // Completed todo icon
 315		TodoInProgressIcon lipgloss.Style // In-progress todo icon
 316		TodoPendingIcon    lipgloss.Style // Pending todo icon
 317		TodoStatusNote     lipgloss.Style // " Β· completed N" / " Β· starting task" trailing note
 318		TodoItem           lipgloss.Style // Default body text for todo list items
 319		TodoJustStarted    lipgloss.Style // Text of the just-started todo in tool-call bodies
 320
 321		// MCP tools
 322		MCPName     lipgloss.Style // The mcp name
 323		MCPToolName lipgloss.Style // The mcp tool name
 324		MCPArrow    lipgloss.Style // The mcp arrow icon
 325
 326		// Images and external resources
 327		ResourceLoadedText      lipgloss.Style
 328		ResourceLoadedIndicator lipgloss.Style
 329		ResourceName            lipgloss.Style
 330		ResourceSize            lipgloss.Style
 331		MediaType               lipgloss.Style
 332
 333		// Hooks
 334		HookLabel        lipgloss.Style // "Hook" label
 335		HookName         lipgloss.Style // Hook command name
 336		HookMatcher      lipgloss.Style // Matcher regex pattern
 337		HookArrow        lipgloss.Style // Arrow indicator
 338		HookDetail       lipgloss.Style // Decision detail text
 339		HookOK           lipgloss.Style // "OK" status
 340		HookDenied       lipgloss.Style // "Denied" status
 341		HookDeniedLabel  lipgloss.Style // "Hook" label when denied
 342		HookDeniedReason lipgloss.Style // Denied reason text
 343		HookRewrote      lipgloss.Style // "Rewrote Input" indicator
 344
 345		// Action verb colors for tool-call headers.
 346		ActionCreate  lipgloss.Style // Constructive actions (e.g. "Add", "Create")
 347		ActionDestroy lipgloss.Style // Destructive actions (e.g. "Remove", "Delete")
 348
 349		// Tool result helpers.
 350		ResultEmpty      lipgloss.Style // "No results" placeholder
 351		ResultTruncation lipgloss.Style // "… and N more" truncation line
 352		ResultItemName   lipgloss.Style // Item name (left column in result lists)
 353		ResultItemDesc   lipgloss.Style // Item description (right column)
 354	}
 355
 356	// Dialog styles
 357	Dialog struct {
 358		Title              lipgloss.Style
 359		TitleText          lipgloss.Style
 360		TitleError         lipgloss.Style
 361		TitleAccent        lipgloss.Style
 362		TitleLineBase      lipgloss.Style // Base for the gradient β•±β•±β•± next to dialog titles
 363		TitleGradFromColor color.Color    // Default dialog title β•±β•±β•± gradient start
 364		TitleGradToColor   color.Color    // Default dialog title β•±β•±β•± gradient end
 365		// View is the main content area style.
 366		View          lipgloss.Style
 367		PrimaryText   lipgloss.Style
 368		SecondaryText lipgloss.Style
 369		// HelpView is the line that contains the help.
 370		HelpView lipgloss.Style
 371		Help     struct {
 372			Ellipsis       lipgloss.Style
 373			ShortKey       lipgloss.Style
 374			ShortDesc      lipgloss.Style
 375			ShortSeparator lipgloss.Style
 376			FullKey        lipgloss.Style
 377			FullDesc       lipgloss.Style
 378			FullSeparator  lipgloss.Style
 379		}
 380
 381		NormalItem   lipgloss.Style
 382		SelectedItem lipgloss.Style
 383		InputPrompt  lipgloss.Style
 384
 385		List lipgloss.Style
 386
 387		Spinner lipgloss.Style
 388
 389		// ContentPanel is used for content blocks with subtle background.
 390		ContentPanel lipgloss.Style
 391
 392		// Scrollbar styles for scrollable content.
 393		ScrollbarThumb lipgloss.Style
 394		ScrollbarTrack lipgloss.Style
 395
 396		// Arguments
 397		Arguments struct {
 398			Content                  lipgloss.Style
 399			Description              lipgloss.Style
 400			InputLabelBlurred        lipgloss.Style
 401			InputLabelFocused        lipgloss.Style
 402			InputRequiredMarkBlurred lipgloss.Style
 403			InputRequiredMarkFocused lipgloss.Style
 404		}
 405
 406		// ListItem styles the info-text rendered alongside list items (commands,
 407		// models, reasoning options). Sessions have their own overrides below.
 408		ListItem struct {
 409			InfoBlurred lipgloss.Style
 410			InfoFocused lipgloss.Style
 411		}
 412
 413		Models struct {
 414			ConfiguredText lipgloss.Style // "Configured" badge shown on the ModelGroup header
 415		}
 416
 417		Permissions struct {
 418			KeyText   lipgloss.Style // Left key cell of a key/value row
 419			ValueText lipgloss.Style // Right value cell of a key/value row
 420			ParamsBg  color.Color    // Background color behind highlighted JSON parameters
 421		}
 422
 423		Quit struct {
 424			Content lipgloss.Style // Wrapper for the quit dialog's inner content
 425			Frame   lipgloss.Style // Outer rounded border framing the quit dialog
 426		}
 427
 428		APIKey struct {
 429			Spinner lipgloss.Style // Loading spinner while validating the key
 430		}
 431
 432		OAuth struct {
 433			Spinner      lipgloss.Style // Loading spinner
 434			Instructions lipgloss.Style // Emphasized instruction text
 435			UserCode     lipgloss.Style // Prominent user code display
 436			Success      lipgloss.Style // Positive status text (e.g. "Authentication successful!")
 437			Link         lipgloss.Style // Underlined verification URL
 438			Enter        lipgloss.Style // "enter" keyword highlight in instructions
 439			ErrorText    lipgloss.Style // Error message when authentication fails
 440			StatusText   lipgloss.Style // Narrative status text ("Initializing...", "Verifying...", etc.)
 441			UserCodeBg   color.Color    // Background color of the centered user-code box
 442		}
 443
 444		ImagePreview lipgloss.Style
 445
 446		Sessions struct {
 447			// styles for when we are in delete mode
 448			DeletingView                   lipgloss.Style
 449			DeletingItemFocused            lipgloss.Style
 450			DeletingItemBlurred            lipgloss.Style
 451			DeletingTitle                  lipgloss.Style
 452			DeletingMessage                lipgloss.Style
 453			DeletingTitleGradientFromColor color.Color
 454			DeletingTitleGradientToColor   color.Color
 455
 456			// styles for when we are in update mode
 457			RenamingView                   lipgloss.Style
 458			RenamingingItemFocused         lipgloss.Style
 459			RenamingItemBlurred            lipgloss.Style
 460			RenamingingTitle               lipgloss.Style
 461			RenamingingMessage             lipgloss.Style
 462			RenamingTitleGradientFromColor color.Color
 463			RenamingTitleGradientToColor   color.Color
 464			RenamingPlaceholder            lipgloss.Style
 465
 466			InfoBlurred lipgloss.Style // Timestamp text on unfocused session items
 467			InfoFocused lipgloss.Style // Timestamp text on the focused session item
 468		}
 469	}
 470
 471	// Status bar and help
 472	Status struct {
 473		Help lipgloss.Style
 474
 475		ErrorIndicator   lipgloss.Style
 476		WarnIndicator    lipgloss.Style
 477		InfoIndicator    lipgloss.Style
 478		UpdateIndicator  lipgloss.Style
 479		SuccessIndicator lipgloss.Style
 480
 481		ErrorMessage   lipgloss.Style
 482		WarnMessage    lipgloss.Style
 483		InfoMessage    lipgloss.Style
 484		UpdateMessage  lipgloss.Style
 485		SuccessMessage lipgloss.Style
 486	}
 487
 488	// Completions popup styles
 489	Completions struct {
 490		Normal  lipgloss.Style
 491		Focused lipgloss.Style
 492		Match   lipgloss.Style
 493	}
 494
 495	// Attachments styles
 496	Attachments struct {
 497		Normal   lipgloss.Style
 498		Image    lipgloss.Style
 499		Text     lipgloss.Style
 500		Deleting lipgloss.Style
 501	}
 502
 503	// Pills styles for todo/queue pills
 504	Pills struct {
 505		Base               lipgloss.Style // Base pill style with padding
 506		Focused            lipgloss.Style // Focused pill with visible border
 507		Blurred            lipgloss.Style // Blurred pill with hidden border
 508		QueueItemPrefix    lipgloss.Style // Prefix for queue list items
 509		QueueItemText      lipgloss.Style // Queue list item body text
 510		QueueLabel         lipgloss.Style // "N Queued" label text
 511		QueueIconBase      lipgloss.Style // Base style for queue gradient triangles
 512		QueueGradFromColor color.Color    // Start color for queue indicator gradient
 513		QueueGradToColor   color.Color    // End color for queue indicator gradient
 514		TodoLabel          lipgloss.Style // "To-Do" label
 515		TodoProgress       lipgloss.Style // Todo ratio (e.g. "2/5")
 516		TodoCurrentTask    lipgloss.Style // Current in-progress task name
 517		TodoSpinner        lipgloss.Style // Todo spinner style
 518		HelpKey            lipgloss.Style // Keystroke hint style
 519		HelpText           lipgloss.Style // Help action text style
 520		Area               lipgloss.Style // Pills area container
 521	}
 522}
 523
 524// ChromaTheme converts the current markdown chroma styles to a chroma
 525// StyleEntries map.
 526func (s *Styles) ChromaTheme() chroma.StyleEntries {
 527	rules := s.Markdown.CodeBlock
 528
 529	return chroma.StyleEntries{
 530		chroma.Text:                chromaStyle(rules.Chroma.Text),
 531		chroma.Error:               chromaStyle(rules.Chroma.Error),
 532		chroma.Comment:             chromaStyle(rules.Chroma.Comment),
 533		chroma.CommentPreproc:      chromaStyle(rules.Chroma.CommentPreproc),
 534		chroma.Keyword:             chromaStyle(rules.Chroma.Keyword),
 535		chroma.KeywordReserved:     chromaStyle(rules.Chroma.KeywordReserved),
 536		chroma.KeywordNamespace:    chromaStyle(rules.Chroma.KeywordNamespace),
 537		chroma.KeywordType:         chromaStyle(rules.Chroma.KeywordType),
 538		chroma.Operator:            chromaStyle(rules.Chroma.Operator),
 539		chroma.Punctuation:         chromaStyle(rules.Chroma.Punctuation),
 540		chroma.Name:                chromaStyle(rules.Chroma.Name),
 541		chroma.NameBuiltin:         chromaStyle(rules.Chroma.NameBuiltin),
 542		chroma.NameTag:             chromaStyle(rules.Chroma.NameTag),
 543		chroma.NameAttribute:       chromaStyle(rules.Chroma.NameAttribute),
 544		chroma.NameClass:           chromaStyle(rules.Chroma.NameClass),
 545		chroma.NameConstant:        chromaStyle(rules.Chroma.NameConstant),
 546		chroma.NameDecorator:       chromaStyle(rules.Chroma.NameDecorator),
 547		chroma.NameException:       chromaStyle(rules.Chroma.NameException),
 548		chroma.NameFunction:        chromaStyle(rules.Chroma.NameFunction),
 549		chroma.NameOther:           chromaStyle(rules.Chroma.NameOther),
 550		chroma.Literal:             chromaStyle(rules.Chroma.Literal),
 551		chroma.LiteralNumber:       chromaStyle(rules.Chroma.LiteralNumber),
 552		chroma.LiteralDate:         chromaStyle(rules.Chroma.LiteralDate),
 553		chroma.LiteralString:       chromaStyle(rules.Chroma.LiteralString),
 554		chroma.LiteralStringEscape: chromaStyle(rules.Chroma.LiteralStringEscape),
 555		chroma.GenericDeleted:      chromaStyle(rules.Chroma.GenericDeleted),
 556		chroma.GenericEmph:         chromaStyle(rules.Chroma.GenericEmph),
 557		chroma.GenericInserted:     chromaStyle(rules.Chroma.GenericInserted),
 558		chroma.GenericStrong:       chromaStyle(rules.Chroma.GenericStrong),
 559		chroma.GenericSubheading:   chromaStyle(rules.Chroma.GenericSubheading),
 560		chroma.Background:          chromaStyle(rules.Chroma.Background),
 561	}
 562}
 563
 564// DialogHelpStyles returns the styles for dialog help.
 565func (s *Styles) DialogHelpStyles() help.Styles {
 566	return help.Styles(s.Dialog.Help)
 567}
 568
 569// DefaultStyles returns the default styles for the UI.
 570func DefaultStyles() Styles {
 571	var (
 572		primary   = charmtone.Charple
 573		secondary = charmtone.Dolly
 574		tertiary  = charmtone.Bok
 575		// accent    = charmtone.Zest
 576
 577		// Backgrounds
 578		bgBase        = charmtone.Pepper
 579		bgBaseLighter = charmtone.BBQ
 580		bgSubtle      = charmtone.Charcoal
 581		bgOverlay     = charmtone.Iron
 582
 583		// Foregrounds
 584		fgBase      = charmtone.Ash
 585		fgMuted     = charmtone.Squid
 586		fgHalfMuted = charmtone.Smoke
 587		fgSubtle    = charmtone.Oyster
 588		// fgSelected  = charmtone.Salt
 589
 590		// Borders
 591		border      = charmtone.Charcoal
 592		borderFocus = charmtone.Charple
 593
 594		// Status
 595		error   = charmtone.Sriracha
 596		warning = charmtone.Zest
 597		info    = charmtone.Malibu
 598
 599		// Colors
 600		white = charmtone.Butter
 601
 602		blueLight = charmtone.Sardine
 603		blue      = charmtone.Malibu
 604		blueDark  = charmtone.Damson
 605
 606		// yellow = charmtone.Mustard
 607		yellow = charmtone.Mustard
 608		// citron = charmtone.Citron
 609
 610		greenLight = charmtone.Bok
 611		green      = charmtone.Julep
 612		greenDark  = charmtone.Guac
 613		// greenLight = charmtone.Bok
 614
 615		red     = charmtone.Coral
 616		redDark = charmtone.Sriracha
 617		// redLight = charmtone.Salmon
 618		// cherry   = charmtone.Cherry
 619	)
 620
 621	normalBorder := lipgloss.NormalBorder()
 622
 623	base := lipgloss.NewStyle().Foreground(fgBase)
 624	muted := lipgloss.NewStyle().Foreground(fgMuted)
 625	subtle := lipgloss.NewStyle().Foreground(fgSubtle)
 626
 627	s := Styles{}
 628
 629	s.Background = bgBase
 630
 631	// Populate color fields
 632	s.WorkingGradFromColor = primary
 633	s.WorkingGradToColor = secondary
 634	s.WorkingLabelColor = fgBase
 635
 636	s.TextInput = textinput.Styles{
 637		Focused: textinput.StyleState{
 638			Text:        base,
 639			Placeholder: base.Foreground(fgSubtle),
 640			Prompt:      base.Foreground(tertiary),
 641			Suggestion:  base.Foreground(fgSubtle),
 642		},
 643		Blurred: textinput.StyleState{
 644			Text:        base.Foreground(fgMuted),
 645			Placeholder: base.Foreground(fgSubtle),
 646			Prompt:      base.Foreground(fgMuted),
 647			Suggestion:  base.Foreground(fgSubtle),
 648		},
 649		Cursor: textinput.CursorStyle{
 650			Color: secondary,
 651			Shape: tea.CursorBlock,
 652			Blink: true,
 653		},
 654	}
 655
 656	s.Editor.Textarea = textarea.Styles{
 657		Focused: textarea.StyleState{
 658			Base:             base,
 659			Text:             base,
 660			LineNumber:       base.Foreground(fgSubtle),
 661			CursorLine:       base,
 662			CursorLineNumber: base.Foreground(fgSubtle),
 663			Placeholder:      base.Foreground(fgSubtle),
 664			Prompt:           base.Foreground(tertiary),
 665		},
 666		Blurred: textarea.StyleState{
 667			Base:             base,
 668			Text:             base.Foreground(fgMuted),
 669			LineNumber:       base.Foreground(fgMuted),
 670			CursorLine:       base,
 671			CursorLineNumber: base.Foreground(fgMuted),
 672			Placeholder:      base.Foreground(fgSubtle),
 673			Prompt:           base.Foreground(fgMuted),
 674		},
 675		Cursor: textarea.CursorStyle{
 676			Color: secondary,
 677			Shape: tea.CursorBlock,
 678			Blink: true,
 679		},
 680	}
 681
 682	s.Markdown = ansi.StyleConfig{
 683		Document: ansi.StyleBlock{
 684			StylePrimitive: ansi.StylePrimitive{
 685				// BlockPrefix: "\n",
 686				// BlockSuffix: "\n",
 687				Color: new(charmtone.Smoke.Hex()),
 688			},
 689			// Margin: new(uint(defaultMargin)),
 690		},
 691		BlockQuote: ansi.StyleBlock{
 692			StylePrimitive: ansi.StylePrimitive{},
 693			Indent:         new(uint(1)),
 694			IndentToken:    new("β”‚ "),
 695		},
 696		List: ansi.StyleList{
 697			LevelIndent: defaultListIndent,
 698		},
 699		Heading: ansi.StyleBlock{
 700			StylePrimitive: ansi.StylePrimitive{
 701				BlockSuffix: "\n",
 702				Color:       new(charmtone.Malibu.Hex()),
 703				Bold:        new(true),
 704			},
 705		},
 706		H1: ansi.StyleBlock{
 707			StylePrimitive: ansi.StylePrimitive{
 708				Prefix:          " ",
 709				Suffix:          " ",
 710				Color:           new(charmtone.Zest.Hex()),
 711				BackgroundColor: new(charmtone.Charple.Hex()),
 712				Bold:            new(true),
 713			},
 714		},
 715		H2: ansi.StyleBlock{
 716			StylePrimitive: ansi.StylePrimitive{
 717				Prefix: "## ",
 718			},
 719		},
 720		H3: ansi.StyleBlock{
 721			StylePrimitive: ansi.StylePrimitive{
 722				Prefix: "### ",
 723			},
 724		},
 725		H4: ansi.StyleBlock{
 726			StylePrimitive: ansi.StylePrimitive{
 727				Prefix: "#### ",
 728			},
 729		},
 730		H5: ansi.StyleBlock{
 731			StylePrimitive: ansi.StylePrimitive{
 732				Prefix: "##### ",
 733			},
 734		},
 735		H6: ansi.StyleBlock{
 736			StylePrimitive: ansi.StylePrimitive{
 737				Prefix: "###### ",
 738				Color:  new(charmtone.Guac.Hex()),
 739				Bold:   new(false),
 740			},
 741		},
 742		Strikethrough: ansi.StylePrimitive{
 743			CrossedOut: new(true),
 744		},
 745		Emph: ansi.StylePrimitive{
 746			Italic: new(true),
 747		},
 748		Strong: ansi.StylePrimitive{
 749			Bold: new(true),
 750		},
 751		HorizontalRule: ansi.StylePrimitive{
 752			Color:  new(charmtone.Charcoal.Hex()),
 753			Format: "\n--------\n",
 754		},
 755		Item: ansi.StylePrimitive{
 756			BlockPrefix: "β€’ ",
 757		},
 758		Enumeration: ansi.StylePrimitive{
 759			BlockPrefix: ". ",
 760		},
 761		Task: ansi.StyleTask{
 762			StylePrimitive: ansi.StylePrimitive{},
 763			Ticked:         "[βœ“] ",
 764			Unticked:       "[ ] ",
 765		},
 766		Link: ansi.StylePrimitive{
 767			Color:     new(charmtone.Zinc.Hex()),
 768			Underline: new(true),
 769		},
 770		LinkText: ansi.StylePrimitive{
 771			Color: new(charmtone.Guac.Hex()),
 772			Bold:  new(true),
 773		},
 774		Image: ansi.StylePrimitive{
 775			Color:     new(charmtone.Cheeky.Hex()),
 776			Underline: new(true),
 777		},
 778		ImageText: ansi.StylePrimitive{
 779			Color:  new(charmtone.Squid.Hex()),
 780			Format: "Image: {{.text}} β†’",
 781		},
 782		Code: ansi.StyleBlock{
 783			StylePrimitive: ansi.StylePrimitive{
 784				Prefix:          " ",
 785				Suffix:          " ",
 786				Color:           new(charmtone.Coral.Hex()),
 787				BackgroundColor: new(charmtone.Charcoal.Hex()),
 788			},
 789		},
 790		CodeBlock: ansi.StyleCodeBlock{
 791			StyleBlock: ansi.StyleBlock{
 792				StylePrimitive: ansi.StylePrimitive{
 793					Color: new(charmtone.Charcoal.Hex()),
 794				},
 795				Margin: new(uint(defaultMargin)),
 796			},
 797			Chroma: &ansi.Chroma{
 798				Text: ansi.StylePrimitive{
 799					Color: new(charmtone.Smoke.Hex()),
 800				},
 801				Error: ansi.StylePrimitive{
 802					Color:           new(charmtone.Butter.Hex()),
 803					BackgroundColor: new(charmtone.Sriracha.Hex()),
 804				},
 805				Comment: ansi.StylePrimitive{
 806					Color: new(charmtone.Oyster.Hex()),
 807				},
 808				CommentPreproc: ansi.StylePrimitive{
 809					Color: new(charmtone.Bengal.Hex()),
 810				},
 811				Keyword: ansi.StylePrimitive{
 812					Color: new(charmtone.Malibu.Hex()),
 813				},
 814				KeywordReserved: ansi.StylePrimitive{
 815					Color: new(charmtone.Pony.Hex()),
 816				},
 817				KeywordNamespace: ansi.StylePrimitive{
 818					Color: new(charmtone.Pony.Hex()),
 819				},
 820				KeywordType: ansi.StylePrimitive{
 821					Color: new(charmtone.Guppy.Hex()),
 822				},
 823				Operator: ansi.StylePrimitive{
 824					Color: new(charmtone.Salmon.Hex()),
 825				},
 826				Punctuation: ansi.StylePrimitive{
 827					Color: new(charmtone.Zest.Hex()),
 828				},
 829				Name: ansi.StylePrimitive{
 830					Color: new(charmtone.Smoke.Hex()),
 831				},
 832				NameBuiltin: ansi.StylePrimitive{
 833					Color: new(charmtone.Cheeky.Hex()),
 834				},
 835				NameTag: ansi.StylePrimitive{
 836					Color: new(charmtone.Mauve.Hex()),
 837				},
 838				NameAttribute: ansi.StylePrimitive{
 839					Color: new(charmtone.Hazy.Hex()),
 840				},
 841				NameClass: ansi.StylePrimitive{
 842					Color:     new(charmtone.Salt.Hex()),
 843					Underline: new(true),
 844					Bold:      new(true),
 845				},
 846				NameDecorator: ansi.StylePrimitive{
 847					Color: new(charmtone.Citron.Hex()),
 848				},
 849				NameFunction: ansi.StylePrimitive{
 850					Color: new(charmtone.Guac.Hex()),
 851				},
 852				LiteralNumber: ansi.StylePrimitive{
 853					Color: new(charmtone.Julep.Hex()),
 854				},
 855				LiteralString: ansi.StylePrimitive{
 856					Color: new(charmtone.Cumin.Hex()),
 857				},
 858				LiteralStringEscape: ansi.StylePrimitive{
 859					Color: new(charmtone.Bok.Hex()),
 860				},
 861				GenericDeleted: ansi.StylePrimitive{
 862					Color: new(charmtone.Coral.Hex()),
 863				},
 864				GenericEmph: ansi.StylePrimitive{
 865					Italic: new(true),
 866				},
 867				GenericInserted: ansi.StylePrimitive{
 868					Color: new(charmtone.Guac.Hex()),
 869				},
 870				GenericStrong: ansi.StylePrimitive{
 871					Bold: new(true),
 872				},
 873				GenericSubheading: ansi.StylePrimitive{
 874					Color: new(charmtone.Squid.Hex()),
 875				},
 876				Background: ansi.StylePrimitive{
 877					BackgroundColor: new(charmtone.Charcoal.Hex()),
 878				},
 879			},
 880		},
 881		Table: ansi.StyleTable{
 882			StyleBlock: ansi.StyleBlock{
 883				StylePrimitive: ansi.StylePrimitive{},
 884			},
 885		},
 886		DefinitionDescription: ansi.StylePrimitive{
 887			BlockPrefix: "\n ",
 888		},
 889	}
 890
 891	// QuietMarkdown style - muted colors on subtle background for thinking content.
 892	plainBg := new(bgBaseLighter.Hex())
 893	plainFg := new(fgMuted.Hex())
 894	s.QuietMarkdown = ansi.StyleConfig{
 895		Document: ansi.StyleBlock{
 896			StylePrimitive: ansi.StylePrimitive{
 897				Color:           plainFg,
 898				BackgroundColor: plainBg,
 899			},
 900		},
 901		BlockQuote: ansi.StyleBlock{
 902			StylePrimitive: ansi.StylePrimitive{
 903				Color:           plainFg,
 904				BackgroundColor: plainBg,
 905			},
 906			Indent:      new(uint(1)),
 907			IndentToken: new("β”‚ "),
 908		},
 909		List: ansi.StyleList{
 910			LevelIndent: defaultListIndent,
 911		},
 912		Heading: ansi.StyleBlock{
 913			StylePrimitive: ansi.StylePrimitive{
 914				BlockSuffix:     "\n",
 915				Bold:            new(true),
 916				Color:           plainFg,
 917				BackgroundColor: plainBg,
 918			},
 919		},
 920		H1: ansi.StyleBlock{
 921			StylePrimitive: ansi.StylePrimitive{
 922				Prefix:          " ",
 923				Suffix:          " ",
 924				Bold:            new(true),
 925				Color:           plainFg,
 926				BackgroundColor: plainBg,
 927			},
 928		},
 929		H2: ansi.StyleBlock{
 930			StylePrimitive: ansi.StylePrimitive{
 931				Prefix:          "## ",
 932				Color:           plainFg,
 933				BackgroundColor: plainBg,
 934			},
 935		},
 936		H3: ansi.StyleBlock{
 937			StylePrimitive: ansi.StylePrimitive{
 938				Prefix:          "### ",
 939				Color:           plainFg,
 940				BackgroundColor: plainBg,
 941			},
 942		},
 943		H4: ansi.StyleBlock{
 944			StylePrimitive: ansi.StylePrimitive{
 945				Prefix:          "#### ",
 946				Color:           plainFg,
 947				BackgroundColor: plainBg,
 948			},
 949		},
 950		H5: ansi.StyleBlock{
 951			StylePrimitive: ansi.StylePrimitive{
 952				Prefix:          "##### ",
 953				Color:           plainFg,
 954				BackgroundColor: plainBg,
 955			},
 956		},
 957		H6: ansi.StyleBlock{
 958			StylePrimitive: ansi.StylePrimitive{
 959				Prefix:          "###### ",
 960				Color:           plainFg,
 961				BackgroundColor: plainBg,
 962			},
 963		},
 964		Strikethrough: ansi.StylePrimitive{
 965			CrossedOut:      new(true),
 966			Color:           plainFg,
 967			BackgroundColor: plainBg,
 968		},
 969		Emph: ansi.StylePrimitive{
 970			Italic:          new(true),
 971			Color:           plainFg,
 972			BackgroundColor: plainBg,
 973		},
 974		Strong: ansi.StylePrimitive{
 975			Bold:            new(true),
 976			Color:           plainFg,
 977			BackgroundColor: plainBg,
 978		},
 979		HorizontalRule: ansi.StylePrimitive{
 980			Format:          "\n--------\n",
 981			Color:           plainFg,
 982			BackgroundColor: plainBg,
 983		},
 984		Item: ansi.StylePrimitive{
 985			BlockPrefix:     "β€’ ",
 986			Color:           plainFg,
 987			BackgroundColor: plainBg,
 988		},
 989		Enumeration: ansi.StylePrimitive{
 990			BlockPrefix:     ". ",
 991			Color:           plainFg,
 992			BackgroundColor: plainBg,
 993		},
 994		Task: ansi.StyleTask{
 995			StylePrimitive: ansi.StylePrimitive{
 996				Color:           plainFg,
 997				BackgroundColor: plainBg,
 998			},
 999			Ticked:   "[βœ“] ",
1000			Unticked: "[ ] ",
1001		},
1002		Link: ansi.StylePrimitive{
1003			Underline:       new(true),
1004			Color:           plainFg,
1005			BackgroundColor: plainBg,
1006		},
1007		LinkText: ansi.StylePrimitive{
1008			Bold:            new(true),
1009			Color:           plainFg,
1010			BackgroundColor: plainBg,
1011		},
1012		Image: ansi.StylePrimitive{
1013			Underline:       new(true),
1014			Color:           plainFg,
1015			BackgroundColor: plainBg,
1016		},
1017		ImageText: ansi.StylePrimitive{
1018			Format:          "Image: {{.text}} β†’",
1019			Color:           plainFg,
1020			BackgroundColor: plainBg,
1021		},
1022		Code: ansi.StyleBlock{
1023			StylePrimitive: ansi.StylePrimitive{
1024				Prefix:          " ",
1025				Suffix:          " ",
1026				Color:           plainFg,
1027				BackgroundColor: plainBg,
1028			},
1029		},
1030		CodeBlock: ansi.StyleCodeBlock{
1031			StyleBlock: ansi.StyleBlock{
1032				StylePrimitive: ansi.StylePrimitive{
1033					Color:           plainFg,
1034					BackgroundColor: plainBg,
1035				},
1036				Margin: new(uint(defaultMargin)),
1037			},
1038		},
1039		Table: ansi.StyleTable{
1040			StyleBlock: ansi.StyleBlock{
1041				StylePrimitive: ansi.StylePrimitive{
1042					Color:           plainFg,
1043					BackgroundColor: plainBg,
1044				},
1045			},
1046		},
1047		DefinitionDescription: ansi.StylePrimitive{
1048			BlockPrefix:     "\n ",
1049			Color:           plainFg,
1050			BackgroundColor: plainBg,
1051		},
1052	}
1053
1054	s.Help = help.Styles{
1055		ShortKey:       base.Foreground(fgMuted),
1056		ShortDesc:      base.Foreground(fgSubtle),
1057		ShortSeparator: base.Foreground(border),
1058		Ellipsis:       base.Foreground(border),
1059		FullKey:        base.Foreground(fgMuted),
1060		FullDesc:       base.Foreground(fgSubtle),
1061		FullSeparator:  base.Foreground(border),
1062	}
1063
1064	s.Diff = diffview.Style{
1065		DividerLine: diffview.LineStyle{
1066			LineNumber: lipgloss.NewStyle().
1067				Foreground(fgHalfMuted).
1068				Background(bgBaseLighter),
1069			Code: lipgloss.NewStyle().
1070				Foreground(fgHalfMuted).
1071				Background(bgBaseLighter),
1072		},
1073		MissingLine: diffview.LineStyle{
1074			LineNumber: lipgloss.NewStyle().
1075				Background(bgBaseLighter),
1076			Code: lipgloss.NewStyle().
1077				Background(bgBaseLighter),
1078		},
1079		EqualLine: diffview.LineStyle{
1080			LineNumber: lipgloss.NewStyle().
1081				Foreground(fgMuted).
1082				Background(bgBase),
1083			Code: lipgloss.NewStyle().
1084				Foreground(fgMuted).
1085				Background(bgBase),
1086		},
1087		InsertLine: diffview.LineStyle{
1088			LineNumber: lipgloss.NewStyle().
1089				Foreground(lipgloss.Color("#629657")).
1090				Background(lipgloss.Color("#2b322a")),
1091			Symbol: lipgloss.NewStyle().
1092				Foreground(lipgloss.Color("#629657")).
1093				Background(lipgloss.Color("#323931")),
1094			Code: lipgloss.NewStyle().
1095				Background(lipgloss.Color("#323931")),
1096		},
1097		DeleteLine: diffview.LineStyle{
1098			LineNumber: lipgloss.NewStyle().
1099				Foreground(lipgloss.Color("#a45c59")).
1100				Background(lipgloss.Color("#312929")),
1101			Symbol: lipgloss.NewStyle().
1102				Foreground(lipgloss.Color("#a45c59")).
1103				Background(lipgloss.Color("#383030")),
1104			Code: lipgloss.NewStyle().
1105				Background(lipgloss.Color("#383030")),
1106		},
1107		Filename: diffview.LineStyle{
1108			LineNumber: lipgloss.NewStyle().
1109				Foreground(fgHalfMuted).
1110				Background(bgBaseLighter),
1111			Code: lipgloss.NewStyle().
1112				Foreground(fgHalfMuted).
1113				Background(bgBaseLighter),
1114		},
1115	}
1116
1117	s.FilePicker = filepicker.Styles{
1118		DisabledCursor:   base.Foreground(fgMuted),
1119		Cursor:           base.Foreground(fgBase),
1120		Symlink:          base.Foreground(fgSubtle),
1121		Directory:        base.Foreground(primary),
1122		File:             base.Foreground(fgBase),
1123		DisabledFile:     base.Foreground(fgMuted),
1124		DisabledSelected: base.Background(bgOverlay).Foreground(fgMuted),
1125		Permission:       base.Foreground(fgMuted),
1126		Selected:         base.Background(primary).Foreground(fgBase),
1127		FileSize:         base.Foreground(fgMuted),
1128		EmptyDirectory:   base.Foreground(fgMuted).PaddingLeft(2).SetString("Empty directory"),
1129	}
1130
1131	// borders
1132	s.ToolCallSuccess = lipgloss.NewStyle().Foreground(green).SetString(ToolSuccess)
1133
1134	s.Header.Charm = base.Foreground(secondary)
1135	s.Header.Diagonals = base.Foreground(primary)
1136	s.Header.Percentage = muted
1137	s.Header.Keystroke = muted
1138	s.Header.KeystrokeTip = subtle
1139	s.Header.WorkingDir = muted
1140	s.Header.Separator = subtle
1141	s.Header.Wrapper = lipgloss.NewStyle().Foreground(fgBase)
1142	s.Header.LogoGradCanvas = lipgloss.NewStyle()
1143	s.Header.LogoGradFromColor = secondary
1144	s.Header.LogoGradToColor = primary
1145
1146	s.CompactDetails.Title = base
1147	s.CompactDetails.View = base.Padding(0, 1, 1, 1).Border(lipgloss.RoundedBorder()).BorderForeground(borderFocus)
1148	s.CompactDetails.Version = lipgloss.NewStyle().Foreground(border)
1149
1150	// Tool rendering styles
1151	s.Tool.IconPending = base.Foreground(greenDark).SetString(ToolPending)
1152	s.Tool.IconSuccess = base.Foreground(green).SetString(ToolSuccess)
1153	s.Tool.IconError = base.Foreground(redDark).SetString(ToolError)
1154	s.Tool.IconCancelled = muted.SetString(ToolPending)
1155
1156	s.Tool.NameNormal = base.Foreground(blue)
1157	s.Tool.NameNested = base.Foreground(blue)
1158
1159	s.Tool.ParamMain = subtle
1160	s.Tool.ParamKey = subtle
1161
1162	// Content rendering - prepared styles that accept width parameter
1163	s.Tool.ContentLine = muted.Background(bgBaseLighter)
1164	s.Tool.ContentTruncation = muted.Background(bgBaseLighter)
1165	s.Tool.ContentCodeLine = base.Background(bgBase).PaddingLeft(2)
1166	s.Tool.ContentCodeTruncation = muted.Background(bgBase).PaddingLeft(2)
1167	s.Tool.ContentCodeBg = bgBase
1168	s.Tool.Body = base.PaddingLeft(2)
1169
1170	// Deprecated - kept for backward compatibility
1171	s.Tool.ContentBg = muted.Background(bgBaseLighter)
1172	s.Tool.ContentText = muted
1173	s.Tool.ContentLineNumber = base.Foreground(fgMuted).Background(bgBase).PaddingRight(1).PaddingLeft(1)
1174
1175	s.Tool.StateWaiting = base.Foreground(fgSubtle)
1176	s.Tool.StateCancelled = base.Foreground(fgSubtle)
1177
1178	s.Tool.ErrorTag = base.Padding(0, 1).Background(red).Foreground(white)
1179	s.Tool.ErrorMessage = base.Foreground(fgHalfMuted)
1180
1181	// Diff and multi-edit styles
1182	s.Tool.DiffTruncation = muted.Background(bgBaseLighter).PaddingLeft(2)
1183	s.Tool.NoteTag = base.Padding(0, 1).Background(info).Foreground(white)
1184	s.Tool.NoteMessage = base.Foreground(fgHalfMuted)
1185
1186	// Job header styles
1187	s.Tool.JobIconPending = base.Foreground(greenDark)
1188	s.Tool.JobIconError = base.Foreground(redDark)
1189	s.Tool.JobIconSuccess = base.Foreground(green)
1190	s.Tool.JobToolName = base.Foreground(blue)
1191	s.Tool.JobAction = base.Foreground(blueDark)
1192	s.Tool.JobPID = muted
1193	s.Tool.JobDescription = subtle
1194
1195	// Agent task styles
1196	s.Tool.AgentTaskTag = base.Bold(true).Padding(0, 1).MarginLeft(2).Background(blueLight).Foreground(white)
1197	s.Tool.AgentPrompt = muted
1198
1199	// Agentic fetch styles
1200	s.Tool.AgenticFetchPromptTag = base.Bold(true).Padding(0, 1).MarginLeft(2).Background(green).Foreground(border)
1201
1202	// Todo styles
1203	s.Tool.TodoRatio = base.Foreground(blueDark)
1204	s.Tool.TodoCompletedIcon = base.Foreground(green)
1205	s.Tool.TodoInProgressIcon = base.Foreground(greenDark)
1206	s.Tool.TodoPendingIcon = base.Foreground(fgMuted)
1207	s.Tool.TodoStatusNote = lipgloss.NewStyle().Foreground(fgSubtle)
1208	s.Tool.TodoItem = lipgloss.NewStyle().Foreground(fgBase)
1209	s.Tool.TodoJustStarted = lipgloss.NewStyle().Foreground(fgBase)
1210
1211	// MCP styles
1212	s.Tool.MCPName = base.Foreground(blue)
1213	s.Tool.MCPToolName = base.Foreground(blueDark)
1214	s.Tool.MCPArrow = base.Foreground(blue).SetString(ArrowRightIcon)
1215
1216	// Loading indicators for images, skills
1217	s.Tool.ResourceLoadedText = base.Foreground(green)
1218	s.Tool.ResourceLoadedIndicator = base.Foreground(greenDark)
1219	s.Tool.ResourceName = base
1220	s.Tool.MediaType = base
1221	s.Tool.ResourceSize = base.Foreground(fgMuted)
1222
1223	// Tool-call action verbs and result-list styling.
1224	s.Tool.ActionCreate = lipgloss.NewStyle().Foreground(greenLight)
1225	s.Tool.ActionDestroy = lipgloss.NewStyle().Foreground(red)
1226	s.Tool.ResultEmpty = lipgloss.NewStyle().Foreground(fgSubtle)
1227	s.Tool.ResultTruncation = lipgloss.NewStyle().Foreground(fgSubtle)
1228	s.Tool.ResultItemName = lipgloss.NewStyle().Foreground(fgBase)
1229	s.Tool.ResultItemDesc = lipgloss.NewStyle().Foreground(fgSubtle)
1230
1231	// Hook styles
1232	s.Tool.HookLabel = base.Foreground(green)
1233	s.Tool.HookName = base
1234	s.Tool.HookMatcher = base.Foreground(fgMuted)
1235	s.Tool.HookArrow = base.Foreground(green)
1236	s.Tool.HookDetail = base.Foreground(fgMuted)
1237	s.Tool.HookOK = base.Foreground(charmtone.Guac)
1238	s.Tool.HookDenied = base.Foreground(charmtone.Sriracha)
1239	s.Tool.HookDeniedLabel = base.Foreground(red)
1240	s.Tool.HookDeniedReason = base.Foreground(charmtone.Iron)
1241	s.Tool.HookRewrote = base.Foreground(charmtone.Iron)
1242
1243	// Buttons
1244	s.Button.Focused = lipgloss.NewStyle().Foreground(white).Background(secondary)
1245	s.Button.Blurred = lipgloss.NewStyle().Foreground(fgBase).Background(bgSubtle)
1246
1247	// Editor
1248	s.Editor.PromptNormalFocused = lipgloss.NewStyle().Foreground(greenDark).SetString("::: ")
1249	s.Editor.PromptNormalBlurred = s.Editor.PromptNormalFocused.Foreground(fgMuted)
1250	s.Editor.PromptYoloIconFocused = lipgloss.NewStyle().MarginRight(1).Foreground(charmtone.Oyster).Background(charmtone.Citron).Bold(true).SetString(" ! ")
1251	s.Editor.PromptYoloIconBlurred = s.Editor.PromptYoloIconFocused.Foreground(charmtone.Pepper).Background(charmtone.Squid)
1252	s.Editor.PromptYoloDotsFocused = lipgloss.NewStyle().MarginRight(1).Foreground(charmtone.Zest).SetString(":::")
1253	s.Editor.PromptYoloDotsBlurred = s.Editor.PromptYoloDotsFocused.Foreground(charmtone.Squid)
1254
1255	s.Radio.On = lipgloss.NewStyle().Foreground(fgHalfMuted).SetString(RadioOn)
1256	s.Radio.Off = lipgloss.NewStyle().Foreground(fgHalfMuted).SetString(RadioOff)
1257	s.Radio.Label = lipgloss.NewStyle().Foreground(fgHalfMuted)
1258
1259	// Logo
1260	s.Logo.FieldColor = primary
1261	s.Logo.TitleColorA = secondary
1262	s.Logo.TitleColorB = primary
1263	s.Logo.CharmColor = secondary
1264	s.Logo.VersionColor = primary
1265	s.Logo.SmallCharm = lipgloss.NewStyle().Foreground(secondary)
1266	s.Logo.SmallDiagonals = lipgloss.NewStyle().Foreground(primary)
1267	s.Logo.GradCanvas = lipgloss.NewStyle()
1268	s.Logo.SmallGradFromColor = secondary
1269	s.Logo.SmallGradToColor = primary
1270
1271	// Section
1272	s.Section.Title = subtle
1273	s.Section.Line = base.Foreground(charmtone.Charcoal)
1274
1275	// Initialize
1276	s.Initialize.Header = base
1277	s.Initialize.Content = muted
1278	s.Initialize.Accent = base.Foreground(greenDark)
1279
1280	// ResourceGroup (LSP/MCP/skills sidebar lists).
1281	s.Resource.Heading = lipgloss.NewStyle().Foreground(charmtone.Oyster)
1282	s.Resource.Name = lipgloss.NewStyle().Foreground(charmtone.Squid)
1283	s.Resource.StatusText = lipgloss.NewStyle().Foreground(charmtone.Oyster)
1284	s.Resource.OfflineIcon = lipgloss.NewStyle().Foreground(charmtone.Iron).SetString("●")
1285	s.Resource.BusyIcon = s.Resource.OfflineIcon.Foreground(charmtone.Citron)
1286	s.Resource.ErrorIcon = s.Resource.OfflineIcon.Foreground(charmtone.Coral)
1287	s.Resource.OnlineIcon = s.Resource.OfflineIcon.Foreground(charmtone.Guac)
1288	s.Resource.DisabledIcon = lipgloss.NewStyle().Foreground(fgMuted).SetString("●")
1289	s.Resource.AdditionalText = lipgloss.NewStyle().Foreground(charmtone.Oyster)
1290	s.Resource.CapabilityCount = lipgloss.NewStyle().Foreground(fgSubtle)
1291	s.Resource.RowTitleBase = lipgloss.NewStyle().Foreground(fgBase)
1292	s.Resource.RowDescBase = lipgloss.NewStyle().Foreground(fgBase)
1293	s.Resource.DefaultTitleFg = fgMuted
1294	s.Resource.DefaultDescFg = fgSubtle
1295
1296	// LSP
1297	s.LSP.ErrorDiagnostic = base.Foreground(redDark)
1298	s.LSP.WarningDiagnostic = base.Foreground(warning)
1299	s.LSP.HintDiagnostic = base.Foreground(fgHalfMuted)
1300	s.LSP.InfoDiagnostic = base.Foreground(info)
1301
1302	// Files
1303	s.Files.Path = lipgloss.NewStyle().Foreground(fgMuted)
1304	s.Files.Additions = lipgloss.NewStyle().Foreground(greenDark)
1305	s.Files.Deletions = lipgloss.NewStyle().Foreground(redDark)
1306	s.Files.SectionTitle = lipgloss.NewStyle().Foreground(fgSubtle)
1307	s.Files.EmptyMessage = lipgloss.NewStyle().Foreground(fgSubtle)
1308	s.Files.TruncationHint = lipgloss.NewStyle().Foreground(fgSubtle)
1309
1310	// Sidebar
1311	s.Sidebar.SessionTitle = lipgloss.NewStyle().Foreground(fgMuted)
1312	s.Sidebar.WorkingDir = lipgloss.NewStyle().Foreground(fgMuted)
1313
1314	// ModelInfo
1315	s.ModelInfo.Icon = lipgloss.NewStyle().Foreground(fgSubtle)
1316	s.ModelInfo.Name = lipgloss.NewStyle().Foreground(fgBase)
1317	s.ModelInfo.Provider = lipgloss.NewStyle().Foreground(fgMuted)
1318	s.ModelInfo.ProviderFallback = lipgloss.NewStyle().Foreground(fgMuted).PaddingLeft(2)
1319	s.ModelInfo.Reasoning = lipgloss.NewStyle().Foreground(fgSubtle).PaddingLeft(2)
1320	s.ModelInfo.TokenCount = lipgloss.NewStyle().Foreground(fgSubtle)
1321	s.ModelInfo.TokenPercentage = lipgloss.NewStyle().Foreground(fgMuted)
1322	s.ModelInfo.Cost = lipgloss.NewStyle().Foreground(fgMuted)
1323
1324	// ResourceGroup
1325	s.Resource.DefaultTitleFg = fgMuted
1326	s.Resource.DefaultDescFg = fgSubtle
1327
1328	// Chat
1329	messageFocussedBorder := lipgloss.Border{
1330		Left: "β–Œ",
1331	}
1332
1333	s.Messages.NoContent = lipgloss.NewStyle().Foreground(fgBase)
1334	s.Messages.UserBlurred = s.Messages.NoContent.PaddingLeft(1).BorderLeft(true).
1335		BorderForeground(primary).BorderStyle(normalBorder)
1336	s.Messages.UserFocused = s.Messages.NoContent.PaddingLeft(1).BorderLeft(true).
1337		BorderForeground(primary).BorderStyle(messageFocussedBorder)
1338	s.Messages.AssistantBlurred = s.Messages.NoContent.PaddingLeft(2)
1339	s.Messages.AssistantFocused = s.Messages.NoContent.PaddingLeft(1).BorderLeft(true).
1340		BorderForeground(greenDark).BorderStyle(messageFocussedBorder)
1341	s.Messages.Thinking = lipgloss.NewStyle().MaxHeight(10)
1342	s.Messages.ErrorTag = lipgloss.NewStyle().Padding(0, 1).
1343		Background(red).Foreground(white)
1344	s.Messages.ErrorTitle = lipgloss.NewStyle().Foreground(fgHalfMuted)
1345	s.Messages.ErrorDetails = lipgloss.NewStyle().Foreground(fgSubtle)
1346
1347	// Message item styles
1348	s.Messages.ToolCallFocused = muted.PaddingLeft(1).
1349		BorderStyle(messageFocussedBorder).
1350		BorderLeft(true).
1351		BorderForeground(greenDark)
1352	s.Messages.ToolCallBlurred = muted.PaddingLeft(2)
1353	// No padding or border for compact tool calls within messages
1354	s.Messages.ToolCallCompact = muted
1355	s.Messages.SectionHeader = base.PaddingLeft(2)
1356	s.Messages.AssistantInfoIcon = subtle
1357	s.Messages.AssistantInfoModel = muted
1358	s.Messages.AssistantInfoProvider = subtle
1359	s.Messages.AssistantInfoDuration = subtle
1360	s.Messages.AssistantCanceled = lipgloss.NewStyle().Foreground(fgBase).Italic(true)
1361
1362	// Thinking section styles
1363	s.Messages.ThinkingBox = subtle.Background(bgBaseLighter)
1364	s.Messages.ThinkingTruncationHint = muted
1365	s.Messages.ThinkingFooterTitle = muted
1366	s.Messages.ThinkingFooterDuration = subtle
1367
1368	// Text selection.
1369	s.TextSelection = lipgloss.NewStyle().Foreground(charmtone.Salt).Background(charmtone.Charple)
1370
1371	// Dialog styles
1372	s.Dialog.Title = base.Padding(0, 1).Foreground(primary)
1373	s.Dialog.TitleText = base.Foreground(primary)
1374	s.Dialog.TitleError = base.Foreground(red)
1375	s.Dialog.TitleAccent = base.Foreground(green).Bold(true)
1376	s.Dialog.TitleLineBase = lipgloss.NewStyle()
1377	s.Dialog.TitleGradFromColor = primary
1378	s.Dialog.TitleGradToColor = secondary
1379
1380	// Dialog.ListItem (commands, reasoning, models)
1381	s.Dialog.ListItem.InfoBlurred = lipgloss.NewStyle().Foreground(fgBase)
1382	s.Dialog.ListItem.InfoFocused = lipgloss.NewStyle().Foreground(fgBase)
1383
1384	// Dialog.Models
1385	s.Dialog.Models.ConfiguredText = lipgloss.NewStyle().Foreground(fgSubtle)
1386
1387	// Dialog.Permissions
1388	s.Dialog.Permissions.KeyText = lipgloss.NewStyle().Foreground(fgMuted)
1389	s.Dialog.Permissions.ValueText = lipgloss.NewStyle().Foreground(fgBase)
1390	s.Dialog.Permissions.ParamsBg = bgSubtle
1391
1392	// Dialog.Quit
1393	s.Dialog.Quit.Content = lipgloss.NewStyle().Foreground(fgBase)
1394	s.Dialog.Quit.Frame = lipgloss.NewStyle().BorderForeground(borderFocus).Border(lipgloss.RoundedBorder()).Padding(1, 2)
1395	s.Dialog.View = base.Border(lipgloss.RoundedBorder()).BorderForeground(borderFocus)
1396	s.Dialog.PrimaryText = base.Padding(0, 1).Foreground(primary)
1397	s.Dialog.SecondaryText = base.Padding(0, 1).Foreground(fgSubtle)
1398	s.Dialog.HelpView = base.Padding(0, 1).AlignHorizontal(lipgloss.Left)
1399	s.Dialog.Help.ShortKey = base.Foreground(fgMuted)
1400	s.Dialog.Help.ShortDesc = base.Foreground(fgSubtle)
1401	s.Dialog.Help.ShortSeparator = base.Foreground(border)
1402	s.Dialog.Help.Ellipsis = base.Foreground(border)
1403	s.Dialog.Help.FullKey = base.Foreground(fgMuted)
1404	s.Dialog.Help.FullDesc = base.Foreground(fgSubtle)
1405	s.Dialog.Help.FullSeparator = base.Foreground(border)
1406	s.Dialog.NormalItem = base.Padding(0, 1).Foreground(fgBase)
1407	s.Dialog.SelectedItem = base.Padding(0, 1).Background(primary).Foreground(fgBase)
1408	s.Dialog.InputPrompt = base.Margin(1, 1)
1409
1410	s.Dialog.List = base.Margin(0, 0, 1, 0)
1411	s.Dialog.ContentPanel = base.Background(bgSubtle).Foreground(fgBase).Padding(1, 2)
1412	s.Dialog.Spinner = base.Foreground(secondary)
1413	s.Dialog.ScrollbarThumb = base.Foreground(secondary)
1414	s.Dialog.ScrollbarTrack = base.Foreground(border)
1415
1416	s.Dialog.ImagePreview = lipgloss.NewStyle().Padding(0, 1).Foreground(fgSubtle)
1417
1418	// API key input dialog
1419	s.Dialog.APIKey.Spinner = base.Foreground(green)
1420
1421	// OAuth dialog
1422	s.Dialog.OAuth.Spinner = base.Foreground(greenLight)
1423	s.Dialog.OAuth.Instructions = lipgloss.NewStyle().Foreground(white)
1424	s.Dialog.OAuth.UserCode = lipgloss.NewStyle().Bold(true).Foreground(white)
1425	s.Dialog.OAuth.Success = lipgloss.NewStyle().Foreground(greenLight)
1426	s.Dialog.OAuth.Link = lipgloss.NewStyle().Foreground(greenDark).Underline(true)
1427	s.Dialog.OAuth.Enter = lipgloss.NewStyle().Foreground(primary)
1428	s.Dialog.OAuth.ErrorText = lipgloss.NewStyle().Foreground(error)
1429	s.Dialog.OAuth.StatusText = lipgloss.NewStyle().Foreground(fgMuted)
1430	s.Dialog.OAuth.UserCodeBg = bgBaseLighter
1431
1432	s.Dialog.Arguments.Content = base.Padding(1)
1433	s.Dialog.Arguments.Description = base.MarginBottom(1).MaxHeight(3)
1434	s.Dialog.Arguments.InputLabelBlurred = base.Foreground(fgMuted)
1435	s.Dialog.Arguments.InputLabelFocused = base.Bold(true)
1436	s.Dialog.Arguments.InputRequiredMarkBlurred = base.Foreground(fgMuted).SetString("*")
1437	s.Dialog.Arguments.InputRequiredMarkFocused = base.Foreground(primary).Bold(true).SetString("*")
1438
1439	s.Dialog.Sessions.DeletingTitle = s.Dialog.Title.Foreground(red)
1440	s.Dialog.Sessions.DeletingView = s.Dialog.View.BorderForeground(red)
1441	s.Dialog.Sessions.DeletingMessage = base.Padding(1)
1442	s.Dialog.Sessions.DeletingTitleGradientFromColor = red
1443	s.Dialog.Sessions.DeletingTitleGradientToColor = primary
1444	s.Dialog.Sessions.DeletingItemBlurred = s.Dialog.NormalItem.Foreground(fgSubtle)
1445	s.Dialog.Sessions.DeletingItemFocused = s.Dialog.SelectedItem.Background(red).Foreground(charmtone.Butter)
1446
1447	s.Dialog.Sessions.RenamingingTitle = s.Dialog.Title.Foreground(charmtone.Zest)
1448	s.Dialog.Sessions.RenamingView = s.Dialog.View.BorderForeground(charmtone.Zest)
1449	s.Dialog.Sessions.RenamingingMessage = base.Padding(1)
1450	s.Dialog.Sessions.RenamingTitleGradientFromColor = charmtone.Zest
1451	s.Dialog.Sessions.RenamingTitleGradientToColor = charmtone.Bok
1452	s.Dialog.Sessions.RenamingItemBlurred = s.Dialog.NormalItem.Foreground(fgSubtle)
1453	s.Dialog.Sessions.RenamingingItemFocused = s.Dialog.SelectedItem.UnsetBackground().UnsetForeground()
1454	s.Dialog.Sessions.RenamingPlaceholder = base.Foreground(charmtone.Squid)
1455	s.Dialog.Sessions.InfoBlurred = lipgloss.NewStyle().Foreground(fgSubtle)
1456	s.Dialog.Sessions.InfoFocused = lipgloss.NewStyle().Foreground(fgBase)
1457
1458	s.Status.Help = lipgloss.NewStyle().Padding(0, 1)
1459	s.Status.SuccessIndicator = base.Foreground(bgSubtle).Background(green).Padding(0, 1).Bold(true).SetString("OKAY!")
1460	s.Status.InfoIndicator = s.Status.SuccessIndicator
1461	s.Status.UpdateIndicator = s.Status.SuccessIndicator.SetString("HEY!")
1462	s.Status.WarnIndicator = s.Status.SuccessIndicator.Foreground(bgOverlay).Background(yellow).SetString("WARNING")
1463	s.Status.ErrorIndicator = s.Status.SuccessIndicator.Foreground(bgBase).Background(red).SetString("ERROR")
1464	s.Status.SuccessMessage = base.Foreground(bgSubtle).Background(greenDark).Padding(0, 1)
1465	s.Status.InfoMessage = s.Status.SuccessMessage
1466	s.Status.UpdateMessage = s.Status.SuccessMessage
1467	s.Status.WarnMessage = s.Status.SuccessMessage.Foreground(bgOverlay).Background(warning)
1468	s.Status.ErrorMessage = s.Status.SuccessMessage.Foreground(white).Background(redDark)
1469
1470	// Completions styles
1471	s.Completions.Normal = base.Background(bgSubtle).Foreground(fgBase)
1472	s.Completions.Focused = base.Background(primary).Foreground(white)
1473	s.Completions.Match = base.Underline(true)
1474
1475	// Attachments styles
1476	attachmentIconStyle := base.Foreground(bgSubtle).Background(green).Padding(0, 1)
1477	s.Attachments.Image = attachmentIconStyle.SetString(ImageIcon)
1478	s.Attachments.Text = attachmentIconStyle.SetString(TextIcon)
1479	s.Attachments.Normal = base.Padding(0, 1).MarginRight(1).Background(fgMuted).Foreground(fgBase)
1480	s.Attachments.Deleting = base.Padding(0, 1).Bold(true).Background(red).Foreground(fgBase)
1481
1482	// Pills styles
1483	s.Pills.Base = base.Padding(0, 1)
1484	s.Pills.Focused = base.Padding(0, 1).BorderStyle(lipgloss.RoundedBorder()).BorderForeground(bgOverlay)
1485	s.Pills.Blurred = base.Padding(0, 1).BorderStyle(lipgloss.HiddenBorder())
1486	s.Pills.QueueItemPrefix = lipgloss.NewStyle().Foreground(fgMuted).SetString("  β€’")
1487	s.Pills.QueueItemText = lipgloss.NewStyle().Foreground(fgMuted)
1488	s.Pills.QueueLabel = lipgloss.NewStyle().Foreground(fgBase)
1489	s.Pills.QueueIconBase = lipgloss.NewStyle().Foreground(fgBase)
1490	s.Pills.QueueGradFromColor = redDark
1491	s.Pills.QueueGradToColor = secondary
1492	s.Pills.TodoLabel = lipgloss.NewStyle().Foreground(fgBase)
1493	s.Pills.TodoProgress = lipgloss.NewStyle().Foreground(fgMuted)
1494	s.Pills.TodoCurrentTask = lipgloss.NewStyle().Foreground(fgSubtle)
1495	s.Pills.TodoSpinner = lipgloss.NewStyle().Foreground(greenDark)
1496	s.Pills.HelpKey = lipgloss.NewStyle().Foreground(fgMuted)
1497	s.Pills.HelpText = lipgloss.NewStyle().Foreground(fgSubtle)
1498	s.Pills.Area = base
1499
1500	return s
1501}
1502
1503func chromaStyle(style ansi.StylePrimitive) string {
1504	var s strings.Builder
1505
1506	if style.Color != nil {
1507		s.WriteString(*style.Color)
1508	}
1509	if style.BackgroundColor != nil {
1510		if s.Len() > 0 {
1511			s.WriteString(" ")
1512		}
1513		s.WriteString("bg:")
1514		s.WriteString(*style.BackgroundColor)
1515	}
1516	if style.Italic != nil && *style.Italic {
1517		if s.Len() > 0 {
1518			s.WriteString(" ")
1519		}
1520		s.WriteString("italic")
1521	}
1522	if style.Bold != nil && *style.Bold {
1523		if s.Len() > 0 {
1524			s.WriteString(" ")
1525		}
1526		s.WriteString("bold")
1527	}
1528	if style.Underline != nil && *style.Underline {
1529		if s.Len() > 0 {
1530			s.WriteString(" ")
1531		}
1532		s.WriteString("underline")
1533	}
1534
1535	return s.String()
1536}