---
version: alpha
name: Haptic
description: Local-first markdown notes distilled to calm — a near-black slate canvas, Inter at restrained weights, a single quiet blue accent, hairline borders, and gentle 8px radii. Writing-room minimalism where chrome recedes and the prose is the interface.
colors:
  # Canvas + ink
  background: "#0e0f11"
  surface: "#16181c"
  surface-soft: "#1c1f24"
  surface-hover: "#22262c"
  ink: "#e8eaed"
  ink-secondary: "#a0a6ae"
  ink-muted: "#6b7280"

  # Accent — single quiet blue
  primary: "#3b82f6"
  primary-hover: "#2f73e6"
  accent-soft: "#1d2b3f"        # tinted blue surface over canvas

  # Borders / hairlines
  border: "#26292e"
  border-strong: "#34383f"

  # Functional
  success: "#34d399"
  danger: "#f87171"
  warning: "#fbbf24"

  # Selection / focus
  selection: "#1d2b3f"
  focus-ring: "#3b82f6"

  # On-color
  on-primary: "#ffffff"
  on-ink: "#0e0f11"

typography:
  display-hero:
    fontFamily: "Inter, -apple-system, BlinkMacSystemFont, sans-serif"
    fontSize: 44px
    fontWeight: 600
    lineHeight: 1.10
    letterSpacing: -1.1px
  section-heading:
    fontFamily: "Inter, -apple-system, sans-serif"
    fontSize: 32px
    fontWeight: 600
    lineHeight: 1.20
    letterSpacing: -0.8px
  sub-heading:
    fontFamily: "Inter, -apple-system, sans-serif"
    fontSize: 22px
    fontWeight: 600
    lineHeight: 1.30
    letterSpacing: -0.4px
  card-title:
    fontFamily: "Inter, -apple-system, sans-serif"
    fontSize: 18px
    fontWeight: 600
    lineHeight: 1.35
    letterSpacing: -0.2px
  body-large:
    fontFamily: "Inter, -apple-system, sans-serif"
    fontSize: 17px
    fontWeight: 400
    lineHeight: 1.65
    letterSpacing: 0px
  body:
    fontFamily: "Inter, -apple-system, sans-serif"
    fontSize: 15px
    fontWeight: 400
    lineHeight: 1.60
    letterSpacing: 0px
  body-medium:
    fontFamily: "Inter, -apple-system, sans-serif"
    fontSize: 14px
    fontWeight: 500
    lineHeight: 1.50
    letterSpacing: 0px
  button-ui:
    fontFamily: "Inter, -apple-system, sans-serif"
    fontSize: 14px
    fontWeight: 500
    lineHeight: 1.43
    letterSpacing: 0px
  caption:
    fontFamily: "Inter, -apple-system, sans-serif"
    fontSize: 12px
    fontWeight: 500
    lineHeight: 1.33
    letterSpacing: 0.1px
  mono-body:
    fontFamily: "JetBrains Mono, ui-monospace, SFMono-Regular, Menlo, monospace"
    fontSize: 13.5px
    fontWeight: 400
    lineHeight: 1.55
    letterSpacing: 0px
  mono-caption:
    fontFamily: "JetBrains Mono, ui-monospace, Menlo, monospace"
    fontSize: 12px
    fontWeight: 500
    lineHeight: 1.40
    letterSpacing: 0px

spacing:
  micro: 2px
  xs: 4px
  sm: 8px
  md: 12px
  lg: 16px
  xl: 24px
  2xl: 40px
  3xl: 64px
  4xl: 96px

rounded:
  none: 0px
  xs: 4px
  sm: 6px
  md: 8px
  lg: 12px
  xl: 16px
  pill: 9999px

