styles.go

  1// Package styles define styling and theming for the project.
  2package styles
  3
  4import (
  5	"fmt"
  6	"image/color"
  7	"strings"
  8
  9	"charm.land/bubbles/v2/filepicker"
 10	"charm.land/bubbles/v2/help"
 11	"charm.land/bubbles/v2/textarea"
 12	"charm.land/bubbles/v2/textinput"
 13	"charm.land/glamour/v2/ansi"
 14	"charm.land/lipgloss/v2"
 15	"github.com/alecthomas/chroma/v2"
 16	"github.com/charmbracelet/crush/internal/ui/diffview"
 17)
 18
 19const (
 20	CheckIcon       string = "βœ“"
 21	SpinnerIcon     string = "β‹―"
 22	LoadingIcon     string = "⟳"
 23	ModelIcon       string = "β—‡"
 24	HypercreditIcon string = "β—†"
 25
 26	ArrowRightIcon string = "β†’"
 27
 28	ToolPending string = "●"
 29	ToolSuccess string = "βœ“"
 30	ToolError   string = "Γ—"
 31
 32	RadioOn  string = "β—‰"
 33	RadioOff string = "β—‹"
 34
 35	BorderThin  string = "β”‚"
 36	BorderThick string = "β–Œ"
 37
 38	SectionSeparator string = "─"
 39
 40	TodoCompletedIcon  string = "βœ“"
 41	TodoPendingIcon    string = "β€’"
 42	TodoInProgressIcon string = "β†’"
 43
 44	ImageIcon string = "β– "
 45	TextIcon  string = "≑"
 46	SkillIcon string = "β–²"
 47
 48	ScrollbarThumb string = "┃"
 49	ScrollbarTrack string = "β”‚"
 50
 51	LSPErrorIcon   string = "E"
 52	LSPWarningIcon string = "W"
 53	LSPInfoIcon    string = "I"
 54	LSPHintIcon    string = "H"
 55)
 56
 57const (
 58	defaultMargin     = 2
 59	defaultListIndent = 2
 60)
 61
 62type Styles struct {
 63	// Header
 64	Header struct {
 65		Charm             lipgloss.Style // Style for "Charmβ„’" label
 66		Diagonals         lipgloss.Style // Style for diagonal separators (β•±)
 67		Percentage        lipgloss.Style // Style for context percentage
 68		Hypercredit       lipgloss.Style // Style for Hypercredit count (β—† N)
 69		Keystroke         lipgloss.Style // Style for keystroke hints (e.g., "ctrl+d")
 70		KeystrokeTip      lipgloss.Style // Style for keystroke action text (e.g., "open", "close")
 71		WorkingDir        lipgloss.Style // Style for current working directory
 72		Separator         lipgloss.Style // Style for separator dots (β€’)
 73		Wrapper           lipgloss.Style // Outer container for the entire header row
 74		LogoGradCanvas    lipgloss.Style // Canvas for the compact "CRUSH" gradient
 75		LogoGradFromColor color.Color    // "CRUSH" wordmark gradient start
 76		LogoGradToColor   color.Color    // "CRUSH" wordmark gradient end
 77	}
 78
 79	CompactDetails struct {
 80		View    lipgloss.Style
 81		Version lipgloss.Style
 82		Title   lipgloss.Style
 83	}
 84
 85	// Tool calls
 86	ToolCallSuccess lipgloss.Style
 87
 88	// Text selection
 89	TextSelection lipgloss.Style
 90
 91	// Markdown & Chroma
 92	Markdown      ansi.StyleConfig
 93	QuietMarkdown ansi.StyleConfig
 94
 95	// Inputs
 96	TextInput textinput.Styles
 97
 98	// Help
 99	Help help.Styles
100
101	// Diff
102	Diff diffview.Style
103
104	// FilePicker
105	FilePicker filepicker.Styles
106
107	// Buttons
108	Button struct {
109		Focused lipgloss.Style
110		Blurred lipgloss.Style
111	}
112
113	// Editor
114	Editor struct {
115		Textarea textarea.Styles
116
117		// Normal mode prompt (default "::: ").
118		PromptNormalFocused lipgloss.Style
119		PromptNormalBlurred lipgloss.Style
120
121		// YOLO mode prompt (" ! " icon + ":::" dots).
122		PromptYoloIconFocused lipgloss.Style
123		PromptYoloIconBlurred lipgloss.Style
124		PromptYoloDotsFocused lipgloss.Style
125		PromptYoloDotsBlurred lipgloss.Style
126	}
127
128	// Radio
129	Radio struct {
130		On    lipgloss.Style
131		Off   lipgloss.Style
132		Label lipgloss.Style // Text next to a radio button
133	}
134
135	// Background
136	Background color.Color
137
138	// Logo
139	Logo struct {
140		FieldColor         color.Color
141		TitleColorA        color.Color
142		TitleColorB        color.Color
143		CharmColor         color.Color
144		VersionColor       color.Color
145		SmallCharm         lipgloss.Style // "Charmβ„’" label in SmallRender
146		SmallDiagonals     lipgloss.Style // Diagonal line fill in SmallRender
147		GradCanvas         lipgloss.Style // Blank canvas for gradient painting
148		SmallGradFromColor color.Color    // Small "Crush" wordmark gradient start
149		SmallGradToColor   color.Color    // Small "Crush" wordmark gradient end
150	}
151
152	// Working indicator gradient (spinners/shimmers on assistant "thinking",
153	// tool-call pending, CLI generating, startup).
154	WorkingGradFromColor color.Color
155	WorkingGradToColor   color.Color
156	WorkingLabelColor    color.Color // Label text color next to the indicator
157
158	// Section Title
159	Section struct {
160		Title lipgloss.Style
161		Line  lipgloss.Style
162	}
163
164	// Initialize
165	Initialize struct {
166		Header  lipgloss.Style
167		Content lipgloss.Style
168		Accent  lipgloss.Style
169	}
170
171	// LSP
172	LSP struct {
173		ErrorDiagnostic   lipgloss.Style
174		WarningDiagnostic lipgloss.Style
175		HintDiagnostic    lipgloss.Style
176		InfoDiagnostic    lipgloss.Style
177	}
178
179	// Sidebar
180	Sidebar struct {
181		SessionTitle lipgloss.Style // Current session title at top of sidebar
182		WorkingDir   lipgloss.Style // Working directory path (PrettyPath)
183	}
184
185	// ModelInfo (model name, provider, reasoning, token/cost summary)
186	ModelInfo struct {
187		Icon                 lipgloss.Style // Model icon (β—‡)
188		Name                 lipgloss.Style // Model name text
189		Provider             lipgloss.Style // "via <provider>" text
190		ProviderFallback     lipgloss.Style // Provider on its own second line
191		Reasoning            lipgloss.Style // Reasoning effort text
192		TokenCount           lipgloss.Style // "(42K)" token count
193		TokenPercentage      lipgloss.Style // "42%" percent of context window
194		EstimatedUsagePrefix lipgloss.Style // "~" prefix for estimated usage
195		Cost                 lipgloss.Style // "$0.42" cost readout
196		HypercreditIcon      lipgloss.Style // Hypercredit icon (β—†)
197		HypercreditText      lipgloss.Style // Remaining Hypercredits text
198	}
199
200	// Resource styles the LSP/MCP/skills sidebar lists: their heading,
201	// each row's status icon, name, status text, and truncation hints.
202	Resource struct {
203		Heading         lipgloss.Style // Section header ("LSPs", "MCPs", "Skills")
204		Name            lipgloss.Style // Resource name (e.g. "gopls")
205		StatusText      lipgloss.Style // Row status description (e.g. "starting...")
206		OfflineIcon     lipgloss.Style // Offline/unstarted/stopped status icon
207		DisabledIcon    lipgloss.Style // Disabled status icon
208		BusyIcon        lipgloss.Style // Busy/starting status icon
209		ErrorIcon       lipgloss.Style // Error status icon
210		OnlineIcon      lipgloss.Style // Online/ready status icon
211		AdditionalText  lipgloss.Style // "None" and "…and N more" text
212		CapabilityCount lipgloss.Style // "N tools" / "N prompts" / "N resources"
213		RowTitleBase    lipgloss.Style // Base style applied over row titles in common.Status
214		RowDescBase     lipgloss.Style // Base style applied over row descriptions in common.Status
215		DefaultTitleFg  color.Color    // Default title color when opt is zero
216		DefaultDescFg   color.Color    // Default description color when opt is zero
217	}
218
219	// Files
220	Files struct {
221		Path           lipgloss.Style
222		Additions      lipgloss.Style
223		Deletions      lipgloss.Style
224		SectionTitle   lipgloss.Style // "Modified Files" heading
225		EmptyMessage   lipgloss.Style // "None" placeholder when no files
226		TruncationHint lipgloss.Style // "…and N more" message
227	}
228
229	// Chat
230	// Messages - chat message item styles
231	Messages struct {
232		UserBlurred      lipgloss.Style
233		UserFocused      lipgloss.Style
234		AssistantBlurred lipgloss.Style
235		AssistantFocused lipgloss.Style
236		NoContent        lipgloss.Style
237		Thinking         lipgloss.Style
238		ErrorTag         lipgloss.Style
239		ErrorTitle       lipgloss.Style
240		ErrorDetails     lipgloss.Style
241		ToolCallFocused  lipgloss.Style
242		ToolCallCompact  lipgloss.Style
243		ToolCallBlurred  lipgloss.Style
244		SectionHeader    lipgloss.Style
245
246		// Thinking section styles
247		ThinkingBox            lipgloss.Style // Background for thinking content
248		ThinkingTruncationHint lipgloss.Style // "… (N lines hidden)" hint
249		ThinkingFooterTitle    lipgloss.Style // "Thought for" text
250		ThinkingFooterDuration lipgloss.Style // Duration value
251		AssistantInfoIcon      lipgloss.Style
252		AssistantInfoModel     lipgloss.Style
253		AssistantInfoProvider  lipgloss.Style
254		AssistantInfoDuration  lipgloss.Style
255		AssistantCanceled      lipgloss.Style // Italic "Canceled" footer
256	}
257
258	// Tool - styles for tool call rendering
259	Tool struct {
260		// Icon styles with tool status
261		IconPending   lipgloss.Style
262		IconSuccess   lipgloss.Style
263		IconError     lipgloss.Style
264		IconCancelled lipgloss.Style
265
266		// Tool name styles
267		NameNormal lipgloss.Style // Top-level tool name
268		NameNested lipgloss.Style // Nested child tool name (inside Agent/Agentic Fetch)
269
270		// Parameter list styles
271		ParamMain lipgloss.Style
272		ParamKey  lipgloss.Style
273
274		// Content rendering styles
275		ContentLine           lipgloss.Style // Individual content line with background and width
276		ContentTruncation     lipgloss.Style // Truncation message "… (N lines)"
277		ContentCodeLine       lipgloss.Style // Code line with background and width
278		ContentCodeTruncation lipgloss.Style // Code truncation message with bgBase
279		ContentCodeBg         color.Color    // Background color for syntax highlighting
280		Body                  lipgloss.Style // Body content padding (PaddingLeft(2))
281
282		// Deprecated - kept for backward compatibility
283		ContentBg         lipgloss.Style // Content background
284		ContentText       lipgloss.Style // Content text
285		ContentLineNumber lipgloss.Style // Line numbers in code
286
287		// State message styles
288		StateWaiting   lipgloss.Style // "Waiting for tool response..."
289		StateCancelled lipgloss.Style // "Canceled."
290
291		// Error styles
292		ErrorTag     lipgloss.Style // ERROR tag
293		ErrorMessage lipgloss.Style // Error message text
294
295		// Warning styles (used for permission denied)
296		WarnTag     lipgloss.Style // WARN tag
297		WarnMessage lipgloss.Style // Warning message text
298
299		// Diff styles
300		DiffTruncation lipgloss.Style // Diff truncation message with padding
301
302		// Multi-edit note styles
303		NoteTag     lipgloss.Style // NOTE tag (yellow background)
304		NoteMessage lipgloss.Style // Note message text
305
306		// Job header styles (for bash jobs)
307		JobIconPending lipgloss.Style // Pending job icon (green dark)
308		JobIconError   lipgloss.Style // Error job icon (red dark)
309		JobIconSuccess lipgloss.Style // Success job icon (green)
310		JobToolName    lipgloss.Style // Job tool name "Bash" (blue)
311		JobAction      lipgloss.Style // Action text (Start, Output, Kill)
312		JobPID         lipgloss.Style // PID text
313		JobDescription lipgloss.Style // Description text
314
315		// Agent task styles
316		AgentTaskTag lipgloss.Style // Agent task tag (blue background, bold)
317		AgentPrompt  lipgloss.Style // Agent prompt text
318
319		// Agentic fetch styles
320		AgenticFetchPromptTag lipgloss.Style // Agentic fetch prompt tag (green background, bold)
321
322		// Todo styles
323		TodoRatio          lipgloss.Style // Todo ratio (e.g., "2/5")
324		TodoCompletedIcon  lipgloss.Style // Completed todo icon
325		TodoInProgressIcon lipgloss.Style // In-progress todo icon
326		TodoPendingIcon    lipgloss.Style // Pending todo icon
327		TodoStatusNote     lipgloss.Style // " Β· completed N" / " Β· starting task" trailing note
328		TodoItem           lipgloss.Style // Default body text for todo list items
329		TodoJustStarted    lipgloss.Style // Text of the just-started todo in tool-call bodies
330
331		// MCP tools
332		MCPName     lipgloss.Style // The mcp name
333		MCPToolName lipgloss.Style // The mcp tool name
334		MCPArrow    lipgloss.Style // The mcp arrow icon
335
336		// Images and external resources
337		ResourceLoadedText      lipgloss.Style
338		ResourceLoadedIndicator lipgloss.Style
339		ResourceName            lipgloss.Style
340		ResourceSize            lipgloss.Style
341		MediaType               lipgloss.Style
342
343		// Hooks
344		HookLabel        lipgloss.Style // "Hook" label
345		HookName         lipgloss.Style // Hook command name
346		HookMatcher      lipgloss.Style // Matcher regex pattern
347		HookArrow        lipgloss.Style // Arrow indicator
348		HookDetail       lipgloss.Style // Decision detail text
349		HookOK           lipgloss.Style // "OK" status
350		HookDenied       lipgloss.Style // "Denied" status
351		HookDeniedLabel  lipgloss.Style // "Hook" label when denied
352		HookDeniedReason lipgloss.Style // Denied reason text
353		HookRewrote      lipgloss.Style // "Rewrote Input" indicator
354
355		// Action verb colors for tool-call headers.
356		ActionCreate  lipgloss.Style // Constructive actions (e.g. "Add", "Create")
357		ActionDestroy lipgloss.Style // Destructive actions (e.g. "Remove", "Delete")
358
359		// Tool result helpers.
360		ResultEmpty      lipgloss.Style // "No results" placeholder
361		ResultTruncation lipgloss.Style // "… and N more" truncation line
362		ResultItemName   lipgloss.Style // Item name (left column in result lists)
363		ResultItemDesc   lipgloss.Style // Item description (right column)
364	}
365
366	// Dialog styles
367	Dialog struct {
368		Title              lipgloss.Style
369		TitleText          lipgloss.Style
370		TitleError         lipgloss.Style
371		TitleAccent        lipgloss.Style
372		TitleLineBase      lipgloss.Style // Base for the gradient β•±β•±β•± next to dialog titles
373		TitleGradFromColor color.Color    // Default dialog title β•±β•±β•± gradient start
374		TitleGradToColor   color.Color    // Default dialog title β•±β•±β•± gradient end
375		// View is the main content area style.
376		View          lipgloss.Style
377		PrimaryText   lipgloss.Style
378		SecondaryText lipgloss.Style
379		// HelpView is the line that contains the help.
380		HelpView lipgloss.Style
381		Help     struct {
382			Ellipsis       lipgloss.Style
383			ShortKey       lipgloss.Style
384			ShortDesc      lipgloss.Style
385			ShortSeparator lipgloss.Style
386			FullKey        lipgloss.Style
387			FullDesc       lipgloss.Style
388			FullSeparator  lipgloss.Style
389		}
390
391		NormalItem   lipgloss.Style
392		SelectedItem lipgloss.Style
393		InputPrompt  lipgloss.Style
394
395		List lipgloss.Style
396
397		Spinner lipgloss.Style
398
399		// ContentPanel is used for content blocks with subtle background.
400		ContentPanel lipgloss.Style
401
402		// Scrollbar styles for scrollable content.
403		ScrollbarThumb lipgloss.Style
404		ScrollbarTrack lipgloss.Style
405
406		// Arguments
407		Arguments struct {
408			Content                  lipgloss.Style
409			Description              lipgloss.Style
410			InputLabelBlurred        lipgloss.Style
411			InputLabelFocused        lipgloss.Style
412			InputRequiredMarkBlurred lipgloss.Style
413			InputRequiredMarkFocused lipgloss.Style
414		}
415
416		// ListItem styles the info-text rendered alongside list items (commands,
417		// models, reasoning options). Sessions have their own overrides below.
418		ListItem struct {
419			InfoBlurred lipgloss.Style
420			InfoFocused lipgloss.Style
421		}
422
423		Models struct {
424			ConfiguredText lipgloss.Style // "Configured" badge shown on the ModelGroup header
425		}
426
427		Permissions struct {
428			KeyText   lipgloss.Style // Left key cell of a key/value row
429			ValueText lipgloss.Style // Right value cell of a key/value row
430			ParamsBg  color.Color    // Background color behind highlighted JSON parameters
431		}
432
433		Quit struct {
434			Content lipgloss.Style // Wrapper for the quit dialog's inner content
435			Frame   lipgloss.Style // Outer rounded border framing the quit dialog
436		}
437
438		APIKey struct {
439			Spinner lipgloss.Style // Loading spinner while validating the key
440		}
441
442		OAuth struct {
443			Spinner      lipgloss.Style // Loading spinner
444			Instructions lipgloss.Style // Emphasized instruction text
445			UserCode     lipgloss.Style // Prominent user code display
446			Success      lipgloss.Style // Positive status text (e.g. "Authentication successful!")
447			Link         lipgloss.Style // Underlined verification URL
448			Enter        lipgloss.Style // "enter" keyword highlight in instructions
449			ErrorText    lipgloss.Style // Error message when authentication fails
450			StatusText   lipgloss.Style // Narrative status text ("Initializing...", "Verifying...", etc.)
451			UserCodeBg   color.Color    // Background color of the centered user-code box
452		}
453
454		ImagePreview lipgloss.Style
455
456		Sessions struct {
457			// styles for when we are in delete mode
458			DeletingView                   lipgloss.Style
459			DeletingItemFocused            lipgloss.Style
460			DeletingItemBlurred            lipgloss.Style
461			DeletingTitle                  lipgloss.Style
462			DeletingMessage                lipgloss.Style
463			DeletingTitleGradientFromColor color.Color
464			DeletingTitleGradientToColor   color.Color
465
466			// styles for when we are in update mode
467			RenamingView                   lipgloss.Style
468			RenamingingItemFocused         lipgloss.Style
469			RenamingItemBlurred            lipgloss.Style
470			RenamingingTitle               lipgloss.Style
471			RenamingingMessage             lipgloss.Style
472			RenamingTitleGradientFromColor color.Color
473			RenamingTitleGradientToColor   color.Color
474			RenamingPlaceholder            lipgloss.Style
475
476			InfoBlurred lipgloss.Style // Timestamp text on unfocused session items
477			InfoFocused lipgloss.Style // Timestamp text on the focused session item
478		}
479	}
480
481	// Status bar and help
482	Status struct {
483		Help lipgloss.Style
484
485		ErrorIndicator   lipgloss.Style
486		WarnIndicator    lipgloss.Style
487		InfoIndicator    lipgloss.Style
488		UpdateIndicator  lipgloss.Style
489		SuccessIndicator lipgloss.Style
490
491		ErrorMessage   lipgloss.Style
492		WarnMessage    lipgloss.Style
493		InfoMessage    lipgloss.Style
494		UpdateMessage  lipgloss.Style
495		SuccessMessage lipgloss.Style
496	}
497
498	// Completions popup styles
499	Completions struct {
500		Normal  lipgloss.Style
501		Focused lipgloss.Style
502		Match   lipgloss.Style
503	}
504
505	// Attachments styles
506	Attachments struct {
507		Normal   lipgloss.Style
508		Image    lipgloss.Style
509		Text     lipgloss.Style
510		Skill    lipgloss.Style
511		Deleting lipgloss.Style
512	}
513
514	// Pills styles for todo/queue pills
515	Pills struct {
516		Base               lipgloss.Style // Base pill style with padding
517		Focused            lipgloss.Style // Focused pill with visible border
518		Blurred            lipgloss.Style // Blurred pill with hidden border
519		QueueItemPrefix    lipgloss.Style // Prefix for queue list items
520		QueueItemText      lipgloss.Style // Queue list item body text
521		QueueLabel         lipgloss.Style // "N Queued" label text
522		QueueIconBase      lipgloss.Style // Base style for queue gradient triangles
523		QueueGradFromColor color.Color    // Start color for queue indicator gradient
524		QueueGradToColor   color.Color    // End color for queue indicator gradient
525		TodoLabel          lipgloss.Style // "To-Do" label
526		TodoProgress       lipgloss.Style // Todo ratio (e.g. "2/5")
527		TodoCurrentTask    lipgloss.Style // Current in-progress task name
528		TodoSpinner        lipgloss.Style // Todo spinner style
529		HelpKey            lipgloss.Style // Keystroke hint style
530		HelpText           lipgloss.Style // Help action text style
531		Area               lipgloss.Style // Pills area container
532	}
533}
534
535// ChromaTheme converts the current markdown chroma styles to a chroma
536// StyleEntries map.
537func (s *Styles) ChromaTheme() chroma.StyleEntries {
538	rules := s.Markdown.CodeBlock
539
540	return chroma.StyleEntries{
541		chroma.Text:                chromaStyle(rules.Chroma.Text),
542		chroma.Error:               chromaStyle(rules.Chroma.Error),
543		chroma.Comment:             chromaStyle(rules.Chroma.Comment),
544		chroma.CommentPreproc:      chromaStyle(rules.Chroma.CommentPreproc),
545		chroma.Keyword:             chromaStyle(rules.Chroma.Keyword),
546		chroma.KeywordReserved:     chromaStyle(rules.Chroma.KeywordReserved),
547		chroma.KeywordNamespace:    chromaStyle(rules.Chroma.KeywordNamespace),
548		chroma.KeywordType:         chromaStyle(rules.Chroma.KeywordType),
549		chroma.Operator:            chromaStyle(rules.Chroma.Operator),
550		chroma.Punctuation:         chromaStyle(rules.Chroma.Punctuation),
551		chroma.Name:                chromaStyle(rules.Chroma.Name),
552		chroma.NameBuiltin:         chromaStyle(rules.Chroma.NameBuiltin),
553		chroma.NameTag:             chromaStyle(rules.Chroma.NameTag),
554		chroma.NameAttribute:       chromaStyle(rules.Chroma.NameAttribute),
555		chroma.NameClass:           chromaStyle(rules.Chroma.NameClass),
556		chroma.NameConstant:        chromaStyle(rules.Chroma.NameConstant),
557		chroma.NameDecorator:       chromaStyle(rules.Chroma.NameDecorator),
558		chroma.NameException:       chromaStyle(rules.Chroma.NameException),
559		chroma.NameFunction:        chromaStyle(rules.Chroma.NameFunction),
560		chroma.NameOther:           chromaStyle(rules.Chroma.NameOther),
561		chroma.Literal:             chromaStyle(rules.Chroma.Literal),
562		chroma.LiteralNumber:       chromaStyle(rules.Chroma.LiteralNumber),
563		chroma.LiteralDate:         chromaStyle(rules.Chroma.LiteralDate),
564		chroma.LiteralString:       chromaStyle(rules.Chroma.LiteralString),
565		chroma.LiteralStringEscape: chromaStyle(rules.Chroma.LiteralStringEscape),
566		chroma.GenericDeleted:      chromaStyle(rules.Chroma.GenericDeleted),
567		chroma.GenericEmph:         chromaStyle(rules.Chroma.GenericEmph),
568		chroma.GenericInserted:     chromaStyle(rules.Chroma.GenericInserted),
569		chroma.GenericStrong:       chromaStyle(rules.Chroma.GenericStrong),
570		chroma.GenericSubheading:   chromaStyle(rules.Chroma.GenericSubheading),
571		chroma.Background:          chromaStyle(rules.Chroma.Background),
572	}
573}
574
575// DialogHelpStyles returns the styles for dialog help.
576func (s *Styles) DialogHelpStyles() help.Styles {
577	return help.Styles(s.Dialog.Help)
578}
579
580// hex returns a pointer to the "#rrggbb" representation of c. It's used to
581// satisfy glamour's string-pointer API when configuring markdown colors
582// from the theme palette.
583func hex(c color.Color) *string {
584	r, g, b, _ := c.RGBA()
585	s := fmt.Sprintf("#%02x%02x%02x", r>>8, g>>8, b>>8)
586	return &s
587}
588
589func chromaStyle(style ansi.StylePrimitive) string {
590	var s strings.Builder
591
592	if style.Color != nil {
593		s.WriteString(*style.Color)
594	}
595	if style.BackgroundColor != nil {
596		if s.Len() > 0 {
597			s.WriteString(" ")
598		}
599		s.WriteString("bg:")
600		s.WriteString(*style.BackgroundColor)
601	}
602	if style.Italic != nil && *style.Italic {
603		if s.Len() > 0 {
604			s.WriteString(" ")
605		}
606		s.WriteString("italic")
607	}
608	if style.Bold != nil && *style.Bold {
609		if s.Len() > 0 {
610			s.WriteString(" ")
611		}
612		s.WriteString("bold")
613	}
614	if style.Underline != nil && *style.Underline {
615		if s.Len() > 0 {
616			s.WriteString(" ")
617		}
618		s.WriteString("underline")
619	}
620
621	return s.String()
622}