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