<!--
ROLE: You are a senior product designer + frontend engineer pair.
TASK: Treat the DESIGN.md below as the SINGLE SOURCE OF TRUTH for visual style.
Every component you produce in this codebase must:
  • Reuse the color tokens declared in YAML frontmatter (no ad-hoc hex values)
  • Use the typography scale (display / h1 / h2 / body / label / mono) verbatim
  • Match the radius scale (button / card / pill) to the named tier
  • Honor the elevation table for shadows
  • Respect the motion section (durations, easings, reduced-motion)
  • Pass the contrast pairs in the accessibility section
INPUT: Project files at ${CWD}.
OUTPUT: Code, not paragraphs. Quote the relevant section number when you cite a token (e.g. "per §3 Typography Rules").
PRINCIPLE: A token used once is a one-off; a token used three times is a system. Prefer system fidelity over local cleverness.
-->

---
name: Obsidian
tagline: Near-black canvas, near-white text, a single electric-purple CTA and a crystal mark — a local-first knowledge base that looks like the editor it ships.
updated_at: 2026-05-28T23:12:43.991Z
published_at: 2026-05-28T23:12:43.991Z
author: webdesignhot
source_url: https://obsidian.md
spec: webdesignhot/0.1
quality: curated
featured: false
categories: [saas]
tags: [dark, structured, sans, notes, purple, local-first, developer]
preview_swatch: ['#0f0f0f', '#7c3aed', '#a78bfa']
related: [notion, bear-app, linear]
description: 'Obsidian''s site is the editor it sells, rendered as a marketing page — a near-black `#0f0f0f` canvas, near-white `#eeeeee` body text, and a single electric-purple `#7c3aed` CTA ("Get Obsidian for macOS", `8px` radius, white text) that carries the entire chromatic load. The hero "Sharpen your thinking" sets at 60px / 600 in the platform''s own UI sans (`ui-sans-serif` — no webfont loaded, a deliberate local-first / privacy gesture). The crystal-facet logo is the only ornament. Everything else is dark surface, hairline borders, and disciplined restraint: the page reads as a developer tool that respects your attention, not a SaaS funnel that mines it. Obsidian is the rare site where "your notes are yours" is a design philosophy you can see — no gradients to load, no tracking pixels to dodge, no system font to download.'


# Canonical 8-role aliases (bg / text / brand / border / accent / muted / surface / danger).
# Maps role names to this entry's actual token names so role-aware
# downstream tools resolve `theme.background` → entry's `bg`, etc.
# Auto-generated by scripts/add-aliases.mjs — do not edit manually;
# regenerate after changing color token names.
aliases:
  background: bg
  foreground: text
  accent: brand
  muted: text-muted
  border: border
  ring: brand

colors:
  bg: '#0f0f0f'                  # near-black page canvas — the editor metaphor
  bg-deep: '#0a0a0a'            # deepest well — behind elevated panels, footer
  surface: '#161616'            # raised card / panel surface, one step off canvas
  surface-elev: '#1f1f1f'       # nested card / hovered surface
  surface-hover: '#262626'      # interactive hover fill (ghost button, list row)
  text: '#eeeeee'               # primary body + display copy — near-white, never pure
  text-strong: '#ffffff'        # rare peak — single heaviest display moment
  text-secondary: '#b0b0b0'     # secondary running-text, deck copy
  text-muted: '#a3a3a3'         # captions, metadata, footer links
  text-faint: '#737373'         # disabled / placeholder / fine print
  brand: '#7c3aed'              # electric purple — the single CTA voltage
  brand-hover: '#6d28d9'        # pressed / hover state — one stop darker
  brand-active: '#5b21b6'       # active / depressed CTA
  brand-text: '#a78bfa'         # lightened purple for links/text on dark (AA-safe)
  brand-text-hover: '#c4b5fd'   # hover for purple text links
  brand-soft: '#2a1a4a'         # purple-tinted soft fill for badges/highlights
  on-brand: '#ffffff'           # white text on the purple CTA
  border: '#2a2a2a'             # default hairline divider on dark
  border-soft: '#1f1f1f'        # near-invisible structural divider
  border-strong: '#3a3a3a'      # focused input / emphasized edge
  border-brand: '#7c3aed'       # focus ring + active-input edge
  shadow-ambient: 'rgba(0,0,0,0.40)'   # subtle lift on dark
  shadow-card: 'rgba(0,0,0,0.50)'      # raised card / dropdown
  shadow-modal: 'rgba(0,0,0,0.70)'     # heavy lift for modals/popovers
  scrim: 'rgba(0,0,0,0.65)'            # modal backdrop over canvas
  success: '#4ade80'            # confirmation green
  success-soft: '#14321f'
  warning: '#fbbf24'            # advisory amber
  warning-soft: '#33270a'
  danger: '#f87171'             # form-error red on dark
  danger-soft: '#3a1717'
  info: '#a78bfa'               # informational accent — same family as brand-text

typography:
  display:
    family: 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif'
    weights: [500, 600, 700]
    opentype-features: ['kern', 'liga']
  body:
    family: 'ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif'
    weights: [400, 500, 600]
  mono:
    family: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", monospace'
    weights: [400, 500]
  scale:
    display-hero:    { size: 60, weight: 600, lineHeight: 1.05, tracking: '-0.02em',  family: display, opentype: ['kern'] }
    display-lg:      { size: 48, weight: 600, lineHeight: 1.08, tracking: '-0.018em', family: display }
    h1:              { size: 40, weight: 600, lineHeight: 1.10, tracking: '-0.015em', family: display }
    h2:              { size: 32, weight: 600, lineHeight: 1.20, tracking: '-0.012em', family: display }
    h3:              { size: 24, weight: 600, lineHeight: 1.25, tracking: '-0.005em', family: display }
    h4:              { size: 20, weight: 600, lineHeight: 1.30, tracking: '0',        family: body }
    title-lg:        { size: 18, weight: 600, lineHeight: 1.40, tracking: '0',        family: body }
    body-lg:         { size: 18, weight: 400, lineHeight: 1.60, tracking: '0',        family: body }
    body:            { size: 16, weight: 400, lineHeight: 1.55, tracking: '0',        family: body }
    body-sm:         { size: 14, weight: 400, lineHeight: 1.50, tracking: '0',        family: body }
    label:           { size: 13, weight: 500, lineHeight: 1.40, tracking: '0',        family: body }
    button:          { size: 15, weight: 500, lineHeight: 1.20, tracking: '0',        family: body }
    nav-link:        { size: 15, weight: 500, lineHeight: 1.40, tracking: '0',        family: body }
    caption:         { size: 12, weight: 500, lineHeight: 1.40, tracking: '0.02em',   family: body }
    overline:        { size: 11, weight: 600, lineHeight: 1.30, tracking: '0.08em',   family: body, transform: uppercase }
    code:            { size: 14, weight: 400, lineHeight: 1.55, tracking: '0',        family: mono }
    code-micro:      { size: 12, weight: 400, lineHeight: 1.50, tracking: '0',        family: mono }

