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