✠  A reliquary of materials  ✠

Cremisi

A gothic, arcane colour scheme for Sublime Text, VS Code and more.
Every colour is born from an object: blood, bone, stone, amber, verdigris.

Obsidian ◆ Ivory
I

Concept

Blood, bone, stone

Cremisi is a cabinet of materials: every hue comes from a real substance, desaturated, earthy, mineral.

The backbone never changes. Blood is the protagonist, bone is the text, stone is the ground. Everything else revolves around these three.

Its colours are wax, resin and oxidised copper, with two cold notes: lapis, ground for illuminated missals, and verdigris, the patina on bronze doors.

Blood #e2586a
Bone #e9e1d1
Crypt stone #17171c
  1. I

    Crypt stone

    The dark ground is cold slate grey, the stone of a crypt.

  2. II

    Crimson rules

    Keywords, control flow, booleans and accents all speak with the voice of blood.

  3. III

    Two cold notes

    Lapis blue for functions and keys, verdigris for properties. Every other hue is warm or mineral.

  4. IV

    Earthly matter

    Desaturated, warm, earthy and mineral colours, drawn from wax, resin, copper and stone.

II

Palette

The materials

Sixteen materials with the same names in both variants: only the values change. Click a colour to copy its hex.

Crypt stone

ground

#17171c#f4eee2

Background

The cold slab on which everything rests.

Bone / ink

ink

#e9e1d1#2b2733

Text, variables

Polished bone, scriptorium ink.

13.74:112.61:1AA

Wrought iron

iron

#9a948c#64606c

Punctuation

The grilles that divide, the nails that hold.

5.94:15.30:1AA

Incense

incense

#9e8d99#8a7f8c

Comments

Smoke that rises and fades between the lines.

5.72:13.31:1exempt

Crimson

crimson

#c42740#c42740

Accent, caret, selection

The heart of the reliquary, identical in both variants.

Crimson deep

crimson_deep

#7e1023#7e1023

Selection border

Blood clotted at the edges of the selection.

Blood

blood

#e2586a#bb1f39

Keywords, control flow, booleans, tags, exceptions

The word that commands.

4.97:15.40:1AA

Lapis

lapis

#6886bb#2d5c9c

Functions, JSON and YAML keys

The deep cold note, ground for missals.

4.86:15.82:1AA

Tallow

tallow

#dccb9a#7e6410

Types, classes, namespaces, attributes

Candle wax for the names that endure.

11.10:14.89:1AA

Amber

amber

#cf9142#9f5c12

Numbers, constants

Ancient resin that traps the numbers.

6.62:14.53:1AA

Sealing wax

sealwax

#c6784c#a24d20

Decorators, annotations, escapes, placeholders, regex

The seal pressed upon decorators, and on the escapes set inside strings.

5.27:15.02:1AA

Malachite

malachite

#44a078#2f7a4e

Strings

Green stone for quoted words.

5.57:14.53:1AA

Verdigris

verdigris

#6bb3b0#1a706d

Properties, members

The cold patina that ages on church doors.

7.40:15.07:1AA

Amethyst

amethyst

#9c7bb0#7e3a9e

Builtins, self, YAML anchors

A bishop's gem for what is born with the language.

5.00:16.09:1AA

Wine

wine

#b27a90#8a3f64

Operators, imports, key-value colons

The chalice of operators.

5.17:16.11:1AA

Withered petal

petal

#c58f96#a8465f

Parameters

Dried petals pressed between the pages.

6.59:14.90:1AA

Interface variables border#302f35#e9e1d1 gutter_fg#4e4a50#b3aa9a
III

Beyond the editor

Two scales

Eleven steps of stone and eleven of blood, interpolated in OKLCH, for building interfaces on top of Cremisi. Structure and identity, and nothing else, on purpose: syntax highlighting stays with the materials. Click a step to copy its hex.

Stone

Structure