radius:
  micro: 2
  sm: 4
  md: 8         # the CTA + buttons + inputs — the dominant rounding
  lg: 12        # cards / panels
  xl: 16        # large feature shells / screenshots
  pill: 9999

spacing:
  base: 4
  scale: [0, 4, 8, 12, 16, 24, 32, 48, 64, 96, 128]

layout:
  page-width: 1280
  prose-width: 720
  header-height: 64
  hero-height: 640

components:
  cta-primary:
    bg: '#7c3aed'
    color: '#ffffff'
    radius: 8
    padding: '10px 16px'
    height: 40
    font: button
    use: 'The signature CTA — "Get Obsidian for macOS". Electric purple, white text, 8px radius. The only saturated element on the page.'
  cta-primary-hover:
    bg: '#6d28d9'
    color: '#ffffff'
    radius: 8
    use: 'Hover — one stop darker purple. No transform, no glow.'
  button-ghost:
    bg: 'transparent'
    color: '#eeeeee'
    border: '1px solid #2a2a2a'
    radius: 8
    padding: '10px 16px'
    height: 40
    font: button
    use: 'Secondary action — outlined ghost on dark. Fill warms to #262626 on hover.'
  button-quiet:
    bg: 'transparent'
    color: '#b0b0b0'
    radius: 8
    padding: '8px 12px'
    use: 'Tertiary / nav-adjacent text button. Text brightens to #eeeeee on hover, no border.'
  cta-platform-split:
    bg: '#7c3aed'
    color: '#ffffff'
    radius: 8
    use: 'The download CTA with an OS-selector caret on the right edge (macOS / Windows / Linux / mobile). Caret region divides with a subtle on-brand hairline.'
  card:
    bg: '#161616'
    color: '#eeeeee'
    border: '1px solid #2a2a2a'
    radius: 12
    padding: '24px'
    use: 'Feature panel — raised one step off canvas via surface tone + hairline, not shadow.'
  card-elev:
    bg: '#1f1f1f'
    color: '#eeeeee'
    border: '1px solid #3a3a3a'
    radius: 12
    use: 'Nested / hovered card — a second tonal step up.'
  input:
    bg: '#0f0f0f'
    color: '#eeeeee'
    border: '1px solid #2a2a2a'
    radius: 8
    height: 40
    padding: '8px 12px'
    placeholder: '#737373'
    focus: 'border becomes #7c3aed (1px) + faint purple ring'
    use: 'Text input — inset darker than card, purple focus edge.'
  badge-soft:
    bg: '#2a1a4a'
    color: '#a78bfa'
    radius: 9999
    padding: '3px 10px'
    font: caption
    use: 'Inline tag / status chip — purple-tinted soft fill, lightened-purple text. Used sparingly ("New", "v1.x").'
  badge-neutral:
    bg: '#1f1f1f'
    color: '#a3a3a3'
    border: '1px solid #2a2a2a'
    radius: 9999
    padding: '3px 10px'
    font: caption
    use: 'Neutral metadata chip — platform / category tags.'
  nav-top:
    bg: '#0f0f0fcc'
    color: '#eeeeee'
    height: 64
    border: '0 0 1px 0 solid #2a2a2a'
    use: 'Sticky top nav — translucent near-black with backdrop blur, hairline bottom border. Crystal mark left, links centre, purple CTA right.'
  link-inline:
    color: '#a78bfa'
    use: 'Inline body link — lightened purple (AA-safe on dark). Underline appears on hover.'

motion:
  ease-standard: 'cubic-bezier(0.4, 0, 0.2, 1)'
  ease-out: 'cubic-bezier(0.0, 0, 0.2, 1)'
  ease-emphasized: 'cubic-bezier(0.2, 0, 0, 1)'
  duration-fast: 150
  duration-standard: 240
  duration-slow: 320
  button-hover: 'background 150ms standard — colour only, no transform'
  link-underline: 'underline fades in over 150ms on hover'
  scroll-reveal: 'sections fade + 8px rise over 320ms ease-out on viewport entry'
  graph-pulse: 'optional node-graph ornament gently animates connection lines — decorative only'
  reduced-motion: 'respects prefers-reduced-motion: reduce — scroll-reveal becomes static render, graph animation pauses, transforms suppressed'

breakpoints:
  mobile: 640
  tablet: 1024
  desktop: 1280
  wide: 1536

shadows:
  ambient: 'rgba(0,0,0,0.40) 0 1px 2px 0'
  card: 'rgba(0,0,0,0.50) 0 8px 24px -8px'
  modal: 'rgba(0,0,0,0.70) 0 24px 64px -16px'
  ring: '0 0 0 3px rgba(124,58,237,0.40)'

accessibility:
  contrast-text-on-bg: 16.5          # #eeeeee on #0f0f0f — AAA
  contrast-text-on-surface: 14.6     # #eeeeee on #161616 — AAA
  contrast-on-brand: 5.7             # #ffffff on #7c3aed — AA (CTA label)
  contrast-brand-on-bg: 3.4          # #7c3aed on #0f0f0f — AA large only (never body text)
  contrast-brand-text-on-bg: 7.0     # #a78bfa on #0f0f0f — AAA (the safe purple for links/text)
  contrast-secondary-on-bg: 8.8      # #b0b0b0 on #0f0f0f — AAA
  contrast-muted-on-bg: 7.6          # #a3a3a3 on #0f0f0f — AAA
  focus-ring: '3px rgba(124,58,237,0.40) ring + 1px solid #7c3aed border on focusable controls'
  reduced-motion-honored: true
  touch-target-min: 40

dark-mode: 'dark-only'   # The marketing site is dark-only — it mirrors Obsidian's default dark editor theme. The app itself ships full light/dark + community themes, but the public site renders near-black canvas exclusively as a brand-identity choice.
---

## 1. Visual Theme & Atmosphere

