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