Not a neutral grey. The hue slides from warm bone at 85° to the violet stone of the crypt at 285°, crossing a faintly rosy grey on the way: the family of incense. Ivory and Obsidian are the same stone, read from opposite ends.

  1. 50 #f4eee2 85° = Ivory ground Aa15.46 Aa1.00
  2. 100 #e9e1d1 85° = Obsidian ink, Ivory border Aa13.74 Aa1.12
  3. 200 #cfc6b8 79° Aa10.57 Aa1.46
  4. 300 #b3aa9a 82° = Ivory gutter Aa7.77 Aa1.99
  5. 400 #9a948c 75° = Obsidian iron Aa5.94 Aa2.60
  6. 500 #827a76 49° Aa4.25 Aa3.64
  7. 600 #696164 353° Aa2.97 Aa5.20
  8. 700 #4e4a50 315° = Obsidian gutter Aa2.06 Aa7.51
  9. 800 #302f35 293° = Obsidian border Aa1.35 Aa11.48
  10. 900 #17171c 286° = Obsidian ground Aa1.00 Aa15.46
  11. 950 #0c0c10 285° Aa1.09 Aa16.90

Blood

Identity

Steps 400 to 800 are the reds the theme already speaks. Above them the scale opens toward the petal, for badges and alerts on Ivory; below, it thickens into clotted blood, for error and diff grounds on Obsidian.

  1. 50 #feeff0 13° Aa16.01 Aa1.04
  2. 100 #ffddde 16° Aa14.16 Aa1.09
  3. 200 #febec1 16° Aa11.35 Aa1.36
  4. 300 #fa969f 14° Aa8.44 Aa1.83
  5. 400 #ef6f80 14° Aa6.17 Aa2.50
  6. 500 #e2586a 16° = blood Aa4.97 Aa3.11
  7. 600 #c42740 19° = crimson Aa3.16 Aa4.90
  8. 700 #a11730 19° Aa2.28 Aa6.78
  9. 800 #7e1023 19° = crimson deep Aa1.69 Aa9.15
  10. 900 #52151f 15° Aa1.26 Aa12.23
  11. 950 #301419 10° Aa1.05 Aa14.66

◆already a colour of the theme 4.5:1 or more: text 3:1: large text, borders, icons below 3:1: surfaces only

Obsidian
Ivory
RoleObsidianIvory
Ground stone-900 stone-50
Sidebar stone-950 stone-100
Borders stone-800 stone-200
Field border stone-700 stone-300
Text stone-100 stone-900
Muted text stone-400 stone-600
Accent blood-600 blood-600
On accent stone-50 stone-50
RoleObsidianIvory
Links blood-400 blood-700
Focus ring blood-500 blood-500
Badge blood-900 blood-100
Badge text blood-200 blood-800
Alert blood-950 blood-50
Alert border blood-800 blood-200
Alert text blood-200 blood-800

Take them with you

Twenty-two custom properties, --cremisi-stone-* and --cremisi-blood-*. The example above is built from nothing else: map them to roles in your own interface, as in the table, and Obsidian and Ivory follow.

cremisi-scales.css
/* Cremisi tonal scales · stone for structure, blood for identity */
:root {
  --cremisi-stone-50: #f4eee2;
  --cremisi-stone-100: #e9e1d1;
  --cremisi-stone-200: #cfc6b8;
  --cremisi-stone-300: #b3aa9a;
  --cremisi-stone-400: #9a948c;
  --cremisi-stone-500: #827a76;
  --cremisi-stone-600: #696164;
  --cremisi-stone-700: #4e4a50;
  --cremisi-stone-800: #302f35;
  --cremisi-stone-900: #17171c;
  --cremisi-stone-950: #0c0c10;

  --cremisi-blood-50: #feeff0;
  --cremisi-blood-100: #ffddde;
  --cremisi-blood-200: #febec1;
  --cremisi-blood-300: #fa969f;
  --cremisi-blood-400: #ef6f80;
  --cremisi-blood-500: #e2586a;
  --cremisi-blood-600: #c42740;
  --cremisi-blood-700: #a11730;
  --cremisi-blood-800: #7e1023;
  --cremisi-blood-900: #52151f;
  --cremisi-blood-950: #301419;
}
IV

Preview

The scriptorium

The theme at work in six languages. Italic for declarations, functions and types, bold for control flow, bold italic for booleans.

 1import re
 2from dataclasses import dataclass, field
 3
 4# The reliquary keeps what time cannot consume.
 5SEAL = re.compile(r"^[A-Z]{3}-\d{4}$")
 6MAX_RELICS = 0x2A
 7
 8
 9@dataclass(frozen=True)