Obsidian's site is the editor it sells, rendered as a marketing page. The canvas is a near-black `#0f0f0f` — the exact mood of the app's default dark theme — and the body copy sits in a near-white `#eeeeee` that never tips to pure white. The hero, "Sharpen your thinking", sets at 60px in the platform's own UI sans (`ui-sans-serif`) at weight 600 — not 700, not bold-marketing impact, just confident. The single saturated element on the entire page is the electric-purple `#7c3aed` "Get Obsidian for macOS" button at 8px radius. Everything else is dark surface, hairline borders, and the crystal-facet logo. The page does not so much sell you a tool as *show* you the room the tool lives in.

The atmosphere is **developer-tool restraint**: a page built by people who treat your attention as something to be respected rather than harvested. There are no gradient washes to download, no hero video, no animated illustrations beyond an optional gently-pulsing node-graph ornament that nods at Obsidian's signature graph view. The whole composition reads as *quiet competence* — closer to a well-configured terminal or a Linear/Vercel dashboard than to a consumer-SaaS funnel. The single purple CTA does all the chromatic work; remove it and the page would be a pure greyscale study.

The most telling decision is the typography: **no webfont is loaded.** The page renders entirely in `ui-sans-serif` / `system-ui` — San Francisco on Mac, Segoe on Windows, Roboto on Android. This is not laziness; it is the brand's local-first ethos made visible. A product whose entire pitch is "your notes are plain files on your own disk, no cloud required" refuses to make your browser phone home for a font. The page loads instantly, works offline-ish, and tracks nothing — the medium *is* the message.

Colour is rationed with monastic discipline. The palette is a near-black canvas, a near-white ink, a stepped greyscale of surfaces (`#0f0f0f` → `#161616` → `#1f1f1f` → `#262626`), hairline borders in `#2a2a2a`, and exactly one accent: purple. Purple is the brand voltage and the CTA fill; on dark backgrounds where the saturated `#7c3aed` fails contrast as text, it is lightened to a violet `#a78bfa` for links. The page never introduces a second accent. There is no teal, no amber-for-warmth, no blue-for-trust — just purple-on-near-black, the way the crystal logo glints against the editor.

The result is a page that signals its values before you read a word: **dark because that is where focused work happens; system-font because your machine is yours; purple-and-crystal because that is the mark; nothing else, because everything else is noise.** Obsidian is the rare site where "your notes are yours" is a design philosophy you can actually see.

**Key Characteristics:**
- Near-black canvas (`#0f0f0f`) — the app's default dark editor theme, lifted to marketing
- Near-white ink (`#eeeeee`) — never pure white; calmer on dark, hits 16.5:1 AAA contrast
- A single accent — electric purple (`#7c3aed`) — carrying the entire chromatic load
- System UI sans (`ui-sans-serif`), no webfont — the local-first / privacy ethos made literal
- Hero at 60px / weight 600 — confident, not bold-marketing-loud
- Crystal-facet logo as the only ornament; optional pulsing node-graph nod to graph view
- Stepped greyscale surfaces (`#0f0f0f` → `#161616` → `#1f1f1f` → `#262626`) for elevation, not shadow stacks
- Hairline `#2a2a2a` borders define structure; depth comes from tone, not drop shadow
- 8px radius on the CTA / buttons / inputs — crisp, developer-tool corners (not pill, not sharp)
- Purple lightens to `#a78bfa` for text/links on dark (the saturated brand fails AA as small text)
- Page loads instantly and tracks nothing — performance and privacy are aesthetic choices

## 2. Color Palette & Roles

### Primary
- **Canvas** (`#0f0f0f`) [→ `bg`]: near-black page floor — the editor metaphor; the default of everything.
- **Deep Well** (`#0a0a0a`) [→ `bg-deep`]: the darkest tone — behind elevated panels and in the footer.
- **Ink** (`#eeeeee`) [→ `text`]: primary body and display copy — near-white, never pure `#ffffff`.
- **Ink Strong** (`#ffffff`) [→ `text-strong`]: rare; the single heaviest display moment per page.

### Brand
- **Brand Purple** (`#7c3aed`) [→ `brand`]: the one accent — CTA fill, focus edge, the crystal-logo voltage.
- **Brand Hover** (`#6d28d9`) [→ `brand-hover`]: CTA hover — one stop darker.
- **Brand Active** (`#5b21b6`) [→ `brand-active`]: pressed CTA — two stops darker.
- **Brand Soft** (`#2a1a4a`) [→ `brand-soft`]: purple-tinted soft fill for badges and inline highlights.

### Accent
There is no decorative accent beyond purple. The page is greyscale + a single purple voltage. Any "second accent" is a violation of the system.

### Interactive
- **Brand Text** (`#a78bfa`) [→ `brand-text`]: inline links and purple text *on dark* — lightened so it passes AAA where `#7c3aed` would fail. **Use this, not `brand`, for any purple text.**
- **Brand Text Hover** (`#c4b5fd`) [→ `brand-text-hover`]: link hover — lighter still; underline fades in.
- **On-Brand** (`#ffffff`) [→ `on-brand`]: white label on the purple CTA fill.
- **Focus Ring** (`rgba(124,58,237,0.40)`) [→ `border-brand`]: 3px purple ring + 1px purple border on focused controls.
- **Disabled** (`#737373` text on `#161616` fill): drained grey, no purple.

### Neutral Scale
- **Ink Strong** (`#ffffff`) — peak display, single moment per page
- **Ink** (`#eeeeee`) — body, primary display, the dominant text colour
- **Secondary** (`#b0b0b0`) — deck copy, secondary running-text (8.8:1 AAA)
- **Muted** (`#a3a3a3`) — captions, metadata, footer links (7.6:1 AAA)
- **Faint** (`#737373`) — disabled, placeholder, fine print

### Surface & Borders
- **Canvas** (`#0f0f0f`) — page floor
- **Surface** (`#161616`) — raised card / panel, one step off canvas
- **Surface Elev** (`#1f1f1f`) — nested / hovered card, second step
- **Surface Hover** (`#262626`) — interactive hover fill (ghost button, list row)
- **Border** (`#2a2a2a`) — default hairline divider
- **Border Soft** (`#1f1f1f`) — near-invisible structural divider
- **Border Strong** (`#3a3a3a`) — focused input / emphasized edge

### Shadow Colors
Obsidian uses **pure-black** shadows (`rgba(0,0,0,…)`) at higher opacities than a light site would — on a near-black canvas, shadow must be deeper than the surface to register at all. Most surfaces, however, use *no shadow*; elevation is communicated by stepping the surface tone up (`#0f0f0f` → `#161616` → `#1f1f1f`) and adding a `#2a2a2a` hairline. Shadow is reserved for genuinely floating chrome.