components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.on-primary}"
    typography: "{typography.button-ui}"
    rounded: "{rounded.md}"
    padding: 8px 16px
  button-primary-hover:
    backgroundColor: "{colors.primary-hover}"
    textColor: "{colors.on-primary}"
    typography: "{typography.button-ui}"
    rounded: "{rounded.md}"
    padding: 8px 16px

  button-secondary:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.ink}"
    typography: "{typography.button-ui}"
    rounded: "{rounded.md}"
    padding: 8px 16px
    borderColor: "{colors.border}"
  button-secondary-hover:
    backgroundColor: "{colors.surface-hover}"
    textColor: "{colors.ink}"
    typography: "{typography.button-ui}"
    rounded: "{rounded.md}"
    padding: 8px 16px
    borderColor: "{colors.border-strong}"

  button-ghost:
    backgroundColor: "{colors.background}"
    textColor: "{colors.ink-secondary}"
    typography: "{typography.button-ui}"
    rounded: "{rounded.sm}"
    padding: 6px 10px

  card:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.ink}"
    rounded: "{rounded.lg}"
    padding: 20px
    borderColor: "{colors.border}"

  sidebar-item:
    backgroundColor: "{colors.background}"
    textColor: "{colors.ink-secondary}"
    typography: "{typography.body-medium}"
    rounded: "{rounded.sm}"
    padding: 6px 10px
  sidebar-item-active:
    backgroundColor: "{colors.surface-soft}"
    textColor: "{colors.ink}"
    typography: "{typography.body-medium}"
    rounded: "{rounded.sm}"
    padding: 6px 10px

  input:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.ink}"
    typography: "{typography.body}"
    rounded: "{rounded.md}"
    padding: 8px 12px
    borderColor: "{colors.border}"
  input-focus:
    backgroundColor: "{colors.surface}"
    textColor: "{colors.ink}"
    rounded: "{rounded.md}"
    padding: 8px 12px
    borderColor: "{colors.focus-ring}"

  badge:
    backgroundColor: "{colors.accent-soft}"
    textColor: "{colors.primary}"
    typography: "{typography.caption}"
    rounded: "{rounded.sm}"
    padding: 2px 8px

  code-block:
    backgroundColor: "{colors.surface-soft}"
    textColor: "{colors.ink}"
    typography: "{typography.mono-body}"
    rounded: "{rounded.md}"
    padding: 12px 14px
    borderColor: "{colors.border}"

  nav-bar:
    backgroundColor: "{colors.background}"
    textColor: "{colors.ink}"
    typography: "{typography.button-ui}"
    padding: 10px 16px
    borderColor: "{colors.border}"
---

# Haptic Design System

## Overview

Haptic is a local-first markdown notes app, and its design is the visual argument for getting out of the writer's way. The interface sits on a near-black slate canvas (`{colors.background}`) — not pure black, but a soft graphite that's gentle for long writing sessions — with surfaces stepping up in barely-perceptible increments (`{colors.surface}`, `{colors.surface-soft}`). There are no heavy panels, no gradients, no decoration competing with the prose. The whole system is a quiet room: dark, even, and calm.

Typography carries the identity. Inter runs the entire UI at restrained weights — 400 for reading, 500 for interface labels, 600 for the few headings that exist. Negative tracking tightens the larger sizes just enough to feel deliberate without shouting. Body copy reads at a generous 1.6 line-height because this is fundamentally a reading-and-writing surface, and the editor type is meant to be lived in. A monospace companion (JetBrains Mono) handles code blocks and any technical metadata, the only place where a second typeface appears.

Color is rationed to a single quiet blue (`{colors.primary}`). It marks the active note, the primary action, the focus ring, and links — and almost nothing else. Everything else is grayscale: an ink scale from bright (`{colors.ink}`) through secondary (`{colors.ink-secondary}`) to muted (`{colors.ink-muted}`), separated by hairline borders (`{colors.border}`) rather than fills. The result is an interface where the blue accent always means "this is what matters right now," and the eye trusts it.

Structure is hairline-driven. Cards, inputs, the sidebar, and the nav are defined by 1px borders one shade above the surface they sit on, paired with soft 8–12px radii. Nothing floats on a drop shadow; depth comes from the border-and-surface step, the same restraint a good text editor brings to its own chrome.

