diff --git a/.stylelintrc.yaml b/.stylelintrc.yaml
index ca0f16b07b..c488d0677f 100644
--- a/.stylelintrc.yaml
+++ b/.stylelintrc.yaml
@@ -1,12 +1,18 @@
 plugins:
   - stylelint-declaration-strict-value
 
+ignoreFiles:
+  - "**/*.go"
+
 overrides:
   - files: ["**/*.less"]
     customSyntax: postcss-less
   - files: ["**/chroma/*", "**/codemirror/*", "**/standalone/*", "**/console/*"]
     rules:
       scale-unlimited/declaration-strict-value: null
+  - files: ["**/chroma/*", "**/codemirror/*"]
+    rules:
+      block-no-empty: null
 
 rules:
   alpha-value-notation: null
diff --git a/web_src/less/chroma/chroma-style-diff.go b/web_src/less/chroma/chroma-style-diff.go
new file mode 100644
index 0000000000..4243259689
--- /dev/null
+++ b/web_src/less/chroma/chroma-style-diff.go
@@ -0,0 +1,79 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+//go:build ignore
+
+/*
+This tool is used to compare the CSS names in a chroma builtin styles with the Gitea theme CSS names.
+
+It outputs the difference between the two sets of CSS names, eg:
+
+```
+CSS names not in builtin:
+.chroma .ln
+----
+Builtin CSS names not in file:
+.chroma .vm
+```
+
+Developers could use this tool to re-sync the CSS names in the Gitea theme.
+*/
+
+package main
+
+import (
+	"os"
+	"regexp"
+	"strings"
+
+	"github.com/alecthomas/chroma/v2"
+)
+
+func main() {
+	if len(os.Args) != 2 {
+		println("Usage: chroma-style-diff css-or-less-file")
+		os.Exit(1)
+	}
+
+	data, err := os.ReadFile(os.Args[1])
+	if err != nil {
+		println(err.Error())
+		os.Exit(1)
+	}
+
+	content := string(data)
+
+	// a simple CSS parser to collect CSS names
+	content = regexp.MustCompile("//.*\r?\n").ReplaceAllString(content, "\n")
+	content = regexp.MustCompile("/\\*.*?\\*/").ReplaceAllString(content, "")
+	matches := regexp.MustCompile("\\s*([-.#:\\w\\s]+)\\s*\\{[^}]*}").FindAllStringSubmatch(content, -1)
+
+	cssNames := map[string]bool{}
+	for _, matchGroup := range matches {
+		cssName := strings.TrimSpace(matchGroup[1])
+		cssNames[cssName] = true
+	}
+
+	// collect Chroma builtin CSS names
+	builtin := map[string]bool{}
+	for tokenType, cssName := range chroma.StandardTypes {
+		if tokenType > 0 && cssName != "" {
+			builtin[".chroma ."+cssName] = true
+		}
+	}
+
+	// show the diff
+	println("CSS names not in builtin:")
+	for cssName := range cssNames {
+		if !builtin[cssName] {
+			println(cssName)
+		}
+	}
+	println("----")
+	println("Builtin CSS names not in file:")
+	for cssName := range builtin {
+		if !cssNames[cssName] {
+			println(cssName)
+		}
+	}
+}
diff --git a/web_src/less/chroma/dark.less b/web_src/less/chroma/dark.less
index 4be9cf7912..1b0c722a16 100644
--- a/web_src/less/chroma/dark.less
+++ b/web_src/less/chroma/dark.less
@@ -7,17 +7,19 @@
 .chroma .cpf { color: #649bc4; } /* CommentPreprocFile */
 .chroma .cs { color: #9075cd; } /* CommentSpecial */
 .chroma .dl { color: #649bc4; } /* LiteralStringDelimiter */
+.chroma .fm {} /* NameFunctionMagic */
+.chroma .g {} /* Generic */
 .chroma .gd { color: #ffffff; background-color: #5f3737; } /* GenericDeleted */
 .chroma .ge { color: #ddee30; } /* GenericEmph */
 .chroma .gh { color: #ffaa10; } /* GenericHeading */
 .chroma .gi { color: #ffffff; background-color: #3a523a; } /* GenericInserted */
+.chroma .gl {} /* GenericUnderline */
 .chroma .go { color: #777e94; } /* GenericOutput */
 .chroma .gp { color: #ebdbb2; } /* GenericPrompt */
 .chroma .gr { color: #ff4433; } /* GenericError */
 .chroma .gs { color: #ebdbb2; } /* GenericStrong */
 .chroma .gt { color: #ff7540; } /* GenericTraceback */
 .chroma .gu { color: #b8bb26; } /* GenericSubheading */
-.chroma .hl { background-color: #3f424d; } /* LineHighlight */
 .chroma .il { color: #649bc4; } /* LiteralNumberIntegerLong */
 .chroma .k { color: #ff7540; } /* Keyword */
 .chroma .kc { color: #649bc4; } /* KeywordConstant */
@@ -25,16 +27,16 @@
 .chroma .kn { color: #ffaa10; } /* KeywordNamespace */
 .chroma .kp { color: #5f8700; } /* KeywordPseudo */
 .chroma .kr { color: #ff7540; } /* KeywordReserved */
-.chroma .kt { color: #fabd2f; } /* KeywordType */
-.chroma .ln { color: #7f8699; } /* LineNumbers */
-.chroma .lnt { color: #7f8699; } /* LineNumbersTable */
+.chroma .kt { color: #ff7b72; } /* KeywordType */
+.chroma .l {} /* Literal */
+.chroma .ld {} /* LiteralDate */
 .chroma .m { color: #649bc4; } /* LiteralNumber */
 .chroma .mb { color: #649bc4; } /* LiteralNumberBin */
 .chroma .mf { color: #649bc4; } /* LiteralNumberFloat */
 .chroma .mh { color: #649bc4; } /* LiteralNumberHex */
 .chroma .mi { color: #649bc4; } /* LiteralNumberInteger */
 .chroma .mo { color: #649bc4; } /* LiteralNumberOct */
-.chroma .n { color: #fabd2f; } /* Name */
+.chroma .n { color: #c9d1d9; } /* Name */
 .chroma .na { color: #b8bb26; } /* NameAttribute */
 .chroma .nb { color: #fabd2f; } /* NameBuiltin */
 .chroma .nc { color: #ffaa10; } /* NameClass */
@@ -51,6 +53,7 @@
 .chroma .o { color: #ff7540; } /* Operator */
 .chroma .ow { color: #5f8700; } /* OperatorWord */
 .chroma .p { color: #d2d4db; } /* Punctuation */
+.chroma .py {} /* NameProperty */
 .chroma .s { color: #b8bb26; } /* LiteralString */
 .chroma .s1 { color: #b8bb26; } /* LiteralStringSingle */
 .chroma .s2 { color: #b8bb26; } /* LiteralStringDouble */
@@ -67,4 +70,5 @@
 .chroma .vc { color: #ff7540; } /* NameVariableClass */
 .chroma .vg { color: #ffaa10; } /* NameVariableGlobal */
 .chroma .vi { color: #ffaa10; } /* NameVariableInstance */
+.chroma .vm {} /* NameVariableMagic */
 .chroma .w { color: #7f8699; } /* TextWhitespace */
diff --git a/web_src/less/chroma/light.less b/web_src/less/chroma/light.less
index 2e811844c2..4bfce8fe71 100644
--- a/web_src/less/chroma/light.less
+++ b/web_src/less/chroma/light.less
@@ -7,16 +7,19 @@
 .chroma .cpf { color: #4c4dbc; } /* CommentPreprocFile */
 .chroma .cs { color: #999999; } /* CommentSpecial */
 .chroma .dl { color: #106303; } /* LiteralStringDelimiter */
+.chroma .fm {} /* NameFunctionMagic */
+.chroma .g {} /* Generic */
 .chroma .gd { color: #000000; background-color: #ffdddd; } /* GenericDeleted */
 .chroma .ge { color: #000000; } /* GenericEmph */
 .chroma .gh { color: #999999; } /* GenericHeading */
 .chroma .gi { color: #000000; background-color: #ddffdd; } /* GenericInserted */
+.chroma .gl {} /* GenericUnderline */
 .chroma .go { color: #888888; } /* GenericOutput */
 .chroma .gp { color: #555555; } /* GenericPrompt */
 .chroma .gr { color: #aa0000; } /* GenericError */
+.chroma .gs {} /* GenericStrong */
 .chroma .gt { color: #aa0000; } /* GenericTraceback */
 .chroma .gu { color: #aaaaaa; } /* GenericSubheading */
-.chroma .hl { background-color: #e5e5e5; } /* LineHighlight */
 .chroma .il { color: #009999; } /* LiteralNumberIntegerLong */
 .chroma .k { color: #d73a49; } /* Keyword */
 .chroma .kc { color: #d73a49; } /* KeywordConstant */
@@ -25,14 +28,15 @@
 .chroma .kp { color: #d73a49; } /* KeywordPseudo */
 .chroma .kr { color: #d73a49; } /* KeywordReserved */
 .chroma .kt { color: #445588; } /* KeywordType */
-.chroma .ln { color: #7f7f7f; } /* LineNumbers */
-.chroma .lnt { color: #7f7f7f; } /* LineNumbersTable */
+.chroma .l {} /* Literal */
+.chroma .ld {} /* LiteralDate */
 .chroma .m { color: #009999; } /* LiteralNumber */
 .chroma .mb { color: #009999; } /* LiteralNumberBin */
 .chroma .mf { color: #009999; } /* LiteralNumberFloat */
 .chroma .mh { color: #009999; } /* LiteralNumberHex */
 .chroma .mi { color: #009999; } /* LiteralNumberInteger */
 .chroma .mo { color: #009999; } /* LiteralNumberOct */
+.chroma .n {} /* Name */
 .chroma .na { color: #d73a49; } /* NameAttribute */
 .chroma .nb { color: #005cc5; } /* NameBuiltin */
 .chroma .nc { color: #445588; } /* NameClass */
@@ -48,6 +52,8 @@
 .chroma .nx { color: #24292e; } /* NameOther */
 .chroma .o { color: #d73a49; } /* Operator */
 .chroma .ow { color: #d73a49; } /* OperatorWord */
+.chroma .p {} /* Punctuation */
+.chroma .py {} /* NameProperty */
 .chroma .s { color: #106303; } /* LiteralString */
 .chroma .s1 { color: #cc7a00; } /* LiteralStringSingle */
 .chroma .s2 { color: #106303; } /* LiteralStringDouble */
@@ -64,4 +70,5 @@
 .chroma .vc { color: #008080; } /* NameVariableClass */
 .chroma .vg { color: #008080; } /* NameVariableGlobal */
 .chroma .vi { color: #008080; } /* NameVariableInstance */
+.chroma .vm {} /* NameVariableMagic */
 .chroma .w { color: #bbbbbb; } /* TextWhitespace */
diff --git a/web_src/less/themes/theme-arc-green.less b/web_src/less/themes/theme-arc-green.less
index 2f06f33aca..17b8f9bae0 100644
--- a/web_src/less/themes/theme-arc-green.less
+++ b/web_src/less/themes/theme-arc-green.less
@@ -1,3 +1,4 @@
+@import "../chroma/base.less";
 @import "../chroma/dark.less";
 @import "../codemirror/dark.less";