- `rgba(0,0,0,0.40) 0 1px 2px 0` — ambient lift (sticky nav at scroll)
- `rgba(0,0,0,0.50) 0 8px 24px -8px` — raised card / dropdown
- `rgba(0,0,0,0.70) 0 24px 64px -16px` — modal / popover

### Semantic
- **Success** (`#4ade80` on `#14321f`) — confirmation green, brightened for dark legibility.
- **Warning** (`#fbbf24` on `#33270a`) — advisory amber.
- **Danger** (`#f87171` on `#3a1717`) — form-error red, softened for dark (a saturated `#dc2626` would vibrate on black).
- **Info** (`#a78bfa` on `#2a1a4a`) — informational accent — *intentionally* the same violet as the link colour. Obsidian treats "information" and "brand" as one voice.

## 3. Typography Rules

### Font Family

**Display & Body (one family)**: `ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif`. There is **no webfont**. Display and body share the system UI sans — they differ only by weight and size, never family. On macOS this resolves to San Francisco, on Windows to Segoe UI, on Android to Roboto. The page deliberately uses whatever native sans the reader's OS provides.

**Mono**: `ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", monospace` — used for code samples, file paths (`~/vault/notes.md`), and any moment that demonstrates Obsidian's plain-text-files-on-disk pitch.

**OpenType features**: `kern` and `liga` on, inherited from the system face. No custom stylistic sets — the brand uses the OS font exactly as the OS ships it.

The single-family decision is the brand's typographic fingerprint, and it is doing ideological work. Most note-apps load a webfont to feel "designed" (Bear ships two in-house cuts; Notion loads its own sans). Obsidian's refusal to load *any* webfont is the most on-brand move on the page: a local-first product that won't make your browser fetch a remote asset to render a marketing headline. The type looks "designed" by being calm and well-spaced, not by being bespoke.

### Hierarchy

| Role | Font | Size | Weight | Line Height | Letter Spacing | OT Features | Notes |
|------|------|------|--------|-------------|----------------|-------------|-------|
| display-hero | system sans | 60 | 600 | 1.05 | -0.02em | kern | Hero "Sharpen your thinking" — peak moment (live-probed at 60/600) |
| display-lg | system sans | 48 | 600 | 1.08 | -0.018em | — | Large section opener |
| h1 | system sans | 40 | 600 | 1.10 | -0.015em | — | Page / section heading |
| h2 | system sans | 32 | 600 | 1.20 | -0.012em | — | Sub-section opener |
| h3 | system sans | 24 | 600 | 1.25 | -0.005em | — | Feature title |
| h4 | system sans | 20 | 600 | 1.30 | 0 | — | Card title |
| title-lg | system sans | 18 | 600 | 1.40 | 0 | — | Inline emphasis title |
| body-lg | system sans | 18 | 400 | 1.60 | 0 | — | Hero deck — slightly larger body |
| body | system sans | 16 | 400 | 1.55 | 0 | — | Default running-text (live-probed at 16/400) |
| body-sm | system sans | 14 | 400 | 1.50 | 0 | — | Card meta, secondary copy |
| label | system sans | 13 | 500 | 1.40 | 0 | — | Form label, small UI label |
| button | system sans | 15 | 500 | 1.20 | 0 | — | CTA / button label |
| nav-link | system sans | 15 | 500 | 1.40 | 0 | — | Top-nav item |
| caption | system sans | 12 | 500 | 1.40 | 0.02em | — | Timestamp, fine metadata |
| overline | system sans | 11 | 600 | 1.30 | 0.08em | uppercase | Section eyebrow |
| code | mono | 14 | 400 | 1.55 | 0 | — | Code / file-path sample |
| code-micro | mono | 12 | 400 | 1.50 | 0 | — | Inline `⌘P`-style shortcut bubble |

### Principles

- **One family, no webfont.** Display and body are the same system UI sans, differing only by weight/size. Loading a webfont would betray the local-first ethos — don't.
- **Display tops out at weight 600, not 700.** The hero is confident, not loud. Weight 600 at 60px reads as "engineered" rather than "marketed". Pushing to 700/800 tips the page toward generic startup-bold.
- **Near-white ink, never pure white.** Body copy is `#eeeeee` — on a near-black canvas, pure `#ffffff` vibrates and fatigues. The slightly-off white is calmer and still hits 16.5:1 AAA.
- **Negative tracking on display only.** Hero `-0.02em`, h1 `-0.015em`, tapering to `0` by h4. Body and below stay at `0`; only the tiny caption/overline get positive tracking.
- **16px body at 1.55 line-height.** Comfortable web body, generous leading — the editor's own reading rhythm.
- **Mono for anything plain-text.** File paths, code, shortcuts render in `ui-monospace` — the page makes the product's core promise (plain `.md` files on disk) typographic.
- **Inter is the closest substitute** if a build can't use the system sans. Inter at weight 400/600 approximates SF / Segoe cleanly. Never substitute a serif or a "designer" sans — the point is system-native neutrality.

## 4. Component Stylings

### Buttons

**`cta-primary`** — The signature CTA. Electric-purple `#7c3aed` fill, white text at 15px / 500, **8px radius**, 10×16px padding, 40px height. This is the only saturated element on the page — "Get Obsidian for macOS". Everything visual on the page funnels to this one button.

**`cta-primary-hover`** — Pointer hover. Fill darkens to `#6d28d9` over 150ms standard. **No transform, no scale, no glow** — colour only. Active state goes to `#5b21b6`.

**`cta-platform-split`** — The download CTA with an OS-selector caret (macOS / Windows / Linux / iOS / Android). The caret region is divided from the label by a subtle on-brand hairline; clicking the caret opens a small dropdown of platform options.

**`button-ghost`** — Secondary action. Transparent fill, `#eeeeee` text, 1px `#2a2a2a` border, 8px radius. On hover the fill warms to `#262626` (no border change). Used for "Read the docs", "Browse plugins".

**`button-quiet`** — Tertiary / nav-adjacent text button. No border, no fill; `#b0b0b0` text that brightens to `#eeeeee` on hover. Used for utility links ("Sign in", "Sync", "Pricing").

### Cards

**`card`** — Feature panel. `#161616` fill (one tonal step off canvas), `#eeeeee` text, 1px `#2a2a2a` hairline border, **12px radius**, 24px padding. **No shadow** — the surface step plus hairline is the elevation language. Inside: h4 title in `#eeeeee`, body in `#b0b0b0`.