10class Relic:
11    name: str
12    century: int
13    materials: list[str] = field(default_factory=list)
14
15
16class Reliquary:
17    """A crypt casket, sealed with wax."""
18
19    def __init__(self, abbey: str, sealed: bool = True) -> None:
20        self.abbey = abbey
21        self.sealed = sealed
22        self._casket: dict[str, Relic] = {}
23
24    def enshrine(self, relic: Relic, *, code: str) -> bool:
25        if not SEAL.match(code):
26            raise ValueError(f"Broken seal: {code!r}\n")
27        for name in self._casket:
28            if name == relic.name:
29                return False
30        self._casket[relic.name] = relic
31        return len(self._casket) <= MAX_RELICS
32
33    @property
34    def antiquity(self) -> float | None:
35        centuries = [r.century for r in self._casket.values()]
36        return sum(centuries) / len(centuries) * 1.0 if centuries else None
Cremisi ObsidianIvory PythonUTF-8Line 25, Column 9
Bone / ink Wrought iron Blood Lapis Tallow Amber Sealing wax Malachite Verdigris Amethyst Wine Withered petal
V

Typography of code

Four voices

Each font style carries a meaning. The shape of the letter tells you the role before the colour does.

def

Italic

  • Comments
  • Keywords and declarations
  • Imports
  • Functions
  • Types and classes
  • Parameters
  • Attributes
  • Builtins and self
  • Constants
  • Exceptions
return

Bold

  • Control flow: if, for, while, return
True

Bold italic

  • Booleans
"amen"

Regular

  • Strings
  • Numbers
  • Operators
  • Punctuation
  • Variables
VI

Legibility

The rule of contrast

Every code token clears the WCAG threshold of 4.5:1 against its own variant's background. Only comments, the smoke of incense, may fall below.

Obsidian #17171c Ivory #f4eee2
Bone / ink 13.74 12.61
Wrought iron 5.94 5.30
Incense exempt 5.72 3.31
Blood 4.97 5.40
Lapis 4.86 5.82
Tallow 11.10 4.89
Amber 6.62 4.53
Sealing wax 5.27 5.02
Malachite 5.57 4.53
Verdigris 7.40 5.07
Amethyst 5.00 6.09
Wine 5.17 6.11
Withered petal 6.59 4.90
AA threshold · 4.5:1 AA threshold · 4.5:1
VII

Rite of entry

Install Cremisi

Sublime Text and VS Code are below. Further ports are available in the repository: vari-sh/Cremisi-Theme.

Sublime Text

  1. Download both variants below.
  2. Copy them into your Packages/User folder (Preferences → Browse Packages…).
  3. Open the command palette and run UI: Select Color Scheme.

VS Code

  1. Install Cremisi from the Visual Studio Marketplace: search for it in the Extensions view, or press Ctrl+P and run ext install vari-sh.cremisi-theme.
  2. For VSCodium or an offline machine, download the extension below and run Extensions: Install from VSIX….
  3. Run Preferences: Color Theme and pick Cremisi Obsidian or Cremisi Ivory. To follow the system appearance:
{
  "window.autoDetectColorScheme": true,
  "workbench.preferredDarkColorTheme": "Cremisi Obsidian",
  "workbench.preferredLightColorTheme": "Cremisi Ivory"
}
VIII

The codex of decisions

What was chosen

  1. i.

    Crimson #c42740 is the only colour shared by both variants. It is the accent.

  2. ii.

    Rather than black, the editor background is slate #17171c: the cold stone of a crypt.

  3. iii.

    Every hue runs warm except lapis and verdigris, the only cold notes: functions and keys, then properties.

  4. iv.

    Malachite and tallow carry strings and types; amethyst marks builtins and self, the words the language owns.

  5. v.

    Incense lives in comments, a soft smoke that recedes behind the code.

  6. vi.

    Sealing wax marks decorators outside strings, escapes and regex inside them: the two never meet.

  7. vii.

    Interfaces get only two tonal scales, stone and blood: structure and identity. Syntax highlighting stays with the materials.