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