**Key Characteristics:**
- Near-black graphite canvas (`{colors.background}`) tuned for long, comfortable writing sessions
- Inter across the entire UI at three weights — 400 read, 500 interact, 600 announce
- A single quiet blue accent (`{colors.primary}`) reserved for active state, primary action, focus, and links
- Hairline borders (`{colors.border}`) instead of fills or shadows to define structure
- Soft 8–12px radii — friendly but not rounded-bubbly
- Grayscale ink scale carries nearly all hierarchy; color is functional, never decorative
- JetBrains Mono as the sole secondary face, for code and technical metadata
- Reading-first body type at 1.6 line-height

## Colors

### Canvas & Surface
- **Canvas** (`{colors.background}`): The graphite page background behind everything.
- **Surface** (`{colors.surface}`): Cards, inputs, raised panels — one step above canvas.
- **Surface Soft** (`{colors.surface-soft}`): Code blocks, active sidebar rows, nested fills.
- **Surface Hover** (`{colors.surface-hover}`): Hover state for surface elements.

### Ink
- **Ink** (`{colors.ink}`): Primary text, headings, active labels.
- **Ink Secondary** (`{colors.ink-secondary}`): Body secondary text, inactive sidebar items.
- **Ink Muted** (`{colors.ink-muted}`): Placeholders, timestamps, disabled text.

### Accent
- **Primary Blue** (`{colors.primary}`): Active note, primary CTA, links, focus ring.
- **Primary Hover** (`{colors.primary-hover}`): Hover state for primary actions.
- **Accent Soft** (`{colors.accent-soft}`): Tinted blue surface for badges and selection.

### Borders
- **Border** (`{colors.border}`): The hairline that defines cards, inputs, sidebar, nav.
- **Border Strong** (`{colors.border-strong}`): Slightly raised border on hover/emphasis.

### Functional
- **Success** (`{colors.success}`): Saved/synced confirmations.
- **Danger** (`{colors.danger}`): Destructive actions, delete.
- **Warning** (`{colors.warning}`): Caution states.

## Typography

### Font Family
- **Primary**: `Inter`, with fallbacks `-apple-system, BlinkMacSystemFont, sans-serif`
- **Monospace**: `JetBrains Mono`, with fallbacks `ui-monospace, SFMono-Regular, Menlo, monospace`

### Hierarchy

The complete type scale lives in the `typography:` token block above. Reference tokens directly (`{typography.display-hero}`, `{typography.body}`, etc.).

| Token | Use |
|---|---|
| `display-hero` | Marketing hero / large title |
| `section-heading` | Section titles |
| `sub-heading` | Sub-sections, note titles |
| `card-title` | Card and panel headings |
| `body-large` | Editor reading text |
| `body` | Standard UI reading text |
| `body-medium` | Sidebar items, emphasized labels |
| `button-ui` | Buttons, links |
| `caption` | Timestamps, metadata, badges |
| `mono-body` | Code blocks |
| `mono-caption` | Code labels, technical metadata |

### Principles
- **Inter only, three weights**: 400 reads, 500 interacts, 600 announces. No 700 in UI chrome.
- **Negative tracking on large sizes**: -1.1px at 44px relaxing to neutral by body — quiet precision, not drama.
- **Reading-first body**: 1.6 line-height because the app is a writing surface above all.
- **Mono is scoped**: JetBrains Mono appears only for code and technical metadata.

## Layout

### Spacing System
The complete scale lives in the `spacing:` token block above. Base unit is 8px (`{spacing.sm}`), with a 4px half-step (`{spacing.xs}`) for tight UI.

### Grid & Container
- App shell: fixed left sidebar (note list) + flexible editor pane
- Editor content capped to a comfortable reading measure, centered in its pane
- Marketing: single-column hero, generous vertical rhythm (`{spacing.3xl}`–`{spacing.4xl}`)

### Whitespace Philosophy
- **Calm density**: tight, consistent padding in chrome; generous breathing room in the editor
- **Borders, not shadows**: separation comes from `{colors.border}` hairlines and the surface step
- **Restful canvas**: the dark graphite background lets type and the single blue accent carry all the energy

