▍ humdrum codex / glint v1.0.2
license AGPL-3.0

feat: Flexoki-meets-Alabaster highlighting model (first pass)

127243797a8ab6658a3521e3199e1a00488bc60f
humdrum <me@humdrum.me> · 2026-06-28 21:55

parent 90e7280d

feat: Flexoki-meets-Alabaster highlighting model (first pass)

Reworks markdown highlighting per the design: prose stays at base Text, all
markup punctuation is Muted, and color is reserved for headings (bold + accent,
hashes dimmed), code, links/URLs/wikilinks (shared reference color, brackets
dimmed), list markers, comments (visible), and an ==highlight== background.
Bold/italic render as real styling in a higher-contrast Emphasis tone with
dimmed markers; blockquotes dim the > marker and italicize the text.

Themes: Flexoki light + dark repainted with proper base/accent roles (cyan
links, green code, blue headings, magenta markers, orange comments, yellow
highlight); adds Emphasis/Comment/Highlight roles; Wikilink folds into Link.
buildVisual preserves per-span highlight backgrounds when painting the canvas.

Deferred: per-level heading deepening, the blockquote left-border + text inset
(display layer), and the broader contrast-tuning pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

6 files changed

internal/editor/scanner.go +85 −36
@@ -10,8 +10,9 @@ 	"github.com/charmbracelet/lipgloss"
 )
 
 var (
-	headingRe = regexp.MustCompile(`^\s*#{1,6}\s`)
-	listRe    = regexp.MustCompile(`^\s*([-*+]|\d+\.)\s`)
+	headingRe    = regexp.MustCompile(`^\s*#{1,6}\s`)
+	listRe       = regexp.MustCompile(`^\s*([-*+]|\d+\.)\s`)
+	blockquoteRe = regexp.MustCompile(`^\s*>\s?`)
 )
 
 // blockState carries cross-line context (fenced code, leading frontmatter).
@@ -23,7 +24,11 @@ }
 
 // ScanLines styles every line, threading block state across lines. The returned
 // slice is parallel to the input: out[i] are the spans for lines[i], whose
-// concatenated text equals lines[i] exactly.
+// concatenated text equals lines[i] exactly (the markup-visible invariant).
+//
+// Highlighting model: prose stays at Text; all markup punctuation is Muted;
+// color is reserved for headings, code, links, list markers, comments, and a
+// highlight background; bold/italic render as real styling in the Emphasis tone.
 func ScanLines(lines []string, th theme.Theme) [][]Span {
 	st := &blockState{}
 	out := make([][]Span, len(lines))
@@ -34,20 +39,21 @@ 	return out
 }
 
 func scanLine(row int, line string, st *blockState, th theme.Theme) []Span {
+	muted := lipgloss.NewStyle().Foreground(th.Muted)
 	code := lipgloss.NewStyle().Foreground(th.Code)
-	muted := lipgloss.NewStyle().Foreground(th.Blockquote)
 	trimmed := strings.TrimSpace(line)
 
-	// Fenced code block: body lines are entirely code-colored.
+	// Fenced code block: delimiters muted, body entirely code-colored.
 	if st.inFence {
 		if strings.HasPrefix(trimmed, "```") {
 			st.inFence = false
+			return wholeLine(line, muted)
 		}
 		return wholeLine(line, code)
 	}
 	if strings.HasPrefix(trimmed, "```") {
 		st.inFence = true
-		return wholeLine(line, code)
+		return wholeLine(line, muted)
 	}
 
 	// Leading YAML frontmatter: only valid starting at row 0.
@@ -64,17 +70,30 @@ 		st.inFrontmatter = true
 		return wholeLine(line, muted)
 	}
 
