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