**`card-elev`** — Nested or hovered card. `#1f1f1f` fill, `#3a3a3a` border — a second tonal step up. Used for cards-within-cards (a plugin card inside a feature panel) or as the hover state of `card`.

**`feature-screenshot`** — App screenshot of the editor itself (showing the dark theme with purple accents — the page literally pictures itself). 16px radius, optional `rgba(0,0,0,0.50) 0 8px 24px -8px` shadow to float it off the canvas.

### Badges, Tags, Pills

**`badge-soft`** — Purple-tinted chip. `#2a1a4a` fill, `#a78bfa` text, 9999px radius, 3×10px padding, 12px caption. Used sparingly for "New", version tags, "Free". The only place soft purple appears outside the CTA.

**`badge-neutral`** — Neutral metadata chip. `#1f1f1f` fill, `#a3a3a3` text, 1px `#2a2a2a` border, pill radius. Platform tags (macOS / Windows / Linux), category labels in the plugin directory.

### Inputs / Forms

**`input`** — Text input. `#0f0f0f` fill (inset *darker* than the surrounding card — the field reads as "below" the surface), `#eeeeee` text, 1px `#2a2a2a` border, 8px radius, 40px height, 8×12px padding. Placeholder in `#737373`. On focus, the border becomes `#7c3aed` (1px) with a faint `rgba(124,58,237,0.40)` 3px ring. Newsletter / search / vault-name fields.

**`select` / `dropdown`** — Same chassis as input; chevron in `#a3a3a3`. Open panel uses `card` surface (`#161616`) with `shadow-card`.

### Navigation

**`nav-top`** — Sticky top nav, 64px height. Translucent near-black (`#0f0f0fcc`) with a backdrop blur so content blurs behind it on scroll, and a 1px `#2a2a2a` bottom hairline. **Crystal-facet logo + "Obsidian" wordmark** flush left in `#eeeeee` — the logo is the only ornament in the chrome. Centre: nav links (Features, Pricing, Plugins, Docs) in 15px / 500 `#eeeeee`. Right: a `button-quiet` ("Sign in") + the purple `cta-primary` ("Download").

**`nav-link`** — `#eeeeee` at rest, no underline. Hover brings a subtle `#a78bfa` underline / colour lift. Active page link sits at full `#ffffff`.

**`footer`** — `#0a0a0a` deep-well background, column heads in 13px / 600 `#eeeeee`, links in 14px / 400 `#a3a3a3`. The crystal mark reappears, muted. Multi-column: Product / Community / Resources / Company.

### Decorative

**`graph-ornament`** — An optional node-graph SVG (nodes + connecting edges) that nods at Obsidian's signature graph view. Edges may gently pulse / draw on viewport entry. Rendered in muted purple (`#a78bfa` at low opacity) on the canvas. Purely decorative — `aria-hidden="true"`.

## 5. Layout Principles

### Spacing System

- Base unit: **4px**
- Scale: `0 · 4 · 8 · 12 · 16 · 24 · 32 · 48 · 64 · 96 · 128`
- Section padding (vertical): 96–128px between major bands — generous, lets the dark canvas breathe
- Card internal padding: 24px on feature cards; 16px on compact list rows
- Inter-card gutters: 24px in feature grids
- The dark canvas does a lot of the spacing work — empty near-black space reads as deliberate, not unfinished

### Grid & Container

- Max content width: **1280px** — standard modern marketing width, wider than Bear's magazine-tight 1080px
- Prose / reading column: 720px for long-form (docs, blog)
- Hero: single-column, centred — H1 + deck + the purple CTA + an editor screenshot beneath
- Feature grid: 3-up at desktop → 2-up at tablet → 1-up at mobile
- 24px gutters; the grid sits inside the 1280px container with generous side margins on wide screens

### Whitespace Philosophy

On a near-black canvas, **negative space is the primary compositional tool.** Where a light site fills space with subtle tints and borders, Obsidian leaves the canvas dark and empty — the void reads as focus, not absence. Surfaces (cards) appear only where there is content to hold; between them is pure `#0f0f0f`. This is the editor's own aesthetic: a dark workspace where the only bright things are the words you wrote and the one action you can take.

### Section Cadence

A typical Obsidian page runs:

1. **Hero** — 60px / 600 H1 ("Sharpen your thinking"), 18px deck in `#b0b0b0`, purple `cta-primary` with OS-selector, editor screenshot floating beneath (optional graph-ornament behind)
2. **Feature spread** — 3-up cards on the dark canvas (Local files, Links & graph, Plugins) — each a `#161616` panel with hairline border
3. **Graph showcase** — the signature node-graph view, large, with a short caption — the product's most recognizable surface
4. **Plugins / community** — grid of plugin cards, neutral badges, a "Browse 2,000+ plugins" ghost button
5. **Sync / Publish band** — the paid tiers, presented as calm feature cards, not aggressive pricing tables
6. **Closing CTA band** — a centred restatement of the purple CTA over empty canvas
7. **Footer** — deep-well `#0a0a0a`, muted multi-column links, crystal mark

The page does not alternate light/dark — it is dark throughout. The "alternation" is canvas (`#0f0f0f`) vs. card surface (`#161616`) tonal contrast.

## 6. Shapes & Radius Scale

| Tier | Value | Use |
|------|-------|-----|
| Micro | 2px | Inline code chips, tiny indicators |
| Small | 4px | Nested elements, fine controls |
| Standard | 8px | CTA, buttons, inputs — the dominant rounding |
| Comfortable | 12px | Cards, panels |
| Large | 16px | Feature shells, app screenshots |
| Pill | 9999px | Badges, neutral chips |

Obsidian's radius hierarchy is **developer-tool crisp** — the dominant 8px on buttons and inputs is the modern-app sweet spot: rounded enough to feel finished, sharp enough to feel engineered (not the soft 12–16px of consumer apps, not the pill-everything of marketing sites). Cards step to 12px; the largest shells and screenshots to 16px. Pill radius is reserved for badges only — the page never makes a pill button, because a pill CTA would read as "consumer", and Obsidian is positioning as a serious tool.

## 7. Depth & Elevation

