Liminal Salt Theme
Liminal Salt is an LLM frontend for OpenRouter that I built in Python and Django, but it also spawned a color theme that I've been using for various projects. The overall aesthetic is inspired by greige, kind of a beige/sage/stone milieu. I've tried to make it accessible and comfortable for reading.
Liminal Salt has an earthy vibe that I really enjoy. I'm transitioning all my tools to use it. Check out the theme on GitHub: liminal-salt
It's still evolving, but here's the current palette:
Dark Theme
Base
The default page background and primary text colors. Foreground Secondary is for supporting text like subtitles and metadata.
#1a1c1b
#e8e4dc
#c5c1b8
Muted
A subdued surface for secondary UI like disabled states, chips, and sidebars. Muted Foreground is for placeholder text and de-emphasized labels.
#141615
#9e9b93
Card
An elevated surface for cards, dialogs, popovers, and panels that sit above the background.
#242726
#e8e4dc
Accent
The primary action color for buttons, links, and interactive highlights. Accent Foreground is the text color on accent-colored surfaces.
#8fac98
#a3bfac
#1a1c1b
Destructive
For destructive actions and error states — delete buttons, form validation errors, error toasts, and danger alerts.
#cc8585
#d99292
#1a1c1b
Success
For confirmations and positive states — saved indicators, valid form fields, success toasts, and completion badges.
#7dba8a
#1a1c1b
Warning
For caution states — warnings, deprecation notices, and attention-needed indicators that aren't errors.
#c9a86c
#1a1c1b
Borders & Focus
Structural and interactive borders. Ring is the focus indicator for keyboard navigation. Input is the default border for form fields. Border is for layout dividers and container edges.
#95bebe
#6b7369
#2e312f
Syntax
Colors for code highlighting — keywords, strings, types, and other language constructs.
#8fac98
#a3bfac
#c9a86c
#7eb8c9
#8fb8ad
#9e9b93
#cc8585
#a9ad78
Editor
Colors for editor chrome — cursor, selection, line highlighting, gutter, and diff backgrounds. These are the tinted surfaces used in code editors and IDEs.
#8fac98
#3d4741
#393a38
#4f4633
#9e9b93
#c5c1b8
#2e312f
#2e312f
#4f3c3b
#384b3c
Light Theme
Base
#f5f2ed
#2d2b28
#5a5753
Muted
#ebe7e0
#6b6762
Card
#fdfcfa
#2d2b28
Accent
#506e58
#425f4a
#f5f2ed
Destructive
#a54d4d
#984242
#f5f2ed
Success
#3a7346
#f5f2ed
Warning
#7d6325
#f5f2ed
Borders & Focus
#3e5d5d
#888379
#ddd8d0
Syntax
#506e58
#425f4a
#7d6325
#3a6f80
#3e6b5d
#6b6762
#a54d4d
#5c6135
Editor
#506e58
#c4cac0
#d7d4cf
#d1c7b1
#6b6762
#5a5753
#ddd8d0
#ddd8d0
#ddc1bd
#bdccbb
Accessibility
All foreground/background pairings meet WCAG 2.1 AA (4.5:1 for normal text, 3:1 for large text). Many primary pairings exceed AAA (7:1).
Dark Theme
On surfaces
Contrast ratios for text and UI elements on the three surface tokens.
| Token | Background | Card | Muted | Level |
|---|---|---|---|---|
| Foreground | 13.5 | 11.9 | 14.3 | AAA |
| Foreground Secondary | 9.5 | 8.4 | 10.1 | AAA |
| Muted Foreground | 6.2 | 5.4 | 6.5 | AA |
| Accent | 7.0 | 6.1 | 7.4 | AA-AAA |
| Accent Hover | 8.7 | 7.6 | 9.2 | AAA |
| Destructive | 5.9 | 5.2 | 6.3 | AA |
| Destructive Hover | 6.9 | 6.1 | 7.3 | AA |
| Success | 7.6 | 6.6 | 8.0 | AA-AAA |
| Warning | 7.6 | 6.7 | 8.1 | AA-AAA |
| Ring | 8.5 | 7.5 | 9.0 | AAA |
| Input | 3.5 | 3.1 | 3.7 | AA (non-text) |
Paired foregrounds
Contrast ratios for foreground tokens measured against their own surface.
| Token | Surface | Contrast | Level |
|---|---|---|---|
| Card Foreground | Card | 11.9 | AAA |
| Accent Foreground | Accent | 7.0 | AAA |
| Destructive Foreground | Destructive | 5.9 | AA |
| Success Foreground | Success | 7.6 | AAA |
| Warning Foreground | Warning | 7.6 | AAA |
Syntax on surfaces
Contrast ratios for syntax highlighting tokens on the three surface tokens.
| Token | Background | Card | Muted | Level |
|---|---|---|---|---|
| Keyword | 7.0 | 6.1 | 7.4 | AA-AAA |
| Function | 8.7 | 7.6 | 9.2 | AAA |
| String | 7.6 | 6.7 | 8.1 | AA-AAA |
| Number | 7.8 | 6.9 | 8.3 | AA-AAA |
| Type | 7.9 | 6.9 | 8.3 | AA-AAA |
| Comment | 6.2 | 5.4 | 6.5 | AA |
| Tag | 5.9 | 5.2 | 6.3 | AA |
| Regex | 7.3 | 6.4 | 7.7 | AA-AAA |
Editor chrome
Contrast ratios for editor text elements on background, and foreground text readability on tinted highlight surfaces.
| Token | On Background | Level |
|---|---|---|
| Cursor | 7.0 | AAA |
| Gutter | 6.2 | AA |
| Gutter Active | 9.5 | AAA |
| Token | Foreground on surface | Level |
|---|---|---|
| Selection | 7.6 | AAA |
| Line Highlight | 9.0 | AAA |
| Find Match | 7.3 | AAA |
| Diff Deleted | 8.1 | AAA |
| Diff Inserted | 7.4 | AAA |
Light Theme
On surfaces
| Token | Background | Card | Muted | Level |
|---|---|---|---|---|
| Foreground | 12.6 | 13.8 | 11.5 | AAA |
| Foreground Secondary | 6.4 | 7.0 | 5.8 | AA-AAA |
| Muted Foreground | 5.0 | 5.5 | 4.6 | AA |
| Accent | 5.1 | 5.5 | 4.6 | AA |
| Accent Hover | 6.3 | 6.9 | 5.7 | AA |
| Destructive | 5.0 | 5.4 | 4.5 | AA |
| Destructive Hover | 5.9 | 6.4 | 5.3 | AA |
| Success | 5.1 | 5.5 | 4.6 | AA |
| Warning | 5.1 | 5.6 | 4.6 | AA |
| Ring | 6.4 | 7.0 | 5.8 | AA-AAA |
| Input | 3.4 | 3.7 | 3.1 | AA (non-text) |
Paired foregrounds
| Token | Surface | Contrast | Level |
|---|---|---|---|
| Card Foreground | Card | 13.8 | AAA |
| Accent Foreground | Accent | 5.1 | AA |
| Destructive Foreground | Destructive | 5.0 | AA |
| Success Foreground | Success | 5.1 | AA |
| Warning Foreground | Warning | 5.1 | AA |
Syntax on surfaces
| Token | Background | Card | Muted | Level |
|---|---|---|---|---|
| Keyword | 5.1 | 5.5 | 4.6 | AA |
| Function | 6.3 | 6.9 | 5.7 | AA |
| String | 5.1 | 5.6 | 4.6 | AA |
| Number | 5.0 | 5.4 | 4.5 | AA |
| Type | 5.4 | 5.9 | 4.9 | AA |
| Comment | 5.0 | 5.5 | 4.6 | AA |
| Tag | 5.0 | 5.4 | 4.5 | AA |
| Regex | 5.8 | 6.4 | 5.3 | AA |
Editor chrome
| Token | On Background | Level |
|---|---|---|
| Cursor | 5.1 | AA |
| Gutter | 5.0 | AA |
| Gutter Active | 6.4 | AA |
| Token | Foreground on surface | Level |
|---|---|---|
| Selection | 8.4 | AAA |
| Line Highlight | 9.5 | AAA |
| Find Match | 8.4 | AAA |
| Diff Deleted | 8.4 | AAA |
| Diff Inserted | 8.4 | AAA |
Examples
Here's how the theme looks applied to common UI elements. Toggle light/dark mode to see both variants.
Buttons
Form Fields
Code Blocks
from dataclasses import dataclass
# Minimum contrast for WCAG AA compliance
CONTRAST_AA = 4.5
@dataclass
class Color:
"""A named color primitive."""
name: str
value: str
luminance: float = 0.0
def meets_aa(self, other: "Color") -> bool:
ratio = self.contrast(other)
return ratio >= CONTRAST_AA
palette = {"sage": "#8fac98", "amber": "#c9a86c"}
total = len(palette)
is_valid = total > 0 and True
print(f"Colors: {total}, valid={is_valid}")
<div class="swatch" data-color="#8fac98">
<span>Sage</span>
<code>#8fac98</code>
</div>
const HEX = /^#([a-f\d]{2}){3}$/i
function parseHex(value) {
if (!HEX.test(value)) {
throw new Error(`Invalid: ${value}`)
}
return [1, 3, 5].map(
(i) => parseInt(value.slice(i, i + 2), 16)
)
}
Blockquote
The Liminal Salt palette draws from natural, earthy tones — muted sage greens and warm beiges that feel grounded without being heavy.
Inline Code & Links
Here's some inline code alongside a link to the repository. The theme's --accent variable drives both the link color and the code highlight, keeping everything visually cohesive across light and dark modes.