summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-01-26 01:18:02 -0600
committerCraig Jennings <c@cjennings.net>2026-01-26 01:18:02 -0600
commit51418d3b375f5223b98a3b7865ab428886e5acbc (patch)
tree901d188584ead435abaf33efb7aa431bd04af6e5
parent92e2b82170f77ef2b21686916485fb2e3f61efb6 (diff)
feat(theme): restructure dupre-theme into modular architecture
Split monolithic theme into three files following modus-themes pattern: - dupre-palette.el: 30 base colors + 28 semantic mappings - dupre-faces.el: 150+ face definitions organized by package - dupre-theme.el: thin entry point that loads palette and faces Applied 60-30-10 color design rule: - 60% neutrals (grays for comments, metadata, lower headings) - 30% signature blue (#67809c) for keywords, links, directories - 10% accents (gold for h1, green for strings, terracotta for functions)
-rw-r--r--themes/dupre-faces.el838
-rw-r--r--themes/dupre-palette.el131
-rw-r--r--themes/dupre-theme.el160
3 files changed, 1006 insertions, 123 deletions
diff --git a/themes/dupre-faces.el b/themes/dupre-faces.el
new file mode 100644
index 00000000..53f131e5
--- /dev/null
+++ b/themes/dupre-faces.el
@@ -0,0 +1,838 @@
+;;; dupre-faces.el --- Face definitions for dupre-theme -*- lexical-binding: t -*-
+
+;; Author: Craig Jennings <c@cjennings.net>
+
+;;; Commentary:
+
+;; Face definitions for dupre-theme, following the 60-30-10 color rule:
+;; - 60% Neutrals (bg, grays, fg) - the canvas
+;; - 30% Signature blue (#67809c) - theme character
+;; - 10% Accents (gold, green, terracotta) - semantic meaning only
+
+;;; Code:
+
+(require 'dupre-palette)
+
+(defun dupre-theme-set-faces ()
+ "Set all faces for dupre-theme."
+ (dupre-with-colors
+ (custom-theme-set-faces
+ 'dupre
+
+;;;;; Base/abstract faces (for inheritance)
+ `(dupre-accent ((t (:foreground ,yellow))))
+ `(dupre-err ((t (:foreground ,intense-red))))
+ `(dupre-warning ((t (:foreground ,yellow+1))))
+ `(dupre-success ((t (:foreground ,green))))
+ `(dupre-info ((t (:foreground ,blue))))
+ ;; Headings: only level 1 gets gold, rest use blue or neutrals
+ `(dupre-heading-1 ((t (:foreground ,yellow :weight bold :height 1.2))))
+ `(dupre-heading-2 ((t (:foreground ,blue :weight bold :height 1.1))))
+ `(dupre-heading-3 ((t (:foreground ,gray+2 :weight bold))))
+ `(dupre-heading-4 ((t (:foreground ,gray+1 :weight bold))))
+
+;;;;; Core Emacs faces
+ `(default ((t (:foreground ,fg :background ,bg))))
+ `(cursor ((t (:background ,fg))))
+ `(hl-line ((t (:background ,bg+0))))
+ `(region ((t (:background ,bg+2))))
+ `(secondary-selection ((t (:background ,bg+1))))
+ `(fringe ((t (:foreground ,gray-2 :background ,bg+1))))
+ `(vertical-border ((t (:foreground ,bg+2))))
+ `(window-divider ((t (:foreground ,bg+2))))
+ `(window-divider-first-pixel ((t (:foreground ,bg+1))))
+ `(window-divider-last-pixel ((t (:foreground ,bg+1))))
+ `(minibuffer-prompt ((t (:foreground ,blue :weight bold))))
+ `(highlight ((t (:background ,bg+2))))
+ `(shadow ((t (:foreground ,gray))))
+ `(success ((t (:foreground ,green :weight bold))))
+ `(warning ((t (:foreground ,yellow+1 :weight bold))))
+ `(error ((t (:foreground ,intense-red :weight bold))))
+ `(link ((t (:foreground ,blue :underline t))))
+ `(link-visited ((t (:foreground ,gray+1 :underline t))))
+ `(button ((t (:foreground ,blue :underline t))))
+ `(escape-glyph ((t (:foreground ,gray+1))))
+ `(homoglyph ((t (:foreground ,gray+1))))
+ `(nobreak-space ((t (:foreground ,gray+1 :underline t))))
+ `(nobreak-hyphen ((t (:foreground ,gray+1))))
+ `(trailing-whitespace ((t (:background ,red-2))))
+
+;;;;; Mode line
+ `(mode-line ((t (:foreground ,gray+2 :background ,bg+2
+ :box (:line-width -1 :style released-button)))))
+ `(mode-line-inactive ((t (:foreground ,gray :background ,bg+1
+ :box (:line-width -1 :style released-button)))))
+ `(mode-line-buffer-id ((t (:foreground ,blue :weight bold))))
+ `(mode-line-emphasis ((t (:foreground ,fg :weight bold))))
+ `(mode-line-highlight ((t (:box (:line-width 2 :color ,gray+1)))))
+
+;;;;; Header line
+ `(header-line ((t (:foreground ,fg :background ,bg+1
+ :box (:line-width -1 :color ,bg+2)))))
+ `(header-line-highlight ((t (:foreground ,blue))))
+
+;;;;; Tab line (Emacs 27+)
+ `(tab-line ((t (:inherit mode-line :background ,bg+1
+ :box (:line-width 4 :color ,bg+1)))))
+ `(tab-line-tab ((t (:inherit tab-line))))
+ `(tab-line-tab-inactive ((t (:inherit tab-line :foreground ,gray))))
+ `(tab-line-tab-current ((t (:background ,bg+2 :foreground ,fg :weight bold))))
+ `(tab-line-highlight ((t (:background ,bg+1 :foreground ,fg))))
+ `(tab-line-close-highlight ((t (:foreground ,intense-red))))
+
+;;;;; Tab bar (Emacs 27+)
+ `(tab-bar ((t (:background ,bg+1 :foreground ,gray))))
+ `(tab-bar-tab ((t (:background ,bg+2 :foreground ,fg :weight bold))))
+ `(tab-bar-tab-inactive ((t (:background ,bg+1 :foreground ,gray))))
+
+;;;;; Line numbers (Emacs 26+)
+ `(line-number ((t (:foreground ,gray-1 :background ,bg+1))))
+ `(line-number-current-line ((t (:foreground ,yellow :background ,bg+1 :weight bold))))
+ `(line-number-major-tick ((t (:foreground ,gray+1 :background ,bg+1 :weight bold))))
+ `(line-number-minor-tick ((t (:foreground ,gray :background ,bg+1))))
+
+;;;;; Font-lock faces - CORE SYNTAX (30% blue for keywords, 10% accents for semantics)
+ `(font-lock-builtin-face ((t (:foreground ,blue))))
+ `(font-lock-comment-face ((t (:foreground ,gray :slant italic))))
+ `(font-lock-comment-delimiter-face ((t (:foreground ,gray-1))))
+ `(font-lock-doc-face ((t (:foreground ,gray))))
+ `(font-lock-constant-face ((t (:foreground ,gray+2 :weight bold))))
+ `(font-lock-function-name-face ((t (:foreground ,red-1)))) ; terracotta
+ `(font-lock-keyword-face ((t (:foreground ,blue :weight bold))))
+ `(font-lock-negation-char-face ((t (:foreground ,gray+1 :weight bold))))
+ `(font-lock-preprocessor-face ((t (:foreground ,gray+1 :slant italic))))
+ `(font-lock-regexp-grouping-construct ((t (:foreground ,gray+1 :weight bold))))
+ `(font-lock-regexp-grouping-backslash ((t (:foreground ,gray+1 :weight bold))))
+ `(font-lock-string-face ((t (:foreground ,green))))
+ `(font-lock-type-face ((t (:foreground ,gray+2))))
+ `(font-lock-variable-name-face ((t (:foreground ,fg))))
+ `(font-lock-warning-face ((t (:foreground ,intense-red :weight bold))))
+ ;; Emacs 29+ faces
+ `(font-lock-bracket-face ((t (:foreground ,gray+1))))
+ `(font-lock-delimiter-face ((t (:foreground ,gray+1))))
+ `(font-lock-escape-face ((t (:foreground ,gray+1))))
+ `(font-lock-misc-punctuation-face ((t (:foreground ,gray+1))))
+ `(font-lock-number-face ((t (:foreground ,gray+2))))
+ `(font-lock-operator-face ((t (:foreground ,gray+1))))
+ `(font-lock-property-name-face ((t (:foreground ,fg))))
+ `(font-lock-property-use-face ((t (:foreground ,fg))))
+ `(font-lock-punctuation-face ((t (:foreground ,gray+1))))
+ `(font-lock-variable-use-face ((t (:foreground ,fg))))
+
+;;;;; Show-paren
+ `(show-paren-match ((t (:foreground ,fg :background ,green-2 :weight bold))))
+ `(show-paren-mismatch ((t (:foreground ,fg :background ,intense-red :weight bold))))
+ `(show-paren-match-expression ((t (:background ,bg+1))))
+
+;;;;; Search and replace
+ `(isearch ((t (:foreground ,fg :background ,green-2 :weight bold))))
+ `(isearch-fail ((t (:foreground ,fg :background ,red-2 :weight bold))))
+ `(lazy-highlight ((t (:foreground ,bg :background ,yellow :weight bold))))
+ `(isearch-group-1 ((t (:foreground ,fg :background ,blue))))
+ `(isearch-group-2 ((t (:foreground ,fg :background ,green-1))))
+ `(match ((t (:foreground ,fg :background ,green-2 :weight bold))))
+ `(query-replace ((t (:inherit isearch))))
+
+;;;;; Diff mode
+ `(diff-added ((t (:foreground ,green :background ,green-2))))
+ `(diff-removed ((t (:foreground ,red :background ,red-3))))
+ `(diff-changed ((t (:foreground ,yellow :background ,yellow-2))))
+ `(diff-refine-added ((t (:foreground ,fg :background ,green-1 :weight bold))))
+ `(diff-refine-removed ((t (:foreground ,fg :background ,red-2 :weight bold))))
+ `(diff-refine-changed ((t (:foreground ,fg :background ,yellow-1 :weight bold))))
+ `(diff-header ((t (:foreground ,fg :background ,bg+2))))
+ `(diff-file-header ((t (:foreground ,blue :background ,bg+2 :weight bold))))
+ `(diff-hunk-header ((t (:foreground ,gray+1 :background ,bg+1))))
+ `(diff-index ((t (:foreground ,gray))))
+ `(diff-indicator-added ((t (:foreground ,green :weight bold))))
+ `(diff-indicator-removed ((t (:foreground ,red :weight bold))))
+ `(diff-indicator-changed ((t (:foreground ,yellow :weight bold))))
+ `(diff-context ((t (:foreground ,gray))))
+ `(diff-nonexistent ((t (:foreground ,gray-1 :slant italic))))
+
+;;;;; Ediff
+ `(ediff-current-diff-A ((t (:background ,red-3))))
+ `(ediff-current-diff-B ((t (:background ,green-2))))
+ `(ediff-current-diff-C ((t (:background ,yellow-2))))
+ `(ediff-current-diff-Ancestor ((t (:background ,bg+2))))
+ `(ediff-fine-diff-A ((t (:foreground ,fg :background ,red-2 :weight bold))))
+ `(ediff-fine-diff-B ((t (:foreground ,fg :background ,green-1 :weight bold))))
+ `(ediff-fine-diff-C ((t (:foreground ,fg :background ,yellow-1 :weight bold))))
+ `(ediff-fine-diff-Ancestor ((t (:foreground ,fg :background ,bg+2 :weight bold))))
+ `(ediff-even-diff-A ((t (:background ,bg+1))))
+ `(ediff-even-diff-B ((t (:background ,bg+1))))
+ `(ediff-even-diff-C ((t (:background ,bg+1))))
+ `(ediff-even-diff-Ancestor ((t (:background ,bg+1))))
+ `(ediff-odd-diff-A ((t (:background ,bg+1))))
+ `(ediff-odd-diff-B ((t (:background ,bg+1))))
+ `(ediff-odd-diff-C ((t (:background ,bg+1))))
+ `(ediff-odd-diff-Ancestor ((t (:background ,bg+1))))
+
+;;;;; Org-mode - Gold for level 1 only, blue for level 2, then neutrals
+ `(org-level-1 ((t (:inherit dupre-heading-1))))
+ `(org-level-2 ((t (:inherit dupre-heading-2))))
+ `(org-level-3 ((t (:inherit dupre-heading-3))))
+ `(org-level-4 ((t (:inherit dupre-heading-4))))
+ `(org-level-5 ((t (:foreground ,gray+1))))
+ `(org-level-6 ((t (:foreground ,gray+1))))
+ `(org-level-7 ((t (:foreground ,gray))))
+ `(org-level-8 ((t (:foreground ,gray))))
+ `(org-todo ((t (:foreground ,intense-red :weight bold))))
+ `(org-done ((t (:foreground ,green :weight bold))))
+ `(org-headline-done ((t (:foreground ,gray))))
+ `(org-headline-todo ((t (:foreground ,fg))))
+ `(org-date ((t (:foreground ,gray :underline t))))
+ `(org-link ((t (:foreground ,blue :underline t))))
+ `(org-code ((t (:foreground ,green :background ,bg+1))))
+ `(org-verbatim ((t (:foreground ,gray+1 :background ,bg+1))))
+ `(org-block ((t (:background ,bg+0 :extend t))))
+ `(org-block-begin-line ((t (:foreground ,gray :background ,bg+1 :extend t))))
+ `(org-block-end-line ((t (:foreground ,gray :background ,bg+1 :extend t))))
+ `(org-meta-line ((t (:foreground ,gray))))
+ `(org-document-title ((t (:foreground ,yellow :weight bold :height 1.4))))
+ `(org-document-info ((t (:foreground ,gray+1))))
+ `(org-document-info-keyword ((t (:foreground ,gray))))
+ `(org-tag ((t (:foreground ,gray))))
+ `(org-checkbox ((t (:foreground ,blue :weight bold))))
+ `(org-checkbox-statistics-todo ((t (:foreground ,gray+1))))
+ `(org-checkbox-statistics-done ((t (:foreground ,green))))
+ `(org-table ((t (:foreground ,gray+1))))
+ `(org-formula ((t (:foreground ,gray+1))))
+ `(org-special-keyword ((t (:foreground ,gray))))
+ `(org-drawer ((t (:foreground ,gray))))
+ `(org-property-value ((t (:foreground ,gray))))
+ `(org-priority ((t (:foreground ,yellow :weight bold))))
+ `(org-scheduled ((t (:foreground ,fg))))
+ `(org-scheduled-today ((t (:foreground ,fg :weight bold))))
+ `(org-scheduled-previously ((t (:foreground ,gray+1))))
+ `(org-upcoming-deadline ((t (:foreground ,yellow+1))))
+ `(org-warning ((t (:foreground ,intense-red :weight bold))))
+ `(org-agenda-structure ((t (:foreground ,blue :weight bold))))
+ `(org-agenda-date ((t (:foreground ,fg))))
+ `(org-agenda-date-today ((t (:foreground ,yellow :weight bold))))
+ `(org-agenda-date-weekend ((t (:foreground ,gray))))
+ `(org-agenda-done ((t (:foreground ,green))))
+ `(org-time-grid ((t (:foreground ,gray))))
+ `(org-ellipsis ((t (:foreground ,gray :underline nil))))
+
+;;;;; Magit
+ `(magit-section-heading ((t (:foreground ,blue :weight bold))))
+ `(magit-section-highlight ((t (:background ,bg+1))))
+ `(magit-section-heading-selection ((t (:foreground ,yellow))))
+ `(magit-branch-local ((t (:foreground ,blue))))
+ `(magit-branch-remote ((t (:foreground ,green))))
+ `(magit-branch-remote-head ((t (:foreground ,green :weight bold))))
+ `(magit-branch-current ((t (:foreground ,blue :weight bold :box (:line-width -1 :color ,blue)))))
+ `(magit-branch-upstream ((t (:foreground ,gray+1 :slant italic))))
+ `(magit-tag ((t (:foreground ,gray+1))))
+ `(magit-hash ((t (:foreground ,gray))))
+ `(magit-head ((t (:foreground ,blue :weight bold))))
+ `(magit-log-author ((t (:foreground ,gray+1))))
+ `(magit-log-date ((t (:foreground ,gray))))
+ `(magit-log-graph ((t (:foreground ,gray))))
+ `(magit-diff-added ((t (:foreground ,green :background ,green-2))))
+ `(magit-diff-added-highlight ((t (:foreground ,green+1 :background ,green-2))))
+ `(magit-diff-removed ((t (:foreground ,red :background ,red-3))))
+ `(magit-diff-removed-highlight ((t (:foreground ,red+1 :background ,red-3))))
+ `(magit-diff-context ((t (:foreground ,gray))))
+ `(magit-diff-context-highlight ((t (:foreground ,gray+1 :background ,bg+1))))
+ `(magit-diff-hunk-heading ((t (:foreground ,gray+1 :background ,bg+2))))
+ `(magit-diff-hunk-heading-highlight ((t (:foreground ,fg :background ,bg+2 :weight bold))))
+ `(magit-diff-hunk-heading-selection ((t (:foreground ,yellow :background ,bg+2))))
+ `(magit-diff-file-heading ((t (:foreground ,fg :weight bold))))
+ `(magit-diff-file-heading-highlight ((t (:foreground ,fg :background ,bg+1 :weight bold))))
+ `(magit-diff-file-heading-selection ((t (:foreground ,yellow))))
+ `(magit-diff-lines-heading ((t (:foreground ,fg :background ,yellow-2))))
+ `(magit-diffstat-added ((t (:foreground ,green))))
+ `(magit-diffstat-removed ((t (:foreground ,red))))
+ `(magit-dimmed ((t (:foreground ,gray))))
+ `(magit-filename ((t (:foreground ,fg))))
+ `(magit-header-line ((t (:foreground ,blue :weight bold))))
+ `(magit-header-line-key ((t (:foreground ,blue))))
+ `(magit-header-line-log-select ((t (:foreground ,fg :weight bold))))
+ `(magit-keyword ((t (:foreground ,gray+1))))
+ `(magit-keyword-squash ((t (:foreground ,yellow))))
+ `(magit-process-ng ((t (:foreground ,intense-red :weight bold))))
+ `(magit-process-ok ((t (:foreground ,green :weight bold))))
+ `(magit-reflog-amend ((t (:foreground ,gray+1))))
+ `(magit-reflog-checkout ((t (:foreground ,blue))))
+ `(magit-reflog-cherry-pick ((t (:foreground ,green))))
+ `(magit-reflog-commit ((t (:foreground ,green))))
+ `(magit-reflog-merge ((t (:foreground ,green))))
+ `(magit-reflog-other ((t (:foreground ,gray))))
+ `(magit-reflog-rebase ((t (:foreground ,gray+1))))
+ `(magit-reflog-remote ((t (:foreground ,gray))))
+ `(magit-reflog-reset ((t (:foreground ,red))))
+ `(magit-refname ((t (:foreground ,gray))))
+ `(magit-sequence-done ((t (:foreground ,gray))))
+ `(magit-sequence-drop ((t (:foreground ,red))))
+ `(magit-sequence-head ((t (:foreground ,blue))))
+ `(magit-sequence-onto ((t (:foreground ,gray))))
+ `(magit-sequence-part ((t (:foreground ,gray+1))))
+ `(magit-sequence-pick ((t (:foreground ,fg))))
+ `(magit-sequence-stop ((t (:foreground ,green))))
+ `(magit-signature-bad ((t (:foreground ,intense-red :weight bold))))
+ `(magit-signature-error ((t (:foreground ,red))))
+ `(magit-signature-expired ((t (:foreground ,gray+1))))
+ `(magit-signature-good ((t (:foreground ,green))))
+ `(magit-signature-revoked ((t (:foreground ,red))))
+ `(magit-signature-untrusted ((t (:foreground ,gray+1))))
+
+;;;;; Transient (used by Magit)
+ `(transient-heading ((t (:foreground ,blue :weight bold))))
+ `(transient-key ((t (:foreground ,blue))))
+ `(transient-argument ((t (:foreground ,green))))
+ `(transient-value ((t (:foreground ,gray+1))))
+ `(transient-inactive-argument ((t (:foreground ,gray))))
+ `(transient-inactive-value ((t (:foreground ,gray))))
+ `(transient-unreachable ((t (:foreground ,gray-1))))
+ `(transient-unreachable-key ((t (:foreground ,gray-1))))
+ `(transient-enabled-suffix ((t (:foreground ,green :weight bold))))
+ `(transient-disabled-suffix ((t (:foreground ,red :weight bold))))
+ `(transient-separator ((t (:background ,bg+1 :extend t))))
+
+;;;;; Vertico
+ `(vertico-current ((t (:background ,bg+2))))
+ `(vertico-group-title ((t (:foreground ,blue :weight bold))))
+ `(vertico-group-separator ((t (:foreground ,bg+2 :strike-through t))))
+ `(vertico-multiline ((t (:foreground ,gray))))
+
+;;;;; Consult
+ `(consult-preview-line ((t (:background ,bg+1))))
+ `(consult-preview-match ((t (:inherit lazy-highlight))))
+ `(consult-narrow-indicator ((t (:foreground ,yellow))))
+ `(consult-async-running ((t (:foreground ,gray+1))))
+ `(consult-async-finished ((t (:foreground ,green))))
+ `(consult-async-failed ((t (:foreground ,intense-red))))
+ `(consult-key ((t (:foreground ,blue))))
+ `(consult-file ((t (:foreground ,fg))))
+ `(consult-bookmark ((t (:foreground ,fg))))
+ `(consult-buffer ((t (:foreground ,fg))))
+ `(consult-line-number ((t (:foreground ,gray))))
+ `(consult-line-number-prefix ((t (:foreground ,gray-1))))
+ `(consult-grep-context ((t (:foreground ,gray))))
+ `(consult-highlight-match ((t (:foreground ,yellow :weight bold))))
+
+;;;;; Orderless
+ `(orderless-match-face-0 ((t (:foreground ,yellow :weight bold))))
+ `(orderless-match-face-1 ((t (:foreground ,blue :weight bold))))
+ `(orderless-match-face-2 ((t (:foreground ,green :weight bold))))
+ `(orderless-match-face-3 ((t (:foreground ,gray+2 :weight bold))))
+
+;;;;; Marginalia
+ `(marginalia-key ((t (:foreground ,blue))))
+ `(marginalia-value ((t (:foreground ,gray))))
+ `(marginalia-size ((t (:foreground ,gray))))
+ `(marginalia-date ((t (:foreground ,gray))))
+ `(marginalia-file-name ((t (:foreground ,fg))))
+ `(marginalia-file-priv-dir ((t (:foreground ,blue))))
+ `(marginalia-file-priv-exec ((t (:foreground ,green))))
+ `(marginalia-file-priv-link ((t (:foreground ,gray+1))))
+ `(marginalia-file-priv-no ((t (:foreground ,gray))))
+ `(marginalia-file-priv-other ((t (:foreground ,gray+1))))
+ `(marginalia-file-priv-rare ((t (:foreground ,gray+1))))
+ `(marginalia-file-priv-read ((t (:foreground ,gray+1))))
+ `(marginalia-file-priv-write ((t (:foreground ,gray+1))))
+ `(marginalia-documentation ((t (:foreground ,gray :slant italic))))
+ `(marginalia-function ((t (:foreground ,red-1))))
+ `(marginalia-mode ((t (:foreground ,gray+1))))
+ `(marginalia-modified ((t (:foreground ,yellow))))
+ `(marginalia-null ((t (:foreground ,gray-1))))
+ `(marginalia-number ((t (:foreground ,gray+1))))
+ `(marginalia-symbol ((t (:foreground ,fg))))
+ `(marginalia-type ((t (:foreground ,gray+1))))
+ `(marginalia-version ((t (:foreground ,gray))))
+
+;;;;; Company
+ `(company-tooltip ((t (:background ,bg+1 :foreground ,fg))))
+ `(company-tooltip-selection ((t (:background ,bg+2))))
+ `(company-tooltip-common ((t (:foreground ,yellow :weight bold))))
+ `(company-tooltip-common-selection ((t (:foreground ,yellow :weight bold))))
+ `(company-tooltip-annotation ((t (:foreground ,gray))))
+ `(company-tooltip-annotation-selection ((t (:foreground ,gray+1))))
+ `(company-scrollbar-bg ((t (:background ,bg+1))))
+ `(company-scrollbar-fg ((t (:background ,gray))))
+ `(company-preview ((t (:foreground ,gray))))
+ `(company-preview-common ((t (:foreground ,gray+1))))
+ `(company-preview-search ((t (:foreground ,green))))
+ `(company-echo ((t nil)))
+ `(company-echo-common ((t (:foreground ,gray+1))))
+
+;;;;; Corfu
+ `(corfu-default ((t (:background ,bg+1 :foreground ,fg))))
+ `(corfu-current ((t (:background ,bg+2))))
+ `(corfu-border ((t (:background ,bg+2))))
+ `(corfu-bar ((t (:background ,gray))))
+ `(corfu-annotations ((t (:foreground ,gray))))
+ `(corfu-deprecated ((t (:foreground ,gray :strike-through t))))
+ `(corfu-echo ((t (:foreground ,gray))))
+
+;;;;; Embark
+ `(embark-keybinding ((t (:foreground ,blue :weight bold))))
+ `(embark-target ((t (:foreground ,yellow :weight bold))))
+ `(embark-collect-candidate ((t (:foreground ,fg))))
+ `(embark-collect-group-title ((t (:foreground ,blue :weight bold))))
+ `(embark-collect-group-separator ((t (:foreground ,bg+2 :strike-through t))))
+ `(embark-collect-marked ((t (:foreground ,yellow :weight bold))))
+ `(embark-verbose-indicator-title ((t (:foreground ,blue))))
+
+;;;;; Dired
+ `(dired-directory ((t (:foreground ,blue :weight bold))))
+ `(dired-flagged ((t (:foreground ,intense-red))))
+ `(dired-header ((t (:foreground ,blue :weight bold))))
+ `(dired-ignored ((t (:foreground ,gray))))
+ `(dired-mark ((t (:foreground ,yellow :weight bold))))
+ `(dired-marked ((t (:foreground ,yellow :weight bold))))
+ `(dired-perm-write ((t (:foreground ,gray+1))))
+ `(dired-symlink ((t (:foreground ,gray+1))))
+ `(dired-warning ((t (:foreground ,yellow+1))))
+ `(dired-broken-symlink ((t (:foreground ,fg :background ,red-2))))
+
+;;;;; Dirvish
+ `(dirvish-hl-line ((t (:background ,bg+2))))
+ `(dirvish-git-commit-message-face ((t (:foreground ,gray :slant italic))))
+ `(dirvish-subtree-guide ((t (:foreground ,bg+2))))
+ `(dirvish-subtree-state ((t (:foreground ,gray+1))))
+
+;;;;; Flycheck
+ `(flycheck-error ((t (:underline (:style wave :color ,intense-red)))))
+ `(flycheck-warning ((t (:underline (:style wave :color ,yellow+1)))))
+ `(flycheck-info ((t (:underline (:style wave :color ,blue)))))
+ `(flycheck-fringe-error ((t (:foreground ,intense-red))))
+ `(flycheck-fringe-warning ((t (:foreground ,yellow+1))))
+ `(flycheck-fringe-info ((t (:foreground ,blue))))
+ `(flycheck-error-list-error ((t (:foreground ,intense-red))))
+ `(flycheck-error-list-warning ((t (:foreground ,yellow+1))))
+ `(flycheck-error-list-info ((t (:foreground ,blue))))
+ `(flycheck-error-list-filename ((t (:foreground ,fg))))
+ `(flycheck-error-list-line-number ((t (:foreground ,gray))))
+ `(flycheck-error-list-column-number ((t (:foreground ,gray))))
+ `(flycheck-error-list-id ((t (:foreground ,gray))))
+ `(flycheck-error-list-checker-name ((t (:foreground ,gray))))
+ `(flycheck-error-list-highlight ((t (:background ,bg+2))))
+
+;;;;; Flymake
+ `(flymake-error ((t (:underline (:style wave :color ,intense-red)))))
+ `(flymake-warning ((t (:underline (:style wave :color ,yellow+1)))))
+ `(flymake-note ((t (:underline (:style wave :color ,blue)))))
+
+;;;;; Mu4e
+ `(mu4e-header-face ((t (:foreground ,fg))))
+ `(mu4e-header-highlight-face ((t (:background ,bg+2))))
+ `(mu4e-header-key-face ((t (:foreground ,blue :weight bold))))
+ `(mu4e-header-marks-face ((t (:foreground ,yellow))))
+ `(mu4e-header-title-face ((t (:foreground ,blue :weight bold))))
+ `(mu4e-header-value-face ((t (:foreground ,gray+1))))
+ `(mu4e-unread-face ((t (:foreground ,fg :weight bold))))
+ `(mu4e-flagged-face ((t (:foreground ,yellow))))
+ `(mu4e-replied-face ((t (:foreground ,gray+1))))
+ `(mu4e-forwarded-face ((t (:foreground ,gray+1))))
+ `(mu4e-draft-face ((t (:foreground ,gray :slant italic))))
+ `(mu4e-trashed-face ((t (:foreground ,gray :strike-through t))))
+ `(mu4e-attach-number-face ((t (:foreground ,blue :weight bold))))
+ `(mu4e-cited-1-face ((t (:foreground ,gray+1))))
+ `(mu4e-cited-2-face ((t (:foreground ,gray))))
+ `(mu4e-cited-3-face ((t (:foreground ,gray))))
+ `(mu4e-cited-4-face ((t (:foreground ,gray-1))))
+ `(mu4e-cited-5-face ((t (:foreground ,gray-1))))
+ `(mu4e-cited-6-face ((t (:foreground ,gray-1))))
+ `(mu4e-cited-7-face ((t (:foreground ,gray-2))))
+ `(mu4e-compose-header-face ((t (:foreground ,blue :weight bold))))
+ `(mu4e-compose-separator-face ((t (:foreground ,gray))))
+ `(mu4e-contact-face ((t (:foreground ,fg))))
+ `(mu4e-context-face ((t (:foreground ,blue :weight bold))))
+ `(mu4e-footer-face ((t (:foreground ,gray))))
+ `(mu4e-highlight-face ((t (:foreground ,yellow :weight bold))))
+ `(mu4e-link-face ((t (:foreground ,blue :underline t))))
+ `(mu4e-modeline-face ((t (:foreground ,gray+1))))
+ `(mu4e-moved-face ((t (:foreground ,gray :slant italic))))
+ `(mu4e-ok-face ((t (:foreground ,green :weight bold))))
+ `(mu4e-region-code ((t (:background ,bg+1))))
+ `(mu4e-related-face ((t (:foreground ,gray :slant italic))))
+ `(mu4e-special-header-value-face ((t (:foreground ,gray+1))))
+ `(mu4e-system-face ((t (:foreground ,gray :slant italic))))
+ `(mu4e-title-face ((t (:foreground ,blue :weight bold))))
+ `(mu4e-url-number-face ((t (:foreground ,blue :weight bold))))
+ `(mu4e-warning-face ((t (:foreground ,yellow+1 :weight bold))))
+
+;;;;; Elfeed
+ `(elfeed-search-date-face ((t (:foreground ,gray))))
+ `(elfeed-search-title-face ((t (:foreground ,fg))))
+ `(elfeed-search-unread-title-face ((t (:foreground ,fg :weight bold))))
+ `(elfeed-search-feed-face ((t (:foreground ,blue))))
+ `(elfeed-search-tag-face ((t (:foreground ,gray+1))))
+ `(elfeed-search-unread-count-face ((t (:foreground ,gray+1))))
+ `(elfeed-search-filter-face ((t (:foreground ,blue :weight bold))))
+ `(elfeed-log-date-face ((t (:foreground ,gray))))
+ `(elfeed-log-info-level-face ((t (:foreground ,blue))))
+ `(elfeed-log-warn-level-face ((t (:foreground ,yellow+1))))
+ `(elfeed-log-error-level-face ((t (:foreground ,intense-red))))
+ `(elfeed-log-debug-level-face ((t (:foreground ,gray))))
+
+;;;;; Rainbow-delimiters - signature blue first, then neutrals
+ `(rainbow-delimiters-depth-1-face ((t (:foreground ,blue))))
+ `(rainbow-delimiters-depth-2-face ((t (:foreground ,gray+2))))
+ `(rainbow-delimiters-depth-3-face ((t (:foreground ,gray+1))))
+ `(rainbow-delimiters-depth-4-face ((t (:foreground ,gray))))
+ `(rainbow-delimiters-depth-5-face ((t (:foreground ,blue))))
+ `(rainbow-delimiters-depth-6-face ((t (:foreground ,gray+2))))
+ `(rainbow-delimiters-depth-7-face ((t (:foreground ,gray+1))))
+ `(rainbow-delimiters-depth-8-face ((t (:foreground ,gray))))
+ `(rainbow-delimiters-depth-9-face ((t (:foreground ,gray-1))))
+ `(rainbow-delimiters-base-face ((t (:foreground ,fg))))
+ `(rainbow-delimiters-base-error-face ((t (:foreground ,intense-red :weight bold))))
+ `(rainbow-delimiters-unmatched-face ((t (:foreground ,intense-red :weight bold))))
+ `(rainbow-delimiters-mismatched-face ((t (:foreground ,intense-red :weight bold))))
+
+;;;;; Dashboard
+ `(dashboard-banner-logo-title ((t (:foreground ,yellow :weight bold :height 1.2))))
+ `(dashboard-heading ((t (:foreground ,blue :weight bold))))
+ `(dashboard-items-face ((t (:foreground ,fg))))
+ `(dashboard-no-items-face ((t (:foreground ,gray))))
+ `(dashboard-navigator ((t (:foreground ,blue))))
+ `(dashboard-footer ((t (:foreground ,gray :slant italic))))
+ `(dashboard-footer-icon ((t (:foreground ,blue))))
+
+;;;;; Which-key
+ `(which-key-key-face ((t (:foreground ,blue :weight bold))))
+ `(which-key-separator-face ((t (:foreground ,gray))))
+ `(which-key-note-face ((t (:foreground ,gray))))
+ `(which-key-command-description-face ((t (:foreground ,fg))))
+ `(which-key-local-map-description-face ((t (:foreground ,fg))))
+ `(which-key-group-description-face ((t (:foreground ,blue))))
+ `(which-key-special-key-face ((t (:foreground ,yellow :weight bold))))
+ `(which-key-highlighted-command-face ((t (:foreground ,yellow :weight bold))))
+ `(which-key-docstring-face ((t (:foreground ,gray :slant italic))))
+
+;;;;; Eshell
+ `(eshell-prompt ((t (:foreground ,blue :weight bold))))
+ `(eshell-ls-directory ((t (:foreground ,blue :weight bold))))
+ `(eshell-ls-symlink ((t (:foreground ,gray+1))))
+ `(eshell-ls-executable ((t (:foreground ,green))))
+ `(eshell-ls-readonly ((t (:foreground ,gray))))
+ `(eshell-ls-unreadable ((t (:foreground ,gray-1))))
+ `(eshell-ls-special ((t (:foreground ,gray+1))))
+ `(eshell-ls-missing ((t (:foreground ,intense-red))))
+ `(eshell-ls-archive ((t (:foreground ,gray+1))))
+ `(eshell-ls-backup ((t (:foreground ,gray))))
+ `(eshell-ls-product ((t (:foreground ,gray))))
+ `(eshell-ls-clutter ((t (:foreground ,gray-1))))
+
+;;;;; Vterm
+ `(vterm-color-default ((t (:foreground ,fg :background ,bg))))
+ `(vterm-color-black ((t (:foreground ,bg+2 :background ,gray-2))))
+ `(vterm-color-red ((t (:foreground ,red-1 :background ,red))))
+ `(vterm-color-green ((t (:foreground ,green :background ,green+1))))
+ `(vterm-color-yellow ((t (:foreground ,yellow :background ,yellow+1))))
+ `(vterm-color-blue ((t (:foreground ,blue :background ,blue+1))))
+ `(vterm-color-magenta ((t (:foreground ,red :background ,red+1))))
+ `(vterm-color-cyan ((t (:foreground ,steel :background ,steel+1))))
+ `(vterm-color-white ((t (:foreground ,gray+1 :background ,fg))))
+
+;;;;; Compilation
+ `(compilation-info ((t (:foreground ,green))))
+ `(compilation-warning ((t (:foreground ,yellow+1))))
+ `(compilation-error ((t (:foreground ,intense-red))))
+ `(compilation-mode-line-exit ((t (:foreground ,green :weight bold))))
+ `(compilation-mode-line-fail ((t (:foreground ,intense-red :weight bold))))
+ `(compilation-mode-line-run ((t (:foreground ,gray+1))))
+ `(compilation-line-number ((t (:foreground ,gray))))
+ `(compilation-column-number ((t (:foreground ,gray))))
+
+;;;;; Info
+ `(info-title-1 ((t (:inherit dupre-heading-1))))
+ `(info-title-2 ((t (:inherit dupre-heading-2))))
+ `(info-title-3 ((t (:inherit dupre-heading-3))))
+ `(info-title-4 ((t (:inherit dupre-heading-4))))
+ `(info-menu-header ((t (:foreground ,blue :weight bold))))
+ `(info-menu-star ((t (:foreground ,gray+1))))
+ `(info-node ((t (:foreground ,blue :weight bold))))
+ `(info-xref ((t (:foreground ,blue :underline t))))
+ `(info-xref-visited ((t (:foreground ,gray+1 :underline t))))
+ `(info-header-node ((t (:foreground ,fg :weight bold))))
+ `(info-header-xref ((t (:foreground ,blue))))
+ `(info-index-match ((t (:inherit lazy-highlight))))
+
+;;;;; Help
+ `(help-key-binding ((t (:foreground ,blue :background ,bg+1
+ :box (:line-width -1 :color ,bg+2)))))
+ `(help-for-help-header ((t (:foreground ,blue :weight bold :height 1.2))))
+ `(help-argument-name ((t (:foreground ,gray+1 :slant italic))))
+
+;;;;; Custom (customize interface)
+ `(custom-variable-tag ((t (:foreground ,blue :weight bold))))
+ `(custom-group-tag ((t (:foreground ,blue :weight bold :height 1.2))))
+ `(custom-group-tag-1 ((t (:foreground ,blue :weight bold))))
+ `(custom-state ((t (:foreground ,green))))
+ `(custom-changed ((t (:foreground ,yellow))))
+ `(custom-modified ((t (:foreground ,yellow))))
+ `(custom-invalid ((t (:foreground ,intense-red))))
+ `(custom-set ((t (:foreground ,green))))
+ `(custom-themed ((t (:foreground ,blue))))
+ `(custom-saved ((t (:foreground ,green :weight bold))))
+ `(custom-button ((t (:foreground ,fg :background ,bg+1
+ :box (:line-width -1 :style released-button)))))
+ `(custom-button-mouse ((t (:foreground ,fg :background ,bg+2
+ :box (:line-width -1 :style released-button)))))
+ `(custom-button-pressed ((t (:foreground ,fg :background ,bg+1
+ :box (:line-width -1 :style pressed-button)))))
+ `(custom-comment ((t (:foreground ,gray))))
+ `(custom-comment-tag ((t (:foreground ,gray))))
+ `(custom-face-tag ((t (:foreground ,blue :weight bold))))
+ `(custom-link ((t (:foreground ,blue :underline t))))
+ `(custom-visibility ((t (:foreground ,blue :underline t))))
+
+;;;;; Markdown
+ `(markdown-header-face-1 ((t (:inherit dupre-heading-1))))
+ `(markdown-header-face-2 ((t (:inherit dupre-heading-2))))
+ `(markdown-header-face-3 ((t (:inherit dupre-heading-3))))
+ `(markdown-header-face-4 ((t (:inherit dupre-heading-4))))
+ `(markdown-header-face-5 ((t (:foreground ,gray+1))))
+ `(markdown-header-face-6 ((t (:foreground ,gray))))
+ `(markdown-bold-face ((t (:weight bold))))
+ `(markdown-italic-face ((t (:slant italic))))
+ `(markdown-strike-through-face ((t (:strike-through t))))
+ `(markdown-code-face ((t (:foreground ,green :background ,bg+1))))
+ `(markdown-inline-code-face ((t (:foreground ,green :background ,bg+1))))
+ `(markdown-pre-face ((t (:foreground ,green :background ,bg+1))))
+ `(markdown-blockquote-face ((t (:foreground ,gray :slant italic))))
+ `(markdown-list-face ((t (:foreground ,gray+1))))
+ `(markdown-link-face ((t (:foreground ,blue))))
+ `(markdown-url-face ((t (:foreground ,gray :underline t))))
+ `(markdown-link-title-face ((t (:foreground ,fg))))
+ `(markdown-reference-face ((t (:foreground ,gray))))
+ `(markdown-footnote-marker-face ((t (:foreground ,gray+1))))
+ `(markdown-footnote-text-face ((t (:foreground ,gray))))
+ `(markdown-table-face ((t (:foreground ,gray+1))))
+ `(markdown-hr-face ((t (:foreground ,bg+2))))
+ `(markdown-metadata-key-face ((t (:foreground ,gray))))
+ `(markdown-metadata-value-face ((t (:foreground ,gray+1))))
+ `(markdown-language-keyword-face ((t (:foreground ,gray+1))))
+ `(markdown-language-info-face ((t (:foreground ,gray))))
+ `(markdown-gfm-checkbox-face ((t (:foreground ,blue))))
+ `(markdown-highlight-face ((t (:background ,yellow-2))))
+ `(markdown-markup-face ((t (:foreground ,gray))))
+
+;;;;; Eglot/LSP
+ `(eglot-highlight-symbol-face ((t (:background ,bg+2))))
+ `(eglot-diagnostic-tag-unnecessary-face ((t (:foreground ,gray :slant italic))))
+ `(eglot-diagnostic-tag-deprecated-face ((t (:foreground ,gray :strike-through t))))
+
+;;;;; Ace-window
+ `(aw-leading-char-face ((t (:foreground ,yellow :weight bold :height 2.0))))
+ `(aw-background-face ((t (:foreground ,gray))))
+ `(aw-mode-line-face ((t (:foreground ,blue :weight bold))))
+ `(aw-key-face ((t (:foreground ,blue :weight bold))))
+
+;;;;; Avy
+ `(avy-lead-face ((t (:foreground ,fg :background ,yellow-2 :weight bold))))
+ `(avy-lead-face-0 ((t (:foreground ,fg :background ,blue :weight bold))))
+ `(avy-lead-face-1 ((t (:foreground ,fg :background ,bg+2 :weight bold))))
+ `(avy-lead-face-2 ((t (:foreground ,fg :background ,bg+2 :weight bold))))
+ `(avy-background-face ((t (:foreground ,gray))))
+ `(avy-goto-char-timer-face ((t (:foreground ,yellow :weight bold))))
+
+;;;;; Whitespace
+ `(whitespace-space ((t (:foreground ,bg+2))))
+ `(whitespace-tab ((t (:foreground ,bg+2))))
+ `(whitespace-newline ((t (:foreground ,bg+2))))
+ `(whitespace-trailing ((t (:background ,red-2))))
+ `(whitespace-line ((t (:background ,red-3))))
+ `(whitespace-indentation ((t (:foreground ,bg+2 :background ,bg))))
+ `(whitespace-empty ((t (:background ,yellow-2))))
+ `(whitespace-space-after-tab ((t (:foreground ,bg+2 :background ,yellow-2))))
+ `(whitespace-space-before-tab ((t (:foreground ,bg+2 :background ,yellow-2))))
+ `(whitespace-hspace ((t (:foreground ,bg+2))))
+ `(whitespace-big-indent ((t (:background ,red-3))))
+ `(whitespace-missing-newline-at-eof ((t (:background ,yellow-2))))
+
+;;;;; Anzu
+ `(anzu-mode-line ((t (:foreground ,blue :weight bold))))
+ `(anzu-mode-line-no-match ((t (:foreground ,intense-red :weight bold))))
+ `(anzu-match-1 ((t (:foreground ,fg :background ,green-2))))
+ `(anzu-match-2 ((t (:foreground ,fg :background ,blue))))
+ `(anzu-match-3 ((t (:foreground ,fg :background ,bg+2))))
+ `(anzu-replace-highlight ((t (:foreground ,fg :background ,red-2))))
+ `(anzu-replace-to ((t (:foreground ,fg :background ,green-2))))
+
+;;;;; Bookmark
+ `(bookmark-face ((t (:foreground ,blue :background ,bg+1))))
+ `(bookmark-menu-bookmark ((t (:foreground ,blue :weight bold))))
+ `(bookmark-menu-heading ((t (:foreground ,blue :weight bold))))
+
+;;;;; Speedbar
+ `(speedbar-button-face ((t (:foreground ,gray+1))))
+ `(speedbar-directory-face ((t (:foreground ,blue :weight bold))))
+ `(speedbar-file-face ((t (:foreground ,fg))))
+ `(speedbar-highlight-face ((t (:background ,bg+2))))
+ `(speedbar-selected-face ((t (:foreground ,yellow :weight bold))))
+ `(speedbar-separator-face ((t (:foreground ,bg+2 :overline t))))
+ `(speedbar-tag-face ((t (:foreground ,gray+1))))
+
+;;;;; Term
+ `(term-color-black ((t (:foreground ,bg+2 :background ,gray-2))))
+ `(term-color-red ((t (:foreground ,red-1 :background ,red))))
+ `(term-color-green ((t (:foreground ,green :background ,green+1))))
+ `(term-color-yellow ((t (:foreground ,yellow :background ,yellow+1))))
+ `(term-color-blue ((t (:foreground ,blue :background ,blue+1))))
+ `(term-color-magenta ((t (:foreground ,red :background ,red+1))))
+ `(term-color-cyan ((t (:foreground ,steel :background ,steel+1))))
+ `(term-color-white ((t (:foreground ,gray+1 :background ,fg))))
+ `(term-default-fg-color ((t (:foreground ,fg))))
+ `(term-default-bg-color ((t (:background ,bg))))
+
+;;;;; Comint
+ `(comint-highlight-prompt ((t (:foreground ,blue :weight bold))))
+ `(comint-highlight-input ((t (:foreground ,fg :weight bold))))
+
+;;;;; Woman
+ `(woman-bold ((t (:foreground ,fg :weight bold))))
+ `(woman-italic ((t (:foreground ,gray+1 :slant italic))))
+ `(woman-unknown ((t (:foreground ,gray+1))))
+ `(woman-addition ((t (:foreground ,gray+1))))
+
+;;;;; Xref
+ `(xref-file-header ((t (:foreground ,blue :weight bold))))
+ `(xref-line-number ((t (:foreground ,gray))))
+ `(xref-match ((t (:inherit lazy-highlight))))
+
+;;;;; Calendar/Diary
+ `(calendar-today ((t (:foreground ,yellow :weight bold))))
+ `(calendar-weekday-header ((t (:foreground ,fg))))
+ `(calendar-weekend-header ((t (:foreground ,gray))))
+ `(calendar-month-header ((t (:foreground ,blue :weight bold))))
+ `(diary ((t (:foreground ,fg))))
+ `(diary-anniversary ((t (:foreground ,gray+1))))
+ `(diary-time ((t (:foreground ,gray))))
+ `(holiday ((t (:foreground ,green))))
+
+;;;;; Message mode (for email)
+ `(message-header-name ((t (:foreground ,blue :weight bold))))
+ `(message-header-to ((t (:foreground ,fg))))
+ `(message-header-cc ((t (:foreground ,gray+1))))
+ `(message-header-subject ((t (:foreground ,fg :weight bold))))
+ `(message-header-other ((t (:foreground ,gray))))
+ `(message-header-newsgroups ((t (:foreground ,fg))))
+ `(message-header-xheader ((t (:foreground ,gray))))
+ `(message-separator ((t (:foreground ,gray))))
+ `(message-cited-text ((t (:foreground ,gray :slant italic))))
+ `(message-cited-text-1 ((t (:foreground ,gray+1))))
+ `(message-cited-text-2 ((t (:foreground ,gray))))
+ `(message-cited-text-3 ((t (:foreground ,gray))))
+ `(message-cited-text-4 ((t (:foreground ,gray-1))))
+ `(message-mml ((t (:foreground ,gray+1))))
+
+;;;;; Gnus
+ `(gnus-group-mail-1 ((t (:foreground ,fg :weight bold))))
+ `(gnus-group-mail-2 ((t (:foreground ,fg))))
+ `(gnus-group-mail-3 ((t (:foreground ,gray+1))))
+ `(gnus-group-mail-1-empty ((t (:foreground ,gray))))
+ `(gnus-group-mail-2-empty ((t (:foreground ,gray))))
+ `(gnus-group-mail-3-empty ((t (:foreground ,gray))))
+ `(gnus-group-news-1 ((t (:foreground ,fg :weight bold))))
+ `(gnus-group-news-2 ((t (:foreground ,fg))))
+ `(gnus-group-news-3 ((t (:foreground ,gray+1))))
+ `(gnus-group-news-1-empty ((t (:foreground ,gray))))
+ `(gnus-group-news-2-empty ((t (:foreground ,gray))))
+ `(gnus-group-news-3-empty ((t (:foreground ,gray))))
+ `(gnus-summary-normal-read ((t (:foreground ,gray))))
+ `(gnus-summary-normal-unread ((t (:foreground ,fg :weight bold))))
+ `(gnus-summary-normal-ancient ((t (:foreground ,gray-1))))
+ `(gnus-summary-selected ((t (:foreground ,yellow :weight bold))))
+ `(gnus-summary-cancelled ((t (:foreground ,intense-red :strike-through t))))
+ `(gnus-header-name ((t (:foreground ,blue :weight bold))))
+ `(gnus-header-from ((t (:foreground ,fg))))
+ `(gnus-header-subject ((t (:foreground ,fg :weight bold))))
+ `(gnus-header-content ((t (:foreground ,gray))))
+ `(gnus-header-newsgroups ((t (:foreground ,fg))))
+ `(gnus-cite-1 ((t (:foreground ,gray+1))))
+ `(gnus-cite-2 ((t (:foreground ,gray))))
+ `(gnus-cite-3 ((t (:foreground ,gray))))
+ `(gnus-cite-4 ((t (:foreground ,gray-1))))
+ `(gnus-cite-5 ((t (:foreground ,gray-1))))
+ `(gnus-signature ((t (:foreground ,gray :slant italic))))
+
+;;;;; Web-mode
+ `(web-mode-html-tag-face ((t (:foreground ,blue))))
+ `(web-mode-html-tag-bracket-face ((t (:foreground ,gray+1))))
+ `(web-mode-html-attr-name-face ((t (:foreground ,gray+1))))
+ `(web-mode-html-attr-value-face ((t (:foreground ,green))))
+ `(web-mode-html-attr-equal-face ((t (:foreground ,gray+1))))
+ `(web-mode-doctype-face ((t (:foreground ,gray :weight bold))))
+ `(web-mode-comment-face ((t (:foreground ,gray :slant italic))))
+ `(web-mode-css-selector-face ((t (:foreground ,blue))))
+ `(web-mode-css-property-name-face ((t (:foreground ,gray+1))))
+ `(web-mode-css-color-face ((t (:foreground ,gray+1))))
+ `(web-mode-css-at-rule-face ((t (:foreground ,blue :weight bold))))
+ `(web-mode-css-pseudo-class-face ((t (:foreground ,gray+1))))
+ `(web-mode-css-function-face ((t (:foreground ,red-1))))
+ `(web-mode-function-name-face ((t (:foreground ,red-1 :weight bold))))
+ `(web-mode-function-call-face ((t (:foreground ,red-1))))
+ `(web-mode-string-face ((t (:foreground ,green))))
+ `(web-mode-keyword-face ((t (:foreground ,blue :weight bold))))
+ `(web-mode-constant-face ((t (:foreground ,gray+2 :weight bold))))
+ `(web-mode-type-face ((t (:foreground ,gray+2))))
+ `(web-mode-variable-name-face ((t (:foreground ,fg))))
+ `(web-mode-builtin-face ((t (:foreground ,blue))))
+ `(web-mode-symbol-face ((t (:foreground ,gray))))
+ `(web-mode-current-element-highlight-face ((t (:background ,bg+2))))
+ `(web-mode-current-column-highlight-face ((t (:background ,bg+1))))
+ `(web-mode-error-face ((t (:foreground ,intense-red :underline t))))
+ `(web-mode-warning-face ((t (:foreground ,yellow+1 :underline t))))
+ `(web-mode-folded-face ((t (:foreground ,gray :underline t))))
+ `(web-mode-block-face ((t (:background ,bg+0))))
+
+;;;;; Treemacs
+ `(treemacs-directory-face ((t (:foreground ,blue))))
+ `(treemacs-file-face ((t (:foreground ,fg))))
+ `(treemacs-root-face ((t (:foreground ,blue :weight bold :height 1.2))))
+ `(treemacs-git-modified-face ((t (:foreground ,yellow))))
+ `(treemacs-git-added-face ((t (:foreground ,green))))
+ `(treemacs-git-conflict-face ((t (:foreground ,intense-red :weight bold))))
+ `(treemacs-git-ignored-face ((t (:foreground ,gray))))
+ `(treemacs-git-renamed-face ((t (:foreground ,gray+1))))
+ `(treemacs-git-untracked-face ((t (:foreground ,gray))))
+ `(treemacs-tags-face ((t (:foreground ,gray+1))))
+ `(treemacs-help-title-face ((t (:foreground ,blue :weight bold))))
+ `(treemacs-help-column-face ((t (:foreground ,gray))))
+ `(treemacs-fringe-indicator-face ((t (:foreground ,blue))))
+ `(treemacs-on-failure-pulse-face ((t (:background ,red-2))))
+ `(treemacs-on-success-pulse-face ((t (:background ,green-2))))
+
+;;;;; Gptel (AI chat)
+ `(gptel-context-highlight-face ((t (:background ,bg+1))))
+ `(gptel-rewrite-highlight-face ((t (:background ,yellow-2))))
+
+;;;;; Eww
+ `(eww-form-text ((t (:foreground ,fg :background ,bg+1
+ :box (:line-width -1 :color ,bg+2)))))
+ `(eww-form-textarea ((t (:foreground ,fg :background ,bg+1
+ :box (:line-width -1 :color ,bg+2)))))
+ `(eww-form-submit ((t (:foreground ,fg :background ,bg+2
+ :box (:line-width -1 :style released-button)))))
+ `(eww-form-checkbox ((t (:foreground ,blue :background ,bg+1
+ :box (:line-width -1 :color ,bg+2)))))
+ `(eww-form-select ((t (:foreground ,fg :background ,bg+1
+ :box (:line-width -1 :color ,bg+2)))))
+ `(eww-form-file ((t (:foreground ,blue :background ,bg+1
+ :box (:line-width -1 :color ,bg+2)))))
+ `(eww-valid-certificate ((t (:foreground ,green :weight bold))))
+ `(eww-invalid-certificate ((t (:foreground ,intense-red :weight bold))))
+
+;;;;; Shr (simple html renderer)
+ `(shr-link ((t (:foreground ,blue :underline t))))
+ `(shr-selected-link ((t (:foreground ,yellow :underline t))))
+ `(shr-strike-through ((t (:strike-through t))))
+ `(shr-h1 ((t (:inherit dupre-heading-1))))
+ `(shr-h2 ((t (:inherit dupre-heading-2))))
+ `(shr-h3 ((t (:inherit dupre-heading-3))))
+ `(shr-h4 ((t (:inherit dupre-heading-4))))
+ `(shr-h5 ((t (:foreground ,gray+1))))
+ `(shr-h6 ((t (:foreground ,gray))))
+ `(shr-code ((t (:foreground ,green :background ,bg+1))))
+ `(shr-mark ((t (:background ,yellow-2))))
+
+ )))
+
+(provide 'dupre-faces)
+;;; dupre-faces.el ends here
diff --git a/themes/dupre-palette.el b/themes/dupre-palette.el
new file mode 100644
index 00000000..b2451e81
--- /dev/null
+++ b/themes/dupre-palette.el
@@ -0,0 +1,131 @@
+;;; dupre-palette.el --- Color palette for dupre-theme -*- lexical-binding: t -*-
+
+;; Author: Craig Jennings <c@cjennings.net>
+
+;;; Commentary:
+
+;; This file defines the color palette and semantic mappings for dupre-theme.
+;; Colors are defined as hex values for GUI Emacs.
+
+;;; Code:
+
+(defconst dupre-palette
+ '(;;; Base colors
+ (bg "#151311")
+ (bg+0 "#151311")
+ (bg+1 "#252321")
+ (bg+2 "#474544")
+
+ ;; Grays
+ (gray-2 "#58574e")
+ (gray-1 "#6c6a60")
+ (gray "#969385")
+ (gray+1 "#b4b1a2")
+ (gray+2 "#d0cbc0")
+
+ ;; Steel (blue-grays)
+ (steel "#8a9496")
+ (steel+1 "#acb0b3")
+ (steel+2 "#c0c7ca")
+
+ ;; Blues
+ (blue "#67809c")
+ (blue+1 "#b2c3cc")
+ (blue+2 "#d9e2ff")
+
+ ;; Greens
+ (green-2 "#646d14")
+ (green-1 "#869038")
+ (green "#a4ac64")
+ (green+1 "#ccc768")
+
+ ;; Reds
+ (red-3 "#3f1c0f")
+ (red-2 "#7c2a09")
+ (red-1 "#a7502d")
+ (red "#d47c59")
+ (red+1 "#edb08f")
+ (red+2 "#edbca2")
+
+ ;; Yellows
+ (yellow-2 "#875f00")
+ (yellow-1 "#ffd700")
+ (yellow "#d7af5f")
+ (yellow+1 "#ffd75f")
+ (yellow+2 "#f9ee98")
+
+ ;; Intense/alert colors
+ (intense-red "#ff2a00")
+
+ ;; Foreground
+ (fg "#f0fef0"))
+ "Color palette for dupre-theme.
+Each entry is (NAME VALUE) where VALUE is a hex color string.")
+
+(defconst dupre-semantic-mappings
+ '(;;; Status colors
+ (accent yellow)
+ (err intense-red)
+ (warning yellow+1)
+ (success green)
+ (info blue+1)
+
+ ;;; Syntax highlighting
+ (keyword blue)
+ (string green)
+ (comment gray)
+ (constant yellow+1)
+ (function red)
+ (variable blue+1)
+ (type green+1)
+ (builtin yellow)
+ (preprocessor steel+1)
+
+ ;;; UI elements
+ (border bg+2)
+ (selection bg+2)
+ (hl-line bg+0)
+ (link blue+1)
+ (cursor fg)
+ (prompt green)
+
+ ;;; Diff colors
+ (diff-added-bg green-2)
+ (diff-added-fg green)
+ (diff-removed-bg red-3)
+ (diff-removed-fg red)
+ (diff-changed-bg yellow-2)
+ (diff-changed-fg yellow))
+ "Semantic color mappings for dupre-theme.
+Each entry maps a semantic name to a palette color name.")
+
+(defun dupre-get-color (name)
+ "Get the hex value for color NAME from the palette.
+NAME can be a base palette color or a semantic mapping."
+ (let ((semantic (assq name dupre-semantic-mappings)))
+ (if semantic
+ ;; Resolve semantic mapping to base color
+ (dupre-get-color (cadr semantic))
+ ;; Look up in base palette
+ (let ((color (assq name dupre-palette)))
+ (if color
+ (cadr color)
+ (error "Unknown color: %s" name))))))
+
+(defmacro dupre-with-colors (&rest body)
+ "Execute BODY with all palette colors bound as local variables."
+ (declare (indent 0))
+ `(let ,(mapcar (lambda (entry)
+ (list (car entry) (cadr entry)))
+ dupre-palette)
+ ;; Also bind semantic mappings resolved to their values
+ (let ,(mapcar (lambda (entry)
+ (let* ((name (car entry))
+ (target (cadr entry))
+ (resolved (cadr (assq target dupre-palette))))
+ (list name resolved)))
+ dupre-semantic-mappings)
+ ,@body)))
+
+(provide 'dupre-palette)
+;;; dupre-palette.el ends here
diff --git a/themes/dupre-theme.el b/themes/dupre-theme.el
index 96c775f3..5edb1a17 100644
--- a/themes/dupre-theme.el
+++ b/themes/dupre-theme.el
@@ -1,126 +1,58 @@
;;; dupre-theme.el --- A dark and elegant theme for Emacs -*- lexical-binding: t -*-
-;; Version: 0.0.2
+;; Version: 1.0.0
;; Author: Craig Jennings <c@cjennings.net>
;; URL: https://github.com/cjennings/dupre-theme
;; Keywords: dark theme faces
;;; Commentary:
-;; A modified version of the distinguished theme by Kim Silkebækken
-;; <kim.silkebaekken@gmail.com>. This version by Craig Jennings
-;; <c@cjennings.net>.
+;; A dark, warm theme for Emacs with 150+ face definitions.
+;; Originally based on the distinguished theme by Kim Silkebaekken.
+;;
+;; This theme is optimized for GUI Emacs. Terminal fallbacks are basic.
+;;
+;; Color palette follows a warm aesthetic:
+;; - Yellow (#d7af5f) as primary accent
+;; - Blue (#67809c) for keywords and navigation
+;; - Green (#a4ac64) for strings and success
+;; - Red (#d47c59) for functions and emphasis
+;;
+;; File structure:
+;; - dupre-theme.el (this file) - Theme definition and entry point
+;; - dupre-palette.el - Color definitions and semantic mappings
+;; - dupre-faces.el - All face specifications (~150 faces)
;;; Code:
+(eval-and-compile
+ ;; Add themes directory to load-path for require
+ (when-let ((dir (file-name-directory (or load-file-name
+ buffer-file-name
+ (locate-library "dupre-theme")))))
+ (unless (member dir load-path)
+ (add-to-list 'load-path dir))))
+
+(require 'dupre-palette)
+(require 'dupre-faces)
+
(defgroup dupre-theme nil
"Options for the `dupre' colour theme."
:group 'faces)
(deftheme dupre
- "A dark and elegant theme for Emacs.")
-
-(let* ((dupre-fg (if (display-graphic-p) "#f0fef0" "color-231"))
- (dupre-bg (if (display-graphic-p) "#000000" "color-232"))
- (dupre-bg+0 (if (display-graphic-p) "#151311" "color-234"))
- (dupre-bg+1 (if (display-graphic-p) "#252321" "color-236"))
- (dupre-bg+2 (if (display-graphic-p) "#474544" "color-238"))
- (dupre-gray-2 (if (display-graphic-p) "#58574e" "color-240"))
- (dupre-gray-1 (if (display-graphic-p) "#6c6a60" "color-242"))
- (dupre-gray (if (display-graphic-p) "#969385" "color-243"))
- (dupre-gray+1 (if (display-graphic-p) "#b4b1a2" "color-250"))
- (dupre-gray+2 (if (display-graphic-p) "#d0cbc0" "color-252"))
- (dupre-steel (if (display-graphic-p) "#8a9496" "color-245"))
- (dupre-steel+1 (if (display-graphic-p) "#acb0b3" "color-247"))
- (dupre-steel+2 (if (display-graphic-p) "#c0c7ca" "color-251"))
- (dupre-blue (if (display-graphic-p) "#67809c" "color-173"))
- (dupre-blue+1 (if (display-graphic-p) "#b2c3cc" "color-66" ))
- (dupre-blue+2 (if (display-graphic-p) "#d9e2ff" "color-69" ))
- (dupre-green-2 (if (display-graphic-p) "#646d14" "color-22" ))
- (dupre-green-1 (if (display-graphic-p) "#869038" "color-28" ))
- (dupre-green (if (display-graphic-p) "#a4ac64" "color-143"))
- (dupre-green+1 (if (display-graphic-p) "#ccc768" "color-67" ))
- (dupre-red-3 (if (display-graphic-p) "#3f1c0f" "color-124"))
- (dupre-red-2 (if (display-graphic-p) "#7c2a09" "color-196"))
- (dupre-red-1 (if (display-graphic-p) "#a7502d" "color-160"))
- (dupre-red (if (display-graphic-p) "#d47c59" "color-179"))
- (dupre-red+1 (if (display-graphic-p) "#edb08f" "color-173"))
- (dupre-red+2 (if (display-graphic-p) "#edbca2" "color-208"))
- (dupre-yellow-2 (if (display-graphic-p) "#875f00" "color-94"))
- (dupre-yellow-1 (if (display-graphic-p) "#ffd700" "color-220"))
- (dupre-yellow (if (display-graphic-p) "#d7af5f" "color-226"))
- (dupre-yellow+1 (if (display-graphic-p) "#ffd75f" "color-137"))
- (dupre-yellow+2 (if (display-graphic-p) "#f9ee98" "color-228"))
- (dupre-intense-red (if (display-graphic-p) "#ff2a00" "color-202")))
-
- ;; Tell Emacs “this is a dark theme”
- (custom-theme-set-variables
- 'dupre
- `(frame-background-mode 'dark)
- `(fringe-mode 8))
-
- (custom-theme-set-faces
- 'dupre
-
- ;; basics
- `(default ((t (:foreground ,dupre-fg :background ,dupre-bg))))
- `(cursor ((t (:background ,dupre-fg))))
- `(hl-line ((t (:background ,dupre-bg+0))))
- `(minibuffer-prompt ((t (:foreground ,dupre-green :weight bold))))
- `(region ((t (:background ,dupre-bg+2))))
- `(fringe ((t (:foreground ,dupre-gray-2 :background ,dupre-bg+1))))
- `(vertical-border ((t (:foreground ,dupre-bg+2))))
- `(mode-line ((t (:foreground ,dupre-gray+2 :background ,dupre-bg+2
- :box (:line-width -1 :style released-button)))))
- `(mode-line-inactive ((t (:foreground ,dupre-gray :background ,dupre-bg+1
- :box (:line-width -1 :style released-button)))))
- `(mode-line-buffer-id ((t (:foreground ,dupre-yellow :weight bold))))
- `(button ((t (:foreground ,dupre-blue+1 :underline t))))
-
- ;; font-lock
- `(font-lock-builtin-face ((t (:foreground ,dupre-yellow :weight bold))))
- `(font-lock-comment-face ((t (:foreground ,dupre-gray :slant italic))))
- `(font-lock-comment-delimiter-face ((t (:foreground ,dupre-bg+2))))
- `(font-lock-doc-face ((t (:foreground ,dupre-gray))))
- `(font-lock-constant-face ((t (:foreground ,dupre-yellow+1 :weight bold))))
- `(font-lock-function-name-face ((t (:foreground ,dupre-red :weight bold))))
- `(font-lock-keyword-face ((t (:foreground ,dupre-blue :weight bold))))
- `(font-lock-negation-char-face ((t (:foreground ,dupre-yellow :weight bold))))
- `(font-lock-preprocessor-face ((t (:foreground ,dupre-steel+1 :weight bold :slant italic))))
- `(font-lock-regexp-grouping-construct ((t (:foreground ,dupre-yellow :weight bold))))
- `(font-lock-regexp-grouping-backslash ((t (:foreground ,dupre-red :weight bold))))
- `(font-lock-string-face ((t (:foreground ,dupre-green))))
- `(font-lock-type-face ((t (:foreground ,dupre-green+1 :weight bold))))
- `(font-lock-variable-name-face ((t (:foreground ,dupre-blue+1 :slant italic))))
- `(font-lock-warning-face ((t (:foreground ,dupre-intense-red :weight bold))))
+ "A dark and elegant theme for Emacs with warm undertones."
+ :background-mode 'dark
+ :kind 'color-scheme)
- ;; show-paren
- `(show-paren-match ((t (:foreground ,dupre-fg :background ,dupre-green-2 :weight bold))))
- `(show-paren-mismatch ((t (:foreground ,dupre-fg :background ,dupre-intense-red :weight bold))))
+;; Set theme variables
+(custom-theme-set-variables
+ 'dupre
+ '(frame-background-mode 'dark)
+ '(fringe-mode 8))
- ;; isearch
- `(isearch ((t (:foreground ,dupre-fg :background ,dupre-green-2
- :weight bold :box (:line-width -1 :style released-button)))))
- `(isearch-fail ((t (:foreground ,dupre-fg :background ,dupre-red-1
- :weight bold :box (:line-width -1 :style released-button)))))
- `(lazy-highlight ((t (:foreground ,dupre-bg :background ,dupre-yellow+1
- :weight bold :box (:line-width -1 :style released-button)))))
-
- ;; line numbers (Emacs ≥26.1)
- (when (>= emacs-major-version 26)
- `(line-number ((t (:foreground ,dupre-gray-1 :background ,dupre-bg+1))))
- `(line-number-current-line ((t (:foreground ,dupre-yellow :background ,dupre-bg+1 :weight bold)))))
-
- ;; tab-line (Emacs ≥27.1)
- (when (>= emacs-major-version 27)
- `(tab-line ((t (:inherit mode-line :background ,dupre-bg+1 :box (:line-width 4 :color ,dupre-bg+1)))))
- `(tab-line-tab ((t (:inherit tab-line))))
- `(tab-line-tab-inactive ((t (:inherit tab-line :foreground ,dupre-gray))))
- `(tab-line-tab-current ((t (:background ,dupre-bg+2 …))))
- `(tab-line-highlight ((t (:background ,dupre-bg+1 …)))))
-
- ) ; closes the WHEN
- ) ; closes custom-theme-set-faces
+;; Apply all face definitions
+(dupre-theme-set-faces)
;;;###autoload
(when load-file-name
@@ -129,21 +61,3 @@
(provide-theme 'dupre)
;;; dupre-theme.el ends here
-
-;; --------------------------------- ERT Tests ---------------------------------
-
-(require 'ert)
-
-(ert-deftest dupre-theme-default-face ()
- "dupre-theme should set the default face correctly."
- (load-theme 'dupre t)
- ;; In a graphical Emacs we expect "#000000"/"#f0fef0"
- (let ((bg (face-attribute 'default :background))
- (fg (face-attribute 'default :foreground)))
- (should (string= bg "#000000"))
- (should (string= fg "#f0fef0"))))
-
-(ert-deftest dupre-theme-comment-face-italic ()
- "Comments should be rendered in italic slant."
- (load-theme 'dupre t)
- (should (eq (face-attribute 'font-lock-comment-face :slant) 'italic)))