| Level | Treatment | Use |
|-------|-----------|-----|
| 0 — Canvas | no shadow, `#0f0f0f` | The page floor, hero, empty space (~70% of surface) |
| 1 — Surface | tonal step to `#161616` + 1px `#2a2a2a` hairline, no shadow | Feature cards, panels |
| 2 — Elevated surface | tonal step to `#1f1f1f` + `#3a3a3a` border | Nested / hovered cards |
| 3 — Floating | `rgba(0,0,0,0.40) 0 1px 2px 0` | Sticky nav at scroll, subtle inputs |
| 4 — Raised | `rgba(0,0,0,0.50) 0 8px 24px -8px` | Dropdowns, popovers, screenshots |
| 5 — Modal | scrim `rgba(0,0,0,0.65)` + `rgba(0,0,0,0.70) 0 24px 64px -16px` | Sign-in / vault dialog |

### Shadow Philosophy

On a near-black canvas, **shadow is a weak signal** — a `rgba(0,0,0,…)` shadow against `#0f0f0f` is barely darker than the floor it sits on. So Obsidian inverts the usual elevation strategy: **depth is communicated by stepping the surface *lighter*, not by casting a shadow darker.** A raised card is `#161616` (lighter than canvas) with a hairline border; a more-raised card is `#1f1f1f`. Shadow is reserved for chrome that genuinely floats over content (dropdowns, modals, the sticky nav), and even then it is used at high opacity (0.50–0.70) purely so it registers at all. The hairline `#2a2a2a` border, not the shadow, is what draws the eye to a surface edge. This is the dark-mode elevation discipline that Linear, Vercel, and well-built developer dashboards all share.

## 8. Interaction & Motion

### Easing

- **Standard**: `cubic-bezier(0.4, 0, 0.2, 1)` — default for hover colour swaps, border transitions
- **Out**: `cubic-bezier(0.0, 0, 0.2, 1)` — scroll-reveal entrances
- **Emphasized**: `cubic-bezier(0.2, 0, 0, 1)` — modal entry, dropdown open

### Durations

| Bucket | Value | Use |
|--------|-------|-----|
| Fast | 150ms | Button hover, link underline, focus-ring fade |
| Standard | 240ms | Card hover, dropdown open, border transitions |
| Slow | 320ms | Scroll-reveal, modal entry, graph-line draw |

### Per-Component Recipes

- **CTA hover**: fill `#7c3aed` → `#6d28d9` over 150ms standard. **No transform, no scale.** Active → `#5b21b6`.
- **Ghost button hover**: transparent → `#262626` fill over 150ms; border unchanged.
- **Card hover**: surface lifts a tonal step (`#161616` → `#1f1f1f`) and border brightens (`#2a2a2a` → `#3a3a3a`) over 240ms. No translate.
- **Link hover**: colour `#a78bfa` → `#c4b5fd`; underline fades in over 150ms.
- **Focus**: 3px `rgba(124,58,237,0.40)` ring + 1px purple border appears over 150ms on keyboard focus.
- **Scroll-reveal**: sections fade in + rise 8px over 320ms ease-out on first viewport entry. One-shot.
- **Graph ornament**: connection edges gently draw / pulse — decorative, low-amplitude, never demands attention.

### Page Transitions

Navigation is a quiet 240ms cross-fade; the sticky nav stays fixed. Anchored links smooth-scroll over 320ms emphasized. Nothing is showy — motion exists to soften state changes, not to perform.

### Reduced Motion

Respects `prefers-reduced-motion: reduce`. Scroll-reveal becomes static render-on-mount (no fade, no rise). The graph-ornament animation pauses to a static frame. Hover transforms (none exist) and all translate/scale are suppressed. Colour-only transitions (button hover, link colour) may remain since they don't induce motion.

## 9. Accessibility & A11y

### Contrast Pairs

| Pair | Ratio | Level |
|------|-------|-------|
| #eeeeee ink on #0f0f0f canvas | 16.5 | AAA |
| #eeeeee ink on #161616 surface | 14.6 | AAA |
| #ffffff label on #7c3aed CTA | 5.7 | AA (passes for the 15px/500 button label) |
| #7c3aed brand on #0f0f0f | 3.4 | **AA large only — never use as body text** |
| #a78bfa brand-text on #0f0f0f | 7.0 | AAA — the safe purple for links / small text |
| #b0b0b0 secondary on #0f0f0f | 8.8 | AAA |
| #a3a3a3 muted on #0f0f0f | 7.6 | AAA |

The critical accessibility nuance: **the brand purple `#7c3aed` only reaches 3.4:1 on the canvas** — it passes for large UI and as a button fill (with white text), but it *fails* as small purple text on dark. The page therefore uses the lightened `#a78bfa` (7.0:1, AAA) for every inline link and purple text run. Treating `brand` and `brand-text` as two distinct tokens is not optional polish — it is what keeps the dark theme readable.

### Focus Indicators

Focus is a 3px `rgba(124,58,237,0.40)` ring plus a 1px solid `#7c3aed` border on the focused control. On the dark canvas the semi-transparent purple ring is clearly visible against `#0f0f0f` without being garish. Focus is never removed; keyboard and pointer users get the same target.

### ARIA Patterns

- **Top nav**: `<nav>` landmark with `aria-label="Primary"`. The crystal logo is an `<img alt="Obsidian">` linking home.
- **Platform-split CTA**: the OS-selector caret is a `<button aria-haspopup="menu" aria-expanded>`; the dropdown is `role="menu"` with `role="menuitem"` per platform.
- **Plugin grid**: each card is a link with an accessible name; neutral badges are decorative text, not separate controls.
- **Graph ornament**: `aria-hidden="true"` — purely visual.
- **Modal** (sign-in / vault): focus trap, Esc closes, click-outside closes, focus returns to trigger.

### Keyboard Navigation

- Top nav: Tab logo → Features → Pricing → Plugins → Docs → Sign in → Download
- Platform-split CTA: Tab to the button; Enter downloads default OS; the caret button opens the menu, arrow keys navigate platforms
- Cards: Tab moves card → card; Enter activates the link
- Modal: Tab cycles within the dialog only

### Screen Reader Hints

The crystal logo carries `alt="Obsidian"`. App screenshots carry descriptive alt text ("Obsidian editor in dark theme, a note open with a backlinks panel and the graph view in the sidebar"). The graph ornament is `aria-hidden`. The CTA's accessible name includes the platform ("Download Obsidian for macOS").

### Reduced Motion

All entrance animations degrade to static render. The graph ornament freezes. Colour-only hover transitions may remain. No essential information is conveyed by motion alone.

## 10. Responsive Behavior

### Breakpoints