-	// Heading: color the whole line, hashes included.
-	if headingRe.MatchString(line) {
-		return wholeLine(line, lipgloss.NewStyle().Foreground(th.Heading).Bold(true))
+	// Comment line: visible, not dimmed.
+	if strings.HasPrefix(trimmed, "<!--") || strings.HasPrefix(trimmed, "%%") {
+		return wholeLine(line, lipgloss.NewStyle().Foreground(th.Comment))
+	}
+
+	// Heading: dim the hashes, bold + accent the text.
+	if loc := headingRe.FindStringIndex(line); loc != nil {
+		spans := []Span{{Text: line[:loc[1]], Style: muted}}
+		if rest := line[loc[1]:]; rest != "" {
+			spans = append(spans, Span{Text: rest, Style: lipgloss.NewStyle().Foreground(th.Heading).Bold(true)})
+		}
+		return spans
 	}
 
-	// Blockquote.
-	if strings.HasPrefix(trimmed, ">") {
-		return wholeLine(line, muted)
+	// Blockquote: dim the > marker, italicize the quoted text at base color.
+	if loc := blockquoteRe.FindStringIndex(line); loc != nil {
+		spans := []Span{{Text: line[:loc[1]], Style: muted}}
+		if rest := line[loc[1]:]; rest != "" {
+			spans = append(spans, Span{Text: rest, Style: lipgloss.NewStyle().Foreground(th.Text).Italic(true)})
+		}
+		return spans
 	}
 
-	// List marker, then inline-scan the remainder.
+	// List marker (colored), then inline-scan the remainder.
 	if loc := listRe.FindStringIndex(line); loc != nil {
 		marker := line[:loc[1]]
 		rest := line[loc[1]:]
@@ -94,13 +113,10 @@ 	return []Span{{Text: line, Style: style}}
 }
 
 // scanFrontmatter highlights one YAML frontmatter line, keeping every character
-// visible: the spans concatenate back to the raw line exactly.
-//   - "# comment"         -> whole line muted
-//   - "  - item"          -> leading ws + dash (ListMarker) + item (Text)
-//   - "key: value"        -> "key:" (Accent) + " value" (Text)
-//   - anything else       -> whole line Text
+// visible. Frontmatter is metadata: keys lightly accented, values base, markers
+// muted.
 func scanFrontmatter(line string, th theme.Theme) []Span {
-	muted := lipgloss.NewStyle().Foreground(th.Blockquote)
+	muted := lipgloss.NewStyle().Foreground(th.Muted)
 	accent := lipgloss.NewStyle().Foreground(th.Accent)
 	plain := lipgloss.NewStyle().Foreground(th.Text)
 	marker := lipgloss.NewStyle().Foreground(th.ListMarker)
@@ -139,7 +155,8 @@ 	return wholeLine(line, plain)
 }
 
 // scanInline emits styled spans for inline constructs, keeping all markup
-// characters visible. Plain text gets the theme's Text foreground.
+// characters visible (markers Muted, content in its role color). Plain text gets
+// the theme's Text foreground.
 func scanInline(text string, th theme.Theme) []Span {
 	plain := lipgloss.NewStyle().Foreground(th.Text)
 	r := []rune(text)
@@ -151,9 +168,9 @@ 			spans = append(spans, Span{Text: string(r[start:end]), Style: plain})
 		}
 	}
 	for i < len(r) {
-		if tok, style, n, ok := matchToken(r, i, th); ok {
+		if toks, n, ok := matchToken(r, i, th); ok {
 			flush(i)
-			spans = append(spans, Span{Text: tok, Style: style})
+			spans = append(spans, toks...)
 			i += n
 			start = i
 			continue
@@ -164,28 +181,49 @@ 	flush(len(r))
 	return spans
 }
 
-// matchToken tries to match an inline construct starting at r[i]. It returns the
-// token (including its markup), the style, the rune length, and whether matched.
-func matchToken(r []rune, i int, th theme.Theme) (string, lipgloss.Style, int, bool) {
+// matchToken tries to match an inline construct starting at r[i], returning its
+// spans (markup Muted, content in its role color), the rune length, and whether
+// matched. The spans' concatenated text equals the original token exactly.
+func matchToken(r []rune, i int, th theme.Theme) ([]Span, int, bool) {
+	muted := lipgloss.NewStyle().Foreground(th.Muted)
+
 	// Inline code: `...`
 	if r[i] == '`' {
 		if j := indexRune(r, '`', i+1); j > i {
-			return string(r[i : j+1]), lipgloss.NewStyle().Foreground(th.Code), j + 1 - i, true
+			return wrap("`", string(r[i+1:j]), "`", muted,
+				lipgloss.NewStyle().Foreground(th.Code)), j + 1 - i, true
+		}
+	}
+	// Highlight: ==...==
+	if r[i] == '=' && i+1 < len(r) && r[i+1] == '=' {
+		if j := indexSeq(r, "==", i+2); j >= 0 {
+			return wrap("==", string(r[i+2:j]), "==", muted,
+				lipgloss.NewStyle().Foreground(th.Text).Background(th.Highlight)), j + 2 - i, true
 		}
 	}
 	// Wikilink: [[...]]
 	if r[i] == '[' && i+1 < len(r) && r[i+1] == '[' {
 		if j := indexSeq(r, "]]", i+2); j >= 0 {
-			end := j + 2
-			return string(r[i:end]), lipgloss.NewStyle().Foreground(th.Wikilink), end - i, true
+			return wrap("[[", string(r[i+2:j]), "]]", muted,
+				lipgloss.NewStyle().Foreground(th.Link)), j + 2 - i, true
 		}
 	}
-	// Link: [text](url)
+	// Link: [text](url) — text stays prose, the url is the colored reference.
 	if r[i] == '[' {
 		if c := indexRune(r, ']', i+1); c > i && c+1 < len(r) && r[c+1] == '(' {
 			if p := indexRune(r, ')', c+2); p > c {
-				end := p + 1
-				return string(r[i:end]), lipgloss.NewStyle().Foreground(th.Link), end - i, true
+				plain := lipgloss.NewStyle().Foreground(th.Text)
+				link := lipgloss.NewStyle().Foreground(th.Link)
+				spans := []Span{{Text: "[", Style: muted}}
+				if text := string(r[i+1 : c]); text != "" {
+					spans = append(spans, Span{Text: text, Style: plain})
+				}
+				spans = append(spans, Span{Text: "](", Style: muted})
+				if url := string(r[c+2 : p]); url != "" {
+					spans = append(spans, Span{Text: url, Style: link})
+				}
+				spans = append(spans, Span{Text: ")", Style: muted})
+				return spans, p + 1 - i, true
 			}
 		}
 	}
@@ -193,19 +231,30 @@ 	// Bold: ** or __
 	for _, d := range []string{"**", "__"} {
 		if hasPrefixRunes(r, i, d) {
 			if j := indexSeq(r, d, i+2); j >= 0 {
-				end := j + 2
-				return string(r[i:end]), lipgloss.NewStyle().Foreground(th.Text).Bold(true), end - i, true
+				return wrap(d, string(r[i+2:j]), d, muted,
+					lipgloss.NewStyle().Foreground(th.Emphasis).Bold(true)), j + 2 - i, true
 			}
 		}
 	}
 	// Italic: * or _
 	if r[i] == '*' || r[i] == '_' {
 		if j := indexRune(r, r[i], i+1); j > i {
-			end := j + 1
-			return string(r[i:end]), lipgloss.NewStyle().Foreground(th.Text).Italic(true), end - i, true
+			m := string(r[i])
+			return wrap(m, string(r[i+1:j]), m, muted,
+				lipgloss.NewStyle().Foreground(th.Emphasis).Italic(true)), j + 1 - i, true
 		}
 	}
-	return "", lipgloss.Style{}, 0, false
+	return nil, 0, false
+}
+
+// wrap builds [open(markup), content(role), close(markup)] spans, dropping an
+// empty content span. The texts concatenate to open+content+close.
+func wrap(open, content, closing string, markup, role lipgloss.Style) []Span {
+	spans := []Span{{Text: open, Style: markup}}
+	if content != "" {
+		spans = append(spans, Span{Text: content, Style: role})
+	}
+	return append(spans, Span{Text: closing, Style: markup})
 }
 
 func indexRune(r []rune, c rune, from int) int {
internal/editor/scanner_test.go +93 −2
@@ -106,8 +106,99 @@ 	out := ScanLines([]string{"### Title"}, th)
 	if spanText(out[0]) != "### Title" {
 		t.Errorf("heading hashes dropped: %q", spanText(out[0]))
 	}
-	if out[0][0].Style.GetForeground() != th.Heading {
-		t.Errorf("heading not heading-colored")
+	// The hashes are muted; the heading text is heading-colored and bold.
+	if out[0][0].Style.GetForeground() != th.Muted {
+		t.Errorf("heading marker not muted, got %v", out[0][0].Style.GetForeground())
+	}
+	last := out[0][len(out[0])-1]
+	if last.Style.GetForeground() != th.Heading || !last.Style.GetBold() {
+		t.Errorf("heading text not bold heading color")
+	}
+}
+
+func TestScanEmphasisUsesEmphasisToneDimMarkers(t *testing.T) {
+	th := theme.FlexokiDark()
+	out := ScanLines([]string{"a **bold** b"}, th)
+	if spanText(out[0]) != "a **bold** b" {
+		t.Fatalf("text altered: %q", spanText(out[0]))
+	}
+	var sawMutedMarker, sawBoldContent bool
+	for _, sp := range out[0] {
+		if sp.Text == "**" && sp.Style.GetForeground() == th.Muted {
+			sawMutedMarker = true
+		}
+		if sp.Text == "bold" && sp.Style.GetForeground() == th.Emphasis && sp.Style.GetBold() {
+			sawBoldContent = true
+		}
+	}
+	if !sawMutedMarker {
+		t.Error("** markers not muted")
+	}
+	if !sawBoldContent {
+		t.Error("bold content not Emphasis+bold")
+	}
+}
+
+func TestScanLinkTargetColoredBracketsMuted(t *testing.T) {
+	th := theme.FlexokiDark()
+	out := ScanLines([]string{"see [text](http://x)"}, th)
+	if spanText(out[0]) != "see [text](http://x)" {
+		t.Fatalf("text altered: %q", spanText(out[0]))
+	}
+	var url, brackets bool
+	for _, sp := range out[0] {
+		if sp.Text == "http://x" && sp.Style.GetForeground() == th.Link {
+			url = true
+		}
+		if (sp.Text == "[" || sp.Text == "](" || sp.Text == ")") && sp.Style.GetForeground() == th.Muted {
+			brackets = true
+		}
+	}
+	if !url {
+		t.Error("link target not Link-colored")
+	}
+	if !brackets {
+		t.Error("link brackets not muted")
+	}
+}
+
+func TestScanHighlightGetsBackground(t *testing.T) {
+	th := theme.FlexokiDark()
+	out := ScanLines([]string{"a ==mark== b"}, th)
+	if spanText(out[0]) != "a ==mark== b" {
+		t.Fatalf("text altered: %q", spanText(out[0]))
+	}
+	found := false
+	for _, sp := range out[0] {
+		if sp.Text == "mark" && sp.Style.GetBackground() == th.Highlight {
+			found = true
+		}
+	}
+	if !found {
+		t.Error("highlight content has no Highlight background")
+	}
+}
+
+func TestScanCommentVisible(t *testing.T) {
+	th := theme.FlexokiDark()
+	out := ScanLines([]string{"<!-- a note -->"}, th)
+	if out[0][0].Style.GetForeground() != th.Comment {
+		t.Errorf("comment not Comment-colored, got %v", out[0][0].Style.GetForeground())
+	}
+}
+
+func TestScanBlockquoteItalicTextDimMarker(t *testing.T) {
+	th := theme.FlexokiDark()
+	out := ScanLines([]string{"> quoted"}, th)
+	if spanText(out[0]) != "> quoted" {
+		t.Fatalf("text altered: %q", spanText(out[0]))
+	}
+	if out[0][0].Style.GetForeground() != th.Muted {
+		t.Error("blockquote marker not muted")
+	}
+	last := out[0][len(out[0])-1]
+	if last.Style.GetForeground() != th.Text || !last.Style.GetItalic() {
+		t.Error("blockquote text not italic base color")
 	}
 }
 
internal/editor/wrap.go +5 −2
@@ -96,10 +96,13 @@ 	return rows
 }
 
 // withBackground stamps the theme background onto every span's style so the
-// rendered text has no terminal-default gaps between or under glyphs.
+// rendered text has no terminal-default gaps between or under glyphs. Spans that
+// already carry a background (e.g. ==highlight==) keep theirs.
 func withBackground(spans []Span, bg lipgloss.Color) []Span {
 	for i := range spans {
-		spans[i].Style = spans[i].Style.Background(bg)
+		if _, unset := spans[i].Style.GetBackground().(lipgloss.NoColor); unset {
+			spans[i].Style = spans[i].Style.Background(bg)
+		}
 	}
 	return spans
 }
internal/theme/theme.go +12 −9
@@ -12,18 +12,21 @@ 	Name         string
 	GlamourStyle string
 
 	// Markdown element colors.
-	Text       lipgloss.Color
-	Heading    lipgloss.Color
-	Code       lipgloss.Color
-	Link       lipgloss.Color
-	Wikilink   lipgloss.Color
-	ListMarker lipgloss.Color
-	Blockquote lipgloss.Color
-	Accent     lipgloss.Color
+	Text       lipgloss.Color // base prose
+	Emphasis   lipgloss.Color // bold/italic — higher contrast than Text
+	Heading    lipgloss.Color // heading text (bold)
+	Code       lipgloss.Color // inline + fenced code
+	Link       lipgloss.Color // links, URLs, and wikilink targets
+	Wikilink   lipgloss.Color // retained == Link (kept for the all-colors check)
+	ListMarker lipgloss.Color // list bullets / numbers
+	Blockquote lipgloss.Color // blockquote marker + border (muted tone)
+	Comment    lipgloss.Color // HTML / %% comments — visible, not dimmed
+	Accent     lipgloss.Color // frontmatter keys, selection
+	Highlight  lipgloss.Color // ==highlight== background tint
 
 	// UI colors.
 	Background lipgloss.Color
-	Muted      lipgloss.Color
+	Muted      lipgloss.Color // markup punctuation, dimmed
 	StatusFg   lipgloss.Color
 	StatusBg   lipgloss.Color
 	SelFg      lipgloss.Color
internal/theme/theme_test.go +4 −3
@@ -11,9 +11,10 @@
 func TestEveryThemeHasAllColorsSet(t *testing.T) {
 	for _, th := range allThemes() {
 		colors := map[string]lipgloss.Color{
-			"Text": th.Text, "Heading": th.Heading, "Code": th.Code, "Link": th.Link,
-			"Wikilink": th.Wikilink, "ListMarker": th.ListMarker, "Blockquote": th.Blockquote,
-			"Accent": th.Accent, "Background": th.Background, "Muted": th.Muted,
+			"Text": th.Text, "Emphasis": th.Emphasis, "Heading": th.Heading, "Code": th.Code,
+			"Link": th.Link, "Wikilink": th.Wikilink, "ListMarker": th.ListMarker,
+			"Blockquote": th.Blockquote, "Comment": th.Comment, "Accent": th.Accent,
+			"Highlight": th.Highlight, "Background": th.Background, "Muted": th.Muted,
 			"StatusFg": th.StatusFg, "StatusBg": th.StatusBg, "SelFg": th.SelFg,
 			"SelBg": th.SelBg, "Pointer": th.Pointer,
 		}
internal/theme/themes.go +47 −30
@@ -2,22 +2,32 @@ package theme
 
 import "github.com/charmbracelet/lipgloss"
 
-// FlexokiDark is Steph Ango's Flexoki palette, dark variant. Hexes match the
-// user's `md` navigator and the vault ontology.
+// Flexoki by Steph Ango (https://stephango.com/flexoki). Accent hexes use the
+// 400 variants on dark backgrounds and the 600 variants on light, per Flexoki's
+// guidance. The role assignments follow the glint highlighting model: prose at
+// base, markup muted, color reserved for headings, code, links, list markers,
+// comments, and a highlight background; bold/italic use the higher-contrast
+// Emphasis tone.
+
+// FlexokiDark is the Flexoki dark variant: warm near-black paper, soft prose.
 func FlexokiDark() Theme {
+	link := lipgloss.Color("#3AA99F") // cyan-400
 	return Theme{
 		Name:         "flexoki-dark",
 		GlamourStyle: "dark",
-		Text:         lipgloss.Color("#CECDC3"),
-		Heading:      lipgloss.Color("#4385BE"),
-		Code:         lipgloss.Color("#879A39"),
-		Link:         lipgloss.Color("#3AA99F"),
-		Wikilink:     lipgloss.Color("#8B7EC8"),
-		ListMarker:   lipgloss.Color("#CE5D97"),
-		Blockquote:   lipgloss.Color("#878580"),
-		Accent:       lipgloss.Color("#D0A215"),
-		Background:   lipgloss.Color("#100F0F"),
-		Muted:        lipgloss.Color("#878580"),
+		Background:   lipgloss.Color("#100F0F"), // black
+		Text:         lipgloss.Color("#CECDC3"), // base-200 — prose
+		Emphasis:     lipgloss.Color("#E6E4D9"), // base-100 — brighter for bold/italic
+		Muted:        lipgloss.Color("#878580"), // base-500 — markup, dim but readable
+		Heading:      lipgloss.Color("#4385BE"), // blue-400
+		Code:         lipgloss.Color("#879A39"), // green-400
+		Link:         link,
+		Wikilink:     link, // merged into Link
+		ListMarker:   lipgloss.Color("#CE5D97"), // magenta-400
+		Blockquote:   lipgloss.Color("#878580"), // base-500 — quote marker/border
+		Comment:      lipgloss.Color("#DA702C"), // orange-400 — visible meta
+		Accent:       lipgloss.Color("#D0A215"), // yellow-400
+		Highlight:    lipgloss.Color("#3A3517"), // deep olive — ==highlight== bg
 		StatusFg:     lipgloss.Color("#100F0F"),
 		StatusBg:     lipgloss.Color("#4385BE"),
 		SelFg:        lipgloss.Color("#100F0F"),
@@ -26,22 +36,25 @@ 		Pointer:      lipgloss.Color("#CE5D97"),
 	}
 }
 
-// FlexokiLight is the Flexoki light variant — the fix for unreadable text on
-// cream/light terminals.
+// FlexokiLight is the Flexoki light variant: cream paper, near-black prose.
 func FlexokiLight() Theme {
+	link := lipgloss.Color("#24837B") // cyan-600
 	return Theme{
 		Name:         "flexoki-light",
 		GlamourStyle: "light",
-		Text:         lipgloss.Color("#100F0F"),
-		Heading:      lipgloss.Color("#205EA6"),
-		Code:         lipgloss.Color("#66800B"),
-		Link:         lipgloss.Color("#24837B"),
-		Wikilink:     lipgloss.Color("#5E409D"),
-		ListMarker:   lipgloss.Color("#A02F6F"),
-		Blockquote:   lipgloss.Color("#6F6E69"),
-		Accent:       lipgloss.Color("#AD8301"),
-		Background:   lipgloss.Color("#FFFCF0"),
-		Muted:        lipgloss.Color("#6F6E69"),
+		Background:   lipgloss.Color("#FFFCF0"), // paper
+		Text:         lipgloss.Color("#1C1B1A"), // base-950 — prose (leaves room below for Emphasis)
+		Emphasis:     lipgloss.Color("#100F0F"), // black — darker for bold/italic
+		Muted:        lipgloss.Color("#6F6E69"), // base-600 — markup, dim but readable
+		Heading:      lipgloss.Color("#205EA6"), // blue-600
+		Code:         lipgloss.Color("#66800B"), // green-600
+		Link:         link,
+		Wikilink:     link, // merged into Link
+		ListMarker:   lipgloss.Color("#A02F6F"), // magenta-600
+		Blockquote:   lipgloss.Color("#6F6E69"), // base-600 — quote marker/border
+		Comment:      lipgloss.Color("#BC5215"), // orange-600 — visible meta
+		Accent:       lipgloss.Color("#AD8301"), // yellow-600
+		Highlight:    lipgloss.Color("#F0E6BE"), // pale yellow — ==highlight== bg
 		StatusFg:     lipgloss.Color("#FFFCF0"),
 		StatusBg:     lipgloss.Color("#205EA6"),
 		SelFg:        lipgloss.Color("#FFFCF0"),
@@ -52,20 +65,24 @@ }
 
 // Charm is a charm.land / charmbracelet-brand themed dark palette.
 func Charm() Theme {
+	link := lipgloss.Color("#5DD5FF")
 	return Theme{
 		Name:         "charm",
 		GlamourStyle: "dark",
-		Text:         lipgloss.Color("#FFFDF5"),
+		Background:   lipgloss.Color("#16161E"),
+		Text:         lipgloss.Color("#DDDDE6"),
+		Emphasis:     lipgloss.Color("#FFFDF5"),
+		Muted:        lipgloss.Color("#6C6C8A"),
 		Heading:      lipgloss.Color("#FF5FAF"),
 		Code:         lipgloss.Color("#00FFA3"),
-		Link:         lipgloss.Color("#5DD5FF"),
-		Wikilink:     lipgloss.Color("#B575FF"),
+		Link:         link,
+		Wikilink:     link,
 		ListMarker:   lipgloss.Color("#FF5FAF"),
 		Blockquote:   lipgloss.Color("#6C6C8A"),
+		Comment:      lipgloss.Color("#FFB454"),
 		Accent:       lipgloss.Color("#FFD500"),
-		Background:   lipgloss.Color("#16161E"),
-		Muted:        lipgloss.Color("#6C6C8A"),
-		StatusFg:     lipgloss.Color("#FFFDF5"),
+		Highlight:    lipgloss.Color("#3A2E4D"),
+		StatusFg:     lipgloss.Color("#16161E"),
 		StatusBg:     lipgloss.Color("#6B50FF"),
 		SelFg:        lipgloss.Color("#16161E"),
 		SelBg:        lipgloss.Color("#FF5FAF"),