Nirvana
The DreamLand Design System
One vocabulary, two surfaces: the marketing site (dreamland.rocks) and the
/play web client. Aged gold and arcane purple on obsidian; parchment for reading,
dark wells for the game. This page is the source of truth — live surfaces migrate onto it.
Overview
The client was built on the site's vocabulary, so the foundation is already one system — same tokens, same fonts, same gem idea. Where they drifted, the calls below pick a single canon.
Three constraints that override everything
1. The terminal, the map, and any panel that renders ANSI game colour stay on a dark surface — the ANSI palette and screen-reader contrast are tuned for dark ground. 2. Parchment is for reading only (articles, news, hints, modals), never for game colour. 3. Colour is never the only signal of state — about 30% of players use a screen reader or low vision.
Color
The tokens below are shared. The ground, arcane, bright-gold and parchment sets are
byte-identical across site and client. The matte-metal surface trio (--gold-metal-*) is the
client's; the gems, the ink-purple cross-ref and the article face are the site's. The one thing to
remember: gold splits in two — bright for text and for a selected/lit
state, matte metal for resting control surfaces.
Ground — obsidian & stone
Arcane — the accent
Gold — text (bright) vs surface (matte metal)
The rule: panel titles, gilded words and links use --gold-bright/--gold.
Resting button and control faces use --gold-metal-*. The bright gold also marks a
selected/lit state (chosen tab, on-chip). Darken the resting surface, never the text or the lit state.
Gems — faceted-stone accents
Parchment & ink — reading surfaces
Text on dark
Typography
Three faces. The resolved call: one monospace, Fira Code — it carries UI labels, code spans and game text (terminal + article bodies). JetBrains Mono is retired.
The ligature rule
Fira Code ships with programming ligatures. In reading (article bodies) they stay
ON. In the terminal / map / any aligned output they go
OFF (font-variant-ligatures: none) — ligatures glue ->,
!=, | together and wreck ASCII maps, tables, and prompts.
Texture & shape
The one gem recipe
Every gold control points at these three tokens, so the matte finish can never drift back to glossy.
Buttons
Faceted gem, matte antique gold. Hover swaps to arcane and the label flips light. Three roles, three scales.
Naming — one role, two class sets
The site uses BEM; the client is locked to Bootstrap names (the JSX emits them). The DS names the role; both class sets are aliases for the same look.
| Role | Site (BEM) | Client (Bootstrap) |
|---|---|---|
| Primary — gold gem | .btn--gold | .btn |
| Accent — arcane | .btn--arcane | .btn-primary |
| Ghost — outline | .btn--ghost | .btn-secondary / .btn-outline-primary |
Focus
One focus language across site and client: the arcane orbit — purple light that circles a focused field. Click in.
Reduced-motion falls back to a steady purple glow. In combat the input border owns red and the orbit stands down.
Form controls
Dark well framed in gold-deep, light text (a typed command echoes the same colour it will print). Switch, dropdown, segmented control and range come from the client settings.
off = muted dark gold, on = arcane. The knob wears a grip.
Tabs
Branded jewel pills where players look; the compact/dev tab is just the segmented control.
Hover an inactive pill = ghost; the active pill = primary gold gem, and it pops in on select (a quick over-scale) rather than sliding. Toggle-chips pop the same way.
Cards & panels
Three carved-panel weights, lightest to heaviest: the everyday app/reading card (windowlet), the opt-in modular railed frame, and the login-grade big inset panel. Reach down the list only when the thing deserves it — most content is a windowlet.
Masked gradient stroke, chevron ornament along the top, arcane wash. Dense, for who/group/affect panels, list rows, and general content blocks.
Dark panel wearing the modular ornate frame (diamond caps, double strokes, keystones). For a headline card or feature block below the top tier.
Ornate octagon rail over an obsidian body, the modular ornate frame set a step inside, and a living arcane portal breathing behind it. The top tier — hero, login, the one crowned moment. Heavier than the railed card, so it stays rare.
Hover is opt-in: add .ds-card--hover only on cards that are
actually clickable (list rows, feature tiles). Static content cards leave it off — no pointer, no lift.
Retired: the corner-bracket card and the faceted gem-card. (Gem-cards are still live on the site home page —
they deprecate in the live-CSS migration, not here.)
Map / segmented controls
Zoom and layer toggles wear the same matte gem as every other button; the active layer presses in and goes arcane.
Which selected-colour? Choosing one option among peers (segmented, tabs, chips) lights it in gold. A power/on state (switch on, active map layer, focus, the accent button) reads arcane.
Chips
Not one component with two skins — two different jobs.
Data-chip colour = --chip-accent (buff green, debuff red, magic amethyst, mind sapphire, stat gold). The affects widget sets it per affect.
Parchment — reading surfaces
Aged sheet with a torn, worn edge, the modular frame
sitting a step inside the rag (same corners/sides/keystones as the railed card, recoloured to
--parch-edge). Help articles, news, hints, side-sheet modals. Game colour gets a light-tuned
ANSI remap — never the dark palette on parchment.
On Ereshkigal, the Silent
Cross-refs on parchment use --arcane-ink (the bright accent washes out on light). One frame system, two surfaces: gold on dark, parch-edge on cream.
Dark — game surfaces
The terminal well, the map, the ANSI panels. Dark, gold-framed, Fira with ligatures off. This never becomes parchment.
Terminal well (80-col game text)ANSI palette (dark ground)
Vital bars — hp / mana / move
The gem marks the resource (same faceted jewel the pill tabs wear). Colour is never the only signal — value text + the affects panel carry state for screen readers.
Ornaments
The decorative library. Skeuomorphic ornament rides the chrome; reading text stays clean. Everything here is modular — corners and sides that reuse and expand at one weight, no scaling.
Filigree dividerModular frame — corners + sides
One corner mask (--frame-corner), flipped for the other three, plus
consistent-weight side rules. Same weight at any size — no stretch. A side can also carry a chevron run.
Chevron ornament kit
The modular shape set (Figma 1124:7090): nested double-stroke units ridden as a
currentColor mask. Middle is the repeating tooth; the -line
pieces transition a tooth into a plain rule; the tl/bl/rt/rb caps close the ends. All nine
modules, left to right:
Two compositions ship ready — a band and a divider. Both feed the chrome: the band is the windowlet top and the frame's chevron side; the divider brackets a section rule.
The rules
The short version. Break these and the thing stops being one system.
| Dark vs parchment | Game colour (ANSI, terminal, map, vitals) on dark. Parchment for reading only. |
| Gold surface vs gold text | Matte --gold-metal-* for resting control faces; bright --gold-bright/--gold for text and the selected/lit state. Darken the resting surface, never the text. |
| Gold vs arcane selection | Choosing one option among peers (segmented, tabs, chips) = gold. A power/on state (switch on, active map layer, focus, accent button) = arcane. |
| One gem recipe | All resting gold controls point at --gem-face / --gem-shadow. The arcane accent is the one lit exception, with its own recipe. |
| One monospace | Fira Code for UI labels, code and game text. Ligatures ON in article bodies, OFF in the terminal / map / any aligned output. |
| Focus | Arcane orbit on every focusable field, both surfaces. Reduced-motion → steady glow. |
| Ornament is modular | Corners and sides reuse at one weight; recolour with currentColor. No stretching an ornament to fit. |
| Accessibility | Colour is never the only signal. Native <select> on narrow screens. ~30% of players read by screen reader. |
Source of truth. Live theme.css (site) and
theme-parchment.css (client) migrate onto these decisions in a later, separately-reviewed pass.