| Name | Width | Key Changes |
|------|-------|-------------|
| Mobile | <640px | Nav collapses to logo + hamburger; hero h1 drops 60 → 36px; CTA goes full-width; feature cards 1-up; graph ornament hidden |
| Tablet | 640–1024px | Inline nav links may persist; hero h1 at ~44px; feature cards 2-up; screenshot at 90% width |
| Desktop | 1024–1280px | Full nav; hero h1 at 60px; feature cards 3-up; screenshot up to 1100px |
| Wide | >1280px | Content caps at 1280px; canvas absorbs the extra width as empty near-black margin |

### Touch Targets

- Purple CTA: 40px height; on mobile it goes full-width for an easy thumb target (44px+ effective row)
- Nav links: minimum 44×44px hit area in the mobile sheet
- Plugin / feature cards: the whole card is the tap target
- Inputs: 40px height, 44px+ effective with padding

### Collapsing Strategy

- Top nav links collapse into a hamburger sheet below 640px; the purple CTA stays visible in the collapsed bar
- Feature grids: 3 → 2 → 1 columns
- The graph-view showcase scales down; on mobile it may switch to a simpler static node image to keep payload light (the no-webfont/perf ethos carries into imagery)
- App screenshots scale by viewport, never crop; 16px radius scales proportionally

### Image Behavior

Editor screenshots render at 2x as PNG/WebP with 16px radius and optional `rgba(0,0,0,0.50)` shadow. They scale `width: 100%; height: auto`. Because the canvas is dark and the screenshots *are* of the dark editor, screenshots blend seamlessly into the page — there is no light-on-dark seam to manage.

### Container Queries

Used on the platform-split CTA: when the available width is too narrow for "Get Obsidian for macOS" + caret, the label shortens to "Download" and the OS name moves into the dropdown.

## 11. Content & Voice

### Tone

Plainspoken, technical, quietly confident. Obsidian's voice trusts the reader to be the kind of person who wants their notes as plain files — it doesn't over-explain, doesn't hype, doesn't use exclamation marks. Headlines are short imperatives or claims ("Sharpen your thinking", "Your thoughts are yours", "A second brain, for you, forever"). The copy assumes competence and rewards it.

### Microcopy Patterns

- **Button verbs**: "Get Obsidian", "Download", "Read the docs", "Browse plugins" — direct, outcome-named
- **Error message recipe**: `[What went wrong] + [What to try]` — e.g., "Couldn't open that vault. Check the folder still exists, then try again."
- **Success confirmations**: short, factual — "Synced." / "Vault created."
- **Field labels**: minimal — "Email", "Vault name" — no friendly framing

### Empty States

The empty-vault state in screenshots: "Create your first note." — single declarative line. The paid-feature gate (Sync / Publish): "Obsidian Sync keeps your vault in sync across devices. Try it free." — names the value, offers the path, no pressure.

### CTA Verb Conventions

- Primary action: **"Get Obsidian"** / **"Download"** (with OS selector)
- Secondary action: **"Read the docs"**, **"Browse plugins"**, **"Learn more"**
- Tertiary text: **"Sign in"**, **"See pricing"**, **"Join the community"**
- Avoided: "Get started free!", "Sign up now", "Click here", "Buy" — Obsidian uses calm outcome verbs, never funnel-urgency

## 12. Dark Mode & Theming

**Dark-only marketing surface.** The public site renders exclusively on the near-black `#0f0f0f` canvas — it mirrors Obsidian's default dark editor theme as a deliberate brand-identity choice. This is the inverse of most sites (which are light-only and ship a dark *app*): here the *site* is dark because the *brand* is dark, and the dark editor is the product's most recognizable face.

The app itself, by contrast, ships a full theming system — light and dark base themes plus a large community-theme ecosystem and per-vault CSS snippets (theming your own vault is a core feature). The marketing site does not expose a light toggle; it commits to dark to *show* the default experience.

If a light variant were ever shipped, the token swap would be: canvas `#ffffff`, surface `#f6f6f6`, ink `#1a1a1a`, border `#e5e5e5`, brand purple **unchanged** at `#7c3aed` (it passes AA as a CTA fill on white and is legible as text on light, so the `brand-text` lightening would no longer be needed). The greyscale stack would simply invert; the single purple accent would carry over intact.

## 13. Lineage & Influences

Obsidian's design sits at the intersection of three traditions. First, the **developer-tool dark aesthetic** — the near-black canvas, hairline-bordered surfaces, single-accent restraint, and system-font neutrality that Linear, Vercel, and well-built dashboards share. Second, the **local-first / plain-text software movement** — the lineage of iA Writer, Roam Research, TiddlyWiki, and the broader "your data in open formats on your own disk" ethos, where the refusal to load a webfont or a tracker is itself a design statement. Third, the **personal-knowledge-management (PKM) tradition** — the Zettelkasten method, wikis, and the graph-of-linked-notes idea that Obsidian's signature graph view makes visible.

The most distinctive — and most ideological — design decision is the absence of a webfont. Where Bear ships two in-house typefaces and Notion loads a custom sans, Obsidian renders entirely in the reader's own system UI font. For a product whose entire pitch is "your notes are plain Markdown files on your own machine, no cloud required, no lock-in", a marketing page that makes your browser phone home for a font would be a contradiction. The system-font choice, the instant load, and the zero tracking are the same value expressed three ways: *your machine, your data, your attention — ours to respect, not to harvest.*

What Obsidian rejects: gradient washes, hero video, animated illustrations, a second accent colour, pill CTAs, urgency microcopy, and webfonts. The page is dark, near-monochrome, system-set, and funnels to a single purple button — the visual equivalent of a clean plain-text file.