## Elevation & Depth

| Level | Treatment | Use |
|---|---|---|
| Flat (0) | Canvas, no border | Page background, editor body |
| Hairline (1) | `1px solid {colors.border}` | Cards, inputs, sidebar, nav |
| Raised (2) | Surface step + `1px solid {colors.border-strong}` | Hovered / emphasized panels |
| Focus | `2px solid {colors.focus-ring}` | Keyboard focus on interactive elements |

**Depth Philosophy**: Haptic almost never uses drop shadows. Depth is communicated by stepping the surface one shade lighter and drawing a hairline border. This keeps the interface flat, quiet, and screen-friendly in dark mode, where heavy shadows read as muddy.

## Shapes

| Token | Value | Use |
|---|---|---|
| `none` | 0px | Reserved / full-bleed |
| `xs` | 4px | Tiny chips, inline code |
| `sm` | 6px | Sidebar items, ghost buttons, badges |
| `md` | 8px | Buttons, inputs, code blocks |
| `lg` | 12px | Cards, panels |
| `xl` | 16px | Large containers, modals |
| `pill` | 9999px | Avatars, toggles |

## Components

The full component spec lives in the `components:` token block above. Reference tokens directly (`{components.button-primary}`, `{components.card}`).

### Buttons
- **`button-primary`** — Quiet blue fill, white text, 8px radius. The single primary action.
- **`button-secondary`** — Surface fill with hairline border. Neutral actions.
- **`button-ghost`** — Transparent on canvas, secondary ink. Toolbar / icon actions.

### Sidebar
- **`sidebar-item`** — Secondary-ink label on canvas; **`sidebar-item-active`** lifts to surface-soft with bright ink. The active note is the one place the layout asserts state.

### Inputs
- **`input`** — Surface fill, hairline border, body type. Focus swaps border to `{colors.focus-ring}`.

### Cards & Code
- **`card`** — Surface fill, hairline border, 12px radius, 20px padding.
- **`code-block`** — Surface-soft fill, JetBrains Mono, 8px radius.

### Badges
- **`badge`** — Tinted blue surface (`{colors.accent-soft}`), blue text, small radius.

### Navigation
- **`nav-bar`** — Canvas background, hairline bottom border, Inter 14px weight 500.

## Do's and Don'ts

### Do
- Keep the canvas a soft graphite (`{colors.background}`), never pure black
- Use Inter at 400/500/600 only — three weights, strict roles
- Reserve `{colors.primary}` for active state, primary action, focus, and links
- Define structure with hairline borders (`{colors.border}`), not shadows
- Use the surface step to imply depth in dark mode
- Keep body type at 1.6 line-height — this is a reading surface

### Don't
- Don't introduce a second accent color — the system is mono-accent
- Don't use drop shadows for elevation
- Don't use pure black (`#000`) as the canvas — it's too harsh for long sessions
- Don't use weight 700 in UI chrome
- Don't apply blue decoratively — it always signals state or action
- Don't crowd the editor; chrome is dense, the writing area is generous

---

## Responsive Behavior

### Breakpoints
| Name | Width | Key Changes |
|------|-------|-------------|
| Mobile | <640px | Sidebar collapses to a drawer; editor full-width |
| Tablet | 640–1024px | Sidebar overlays or narrows; single editor pane |
| Desktop | >1024px | Persistent sidebar + editor split |

### Collapsing Strategy
- Sidebar (note list): persistent → slide-over drawer on mobile
- Editor: capped reading measure on desktop → full bleed on mobile
- Toolbar: full controls → condensed overflow menu
- Marketing hero: 44px → scales down, tracking held proportionally

### Touch Targets
- Sidebar rows and buttons keep ≥36px tappable height on mobile
- Ghost/icon buttons gain padding on touch viewports

---

## Attribution

Independent design analysis from [Design Swatches](https://designmd.santiagoalonso.com) by [Santiago Alonso](https://santiagoalonso.com). Based on publicly observable interface patterns. Not affiliated with or endorsed by Haptic. Brand names and trademarks belong to their respective owners.