**Influences:**
- Linear — dark-canvas developer-tool aesthetic; hairline surfaces, single-accent restraint, [linear.app](https://linear.app)
- Vercel — near-black canvas, system-font neutrality, crisp 8px-radius developer chrome, [vercel.com](https://vercel.com)
- iA Writer — plain-text-as-craft, local files, typographic restraint as positioning, [ia.net/writer](https://ia.net/writer)
- Roam Research — networked-thought / linked-notes lineage and the graph-of-ideas paradigm, [roamresearch.com](https://roamresearch.com)
- TiddlyWiki — single-file, local-first, own-your-data personal-wiki heritage, [tiddlywiki.com](https://tiddlywiki.com)

## 14. Do's and Don'ts

**Do**
- Keep the canvas near-black at `#0f0f0f` — it is the editor metaphor and the brand floor
- Use `#eeeeee` for body text, never pure `#ffffff` — the off-white is calmer on dark and still AAA
- Let the single purple `#7c3aed` CTA carry the entire chromatic load — everything funnels to it
- Render in the system UI sans (`ui-sans-serif`) with no webfont — it is the local-first ethos made visible
- Set the hero at weight 600, not 700 — confident, not bold-marketing-loud
- Lighten purple to `#a78bfa` for any text/links on dark — the saturated brand fails AA as small text
- Step surfaces lighter (`#0f0f0f` → `#161616` → `#1f1f1f`) for elevation, not darker shadows
- Define structure with `#2a2a2a` hairline borders, not drop shadows
- Use 8px radius on buttons and inputs — developer-tool crisp
- Keep the crystal mark as the only ornament; if you add a graph-view nod, keep it muted and decorative
- Ration negative space generously — empty near-black canvas reads as focus, not absence

**Don't**
- Don't introduce a second accent colour — purple is the entire chromatic system
- Don't load a webfont — it contradicts the local-first / privacy ethos the brand sells
- Don't use the saturated `#7c3aed` as small purple text on dark — it fails AA; use `#a78bfa`
- Don't use pure white `#ffffff` for body copy — it vibrates against the near-black canvas
- Don't make the hero weight 700/800 — keep it 600, engineered not loud
- Don't pile up drop shadows for depth — on dark, lighter surface tone is the elevation signal
- Don't make a pill-shaped CTA — pill reads "consumer"; Obsidian is positioning as a serious tool
- Don't add gradient washes, hero video, or animated illustration beyond the muted graph nod
- Don't use urgency microcopy ("Sign up now!", "Limited time") — the voice is calm and trusting
- Don't add tracking pixels or analytics theatre — the page's restraint is the message
- Don't tint the canvas blue or warm — near-neutral near-black is the brand floor

## 15. Agent Prompt Guide

### Quick Color Reference

```
Canvas:       #0f0f0f   (near-black page floor)
Deep well:    #0a0a0a   (footer, behind elevated panels)
Surface:      #161616   (raised card, one step off canvas)
Surface-elev: #1f1f1f   (nested / hovered card)
Ink:          #eeeeee   (body + display, never pure white)
Secondary:    #b0b0b0   (deck copy, secondary text)
Muted:        #a3a3a3   (captions, footer links)
Brand:        #7c3aed   (the one accent — CTA fill only)
Brand-text:   #a78bfa   (purple text/links on dark — AA-safe)
Border:       #2a2a2a   (hairline divider)
On-brand:     #ffffff   (white label on the purple CTA)
```

### Example Component Prompts

- "Create an Obsidian-style hero: near-black canvas (#0f0f0f), a 60px / weight-600 headline 'Sharpen your thinking' in the system UI sans (ui-sans-serif, NO webfont) in #eeeeee with -0.02em tracking and 1.05 line-height. Below: an 18px / 400 deck in #b0b0b0 at 1.6 line-height. Below that: a single electric-purple (#7c3aed) CTA button 'Get Obsidian for macOS', white text at 15px/500, 8px radius, 10×16px padding, with a small OS-selector caret on the right edge. No second accent, no gradient, no webfont. Optionally a muted purple (#a78bfa low-opacity) node-graph SVG floating behind."
- "Design an Obsidian feature card: #161616 fill (one tonal step off the #0f0f0f canvas), 1px #2a2a2a hairline border, 12px radius, 24px padding, NO shadow. Inside: a 20px/600 title in #eeeeee, then 16px/400 body in #b0b0b0 at 1.55 line-height. On hover, lift the surface a tonal step to #1f1f1f and brighten the border to #3a3a3a over 240ms — no translate."
- "Build the Obsidian top nav: 64px tall, translucent near-black (#0f0f0fcc) with backdrop-blur and a 1px #2a2a2a bottom hairline. Left: a crystal-facet logo + 'Obsidian' wordmark in #eeeeee. Centre: nav links (Features, Pricing, Plugins, Docs) in 15px/500 #eeeeee with a subtle #a78bfa underline on hover. Right: a quiet text 'Sign in' link in #b0b0b0, then the purple (#7c3aed) 'Download' CTA at 8px radius."
- "Create an Obsidian text input: #0f0f0f fill (inset DARKER than the surrounding #161616 card), #eeeeee text, 1px #2a2a2a border, 8px radius, 40px height, placeholder in #737373. On focus, set the border to #7c3aed (1px) plus a 3px rgba(124,58,237,0.40) ring."
- "Design an Obsidian inline link + soft badge: links in lightened purple #a78bfa (NOT the saturated #7c3aed — it fails AA on dark) with an underline that fades in on hover toward #c4b5fd. A soft badge: #2a1a4a fill, #a78bfa text, pill radius (9999px), 3×10px padding, 12px caption — used sparingly for 'New' or a version tag."
- "Build an Obsidian closing CTA band: centred on the bare #0f0f0f canvas with generous vertical padding (96–128px), a 32px/600 #eeeeee restatement headline, and the single purple (#7c3aed) 'Get Obsidian' CTA at 8px radius. Nothing else — the empty near-black space is the design."

### Iteration Guide

1. **One accent, always.** Purple is the entire chromatic system. If you find yourself reaching for a second colour, you've left the brand — express the variation in greyscale tone instead.
2. **No webfont, ever.** Render in `ui-sans-serif` / `system-ui`. Loading a font betrays the local-first ethos and is the single fastest way to make the page "not Obsidian".
3. **Two purples, two jobs.** `#7c3aed` is for fills (the CTA); `#a78bfa` is for purple *text* on dark. Swapping them breaks contrast — the saturated purple as small text fails AA.
4. **Off-white, not white.** Body is `#eeeeee`. Pure `#ffffff` vibrates on the near-black canvas and reads as a beginner mistake.
5. **Elevation goes lighter, not darker.** Lift a surface by stepping its tone up (`#0f0f0f` → `#161616` → `#1f1f1f`) and adding a hairline — not by casting a shadow that barely registers on black.
6. **Hero weight 600, not 700.** Keep display confident and engineered. The moment it goes bold-marketing, it stops being Obsidian and starts being a generic startup.
7. **Let the dark breathe.** Negative near-black space is the primary compositional tool. Resist the urge to fill it with tints, gradients, or decoration — the void is the focus.
8. **Calm voice, no urgency.** Microcopy is plainspoken and trusting ("Get Obsidian", "Read the docs"). Never "Sign up now!", never exclamation marks, never a pill CTA.

---

*Theme-toggle audit: score=0, signals=[none]*
