# Design System

## Overview

See [https://duly.finance/brand](https://duly.finance/brand) for the live brand guidelines page with downloadable assets, color swatches, typography specimens and usage examples.

A calm, monochrome interface for payment infrastructure on Solana.
High contrast, restrained color, institutional confidence. The design fades into the background so content is what users notice. Quiet confidence over flashy effects.

## Logo

The duly mark is a bold geometric uppercase "D" with a sharp diagonal slash, set in monochrome (black on light, white on dark). The wordmark is always lowercase "duly" in Clash Grotesk Bold. All wordmark SVGs include a lavender dot (#C8B6F9) as a separate path element.

## Colors

- **Black** (#000000): Primary text (light mode), primary backgrounds (dark mode), button fills
- **White** (#FFFFFF): Primary backgrounds (light mode), primary text (dark mode), button fills
- **Lavender** (#C8B6F9): Single accent color. Used sparingly for heading dots, focus rings, interactive highlights and the lavender dot brand mark. Never used as a background fill on large surfaces.

### Neutral Scale

| Token | Hex |
|-------|-----|
| neutral-50 | #FAFAFA |
| neutral-100 | #F5F5F5 |
| neutral-200 | #E5E5E5 |
| neutral-300 | #D4D4D4 |
| neutral-400 | #A3A3A3 |
| neutral-500 | #737373 |
| neutral-600 | #525252 |
| neutral-700 | #404040 |
| neutral-800 | #262626 |
| neutral-900 | #141414 |
| neutral-950 | #0A0A0A |

### Lavender Scale

| Token | Hex |
|-------|-----|
| lavender-50 | #F5F0FF |
| lavender-100 | #EDE5FF |
| lavender-200 | #DDD0FF |
| lavender-300 | #C8B6F9 (core) |
| lavender-400 | #B09AE8 |
| lavender-500 | #9580D5 |
| lavender-600 | #7A66C0 |
| lavender-700 | #5F4DA8 |
| lavender-800 | #453690 |
| lavender-900 | #2E2178 |

### Surfaces

Light mode:
- **--bg-page** (#FFFFFF): Main background
- **--bg-canvas** (#FFFFFF): Card backgrounds
- **--bg-subtle** (#FAFAFA): Grouped content, pill backgrounds
- **--bg-muted** (#F5F5F5): Input backgrounds, code inline backgrounds
- **--accent** (#C8B6F9): Accent color
- **--accent-soft** (#F5F0FF): Light lavender background
- **--accent-strong** (#5F4DA8): Darker lavender for depth

Dark mode:
- **--bg-page** (#000000): Main background (pure black)
- **--bg-canvas** (#0A0A0A): Card backgrounds
- **--bg-subtle** (#111111): Grouped content
- **--bg-muted** (#141414): Input backgrounds
- **--accent** (#C8B6F9): Same lavender
- **--accent-soft** (#2E2178): Dark lavender background
- **--accent-strong** (#DDD0FF): Lighter lavender for contrast

### Text

Light mode:
- **--text-primary** (#000000): Headings, primary content
- **--text-secondary** (#525252): Body text, descriptions
- **--text-tertiary** (#A3A3A3): Overlines, muted labels, placeholders

Dark mode:
- **--text-primary** (#FFFFFF): Headings, primary content
- **--text-secondary** (#A3A3A3): Body text, descriptions
- **--text-tertiary** (#737373): Overlines, muted labels, placeholders

### Semantic

- **Success** (#00D07A): Positive states, approved indicators, "do" examples
- **Warning** (#F4B400): Caution states
- **Error** (#FF4D5A): Destructive actions, validation errors, "don't" examples
- **Info** (#60B7FF): Informational states

### Borders

- Light mode: **--border** (#E5E5E5), **--border-strong** (#000000)
- Dark mode: **--border** (#1E1E1E), **--border-strong** (#FFFFFF)

### Shadows

Light mode shadows use desaturated deep purple tint rgba(31, 19, 63), not pure black. This creates warmth without visible color.
Dark mode hover shadow uses a subtle lavender glow: rgba(200, 182, 249, 0.15).

- **--shadow-sm**: 0 1px 2px rgba(31, 19, 63, 0.04)
- **--shadow-md**: 0 4px 6px rgba(31, 19, 63, 0.06), 0 2px 4px rgba(31, 19, 63, 0.03)
- **--shadow-hover**: 0 4px 12px rgba(31, 19, 63, 0.07)
- **Dark --shadow-hover**: 0 4px 20px rgba(200, 182, 249, 0.15) (lavender glow)

## Typography

- **Display / Headings**: Clash Grotesk, weights 600-700. Angular terminals echo the D mark's diagonal slash. Used for page headings, section titles, the wordmark, navigation items, button labels and the lavender dot.
- **Body / UI**: Satoshi, weights 400-500. High x-height and open apertures for readability at any size. Used for paragraphs, descriptions, form inputs, labels, captions.
- **Data / Code**: JetBrains Mono, weights 400-500. Tabular figures for aligned columns. Used for financial amounts (USDC), wallet addresses, transaction hashes, code blocks, step indicators.

### Font Loading

```html
<!-- Fontshare CDN (Clash Grotesk + Satoshi) -->
<link href="https://api.fontshare.com/v2/css?f[]=clash-grotesk@200,300,400,500,600,700&f[]=satoshi@300,400,500,700,900&display=swap" rel="stylesheet">

<!-- Google Fonts (JetBrains Mono) -->
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
```

### CSS Variables

```css
:root {
  --font-display: 'Clash Grotesk', sans-serif;
  --font-body: 'Satoshi', -apple-system, system-ui, sans-serif;
  --font-mono: 'JetBrains Mono', monospace;
}
```

### Scale

| Role | Font | Weight | Size | Line Height | Tracking |
|------|------|--------|------|-------------|----------|
| Display | Clash Grotesk | 700 | 48px | 1.15 | -0.02em |
| H1 | Clash Grotesk | 700 | 36px | 1.2 | -0.015em |
| H2 | Clash Grotesk | 600 | 28px | 1.3 | -0.01em |
| H3 | Clash Grotesk | 600 | 24px | 1.4 | 0 |
| Body | Satoshi | 400 | 16px | 1.6 | 0 |
| Body Small | Satoshi | 400 | 14px | 1.5 | 0 |
| UI Label | Satoshi | 500 | 14px | 1.4 | 0 |
| Caption | Satoshi | 400 | 13px | 1.5 | 0 |
| Overline | Satoshi | 600 | 11px | 1.2 | 0.1em, uppercase |
| Data | JetBrains Mono | 500 | 16px | 1.5 | 0 |
| Code | JetBrains Mono | 400 | 13px | 1.7 | 0 |

### Wordmark Rules

- "duly" is always lowercase. Never "Duly", "DULY", or "DuLy".
- In running text: `font-display font-semibold tracking-[-0.02em]` when "duly" starts a sentence or paragraph. Mid-sentence mentions in body text stay plain. In legal pages, sentence-starting "duly" gets wordmark treatment; mid-sentence stays plain to avoid distraction.
- The lavender dot after "duly" uses `font-display text-lavender` with `-ml-[0.11em]` to track tight against the "y".
- The lavender dot is only tight-tracked after "duly" in the standalone wordmark. In "duly.finance", the dot stays at natural font spacing since it's functional punctuation separating the two words.
- All wordmark SVGs (duly and duly.finance) include the lavender dot (#C8B6F9) as a separate path element.

## Layout

### Container
- Max width: 1320px
- Centered: `mx-auto w-full max-w-[1320px]`
- Responsive padding via Container component: `px-4 md:px-8 xl:px-12`

### Page Spacing
- Outer padding: `py-10 md:py-16`
- Section gaps: `mt-12 md:mt-16`
- Hero to first section: `mt-12 md:mt-16`

### Responsive Breakpoints
- Mobile: < 768px (single column)
- Desktop: >= 768px (`md:` prefix)
- Large: >= 1280px (`xl:` prefix for container padding only)

### Page Structure
Every public page follows this pattern:
1. Hero card (`rounded-xl border border-[var(--border)] bg-[var(--bg-canvas)] p-5 md:p-8`)
2. Content sections with `fade-in-section` class
3. CTA bar at bottom (`rounded-xl border bg-[var(--bg-subtle)] p-6 md:p-8`)

### Header
- Sticky: `sticky top-0 z-40`
- Height: `h-16`
- Background: `bg-[color-mix(in_srgb,var(--bg-page)_92%,transparent)] backdrop-blur`
- Border: `border-b border-[color-mix(in_srgb,var(--border)_72%,transparent)]`

### Footer
- Compact two-row layout
- Row 1: Non-redundant nav links (pages not in header)
- Row 2: D mark logo | divider | social icons ... legal links + copyright
- Copyright: `© [year] duly` with wordmark treatment

## Elevation

No gradients on buttons or cards. Depth is conveyed through border contrast and surface color variation (page, canvas, subtle, muted).

## Components

### Buttons
- Border radius: 10px
- Solid fill only (no gradients, no blur, no colored backgrounds)
- Primary: `--button-primary-bg` (black in light, white in dark), `--button-primary-text` (inverse)
- Secondary: `--button-secondary-bg` with `--button-secondary-border`
- Font: Clash Grotesk 600, 0.9rem, letter-spacing -0.01em
- Min width: 7.5rem, min height: 2.75rem
- Padding: 0 0.9rem
- Gap (icon + text): 0.45rem
- Hover: opacity 0.88
- Active: translateY(1px)
- Disabled: opacity 0.5, pointer-events none

### Cards
- Border radius: rounded-xl (12px)
- Border: 1px solid `--border`
- Background: `--bg-canvas`
- Padding: `p-4 md:p-5` (standard), `p-5 md:p-8` (hero)
- Hover: `hover-lift` class — translateY(-2px) + `--shadow-hover`, 150ms brand easing

### Inputs
- Border: 1px solid `--border`
- Background: `--bg-muted`
- Border radius: rounded-lg (8px) or rounded-[10px] for search
- Height: h-12 (search), h-10 (standard)
- Focus ring: 2px lavender (`ring-lavender`) with 2px offset (`ring-offset-2`)

### Pills / Badges
- `rounded-full`, 1px border, `bg-subtle` background
- Padding: `px-3 py-1`
- Text: overline style (11px, semibold, uppercase, 0.1em tracking, text-tertiary)

### Overline Labels
- 11px, font-semibold, uppercase, tracking 0.1em, text-tertiary color
- Used before every major section
- Hero overlines get the pill treatment (rounded-full border bg-subtle)
- Section overlines are bare text

### Details / Summary
- Container: `rounded-xl border bg-canvas`
- Chevron: 16px SVG, rotates 180deg on open with 200ms brand easing
- Summary: `hover:bg-subtle`, cursor-pointer
- Marker hidden: `[&::-webkit-details-marker]:hidden list-none`

### Status Badges
- `rounded-full border px-2 py-0.5 text-[11px] font-semibold`
- Success: `border-success/35 bg-success/12 text-success`
- Error: `border-error/25 bg-error/[0.06] text-error`
- Accent: `border-[var(--accent)]/35 bg-[var(--accent-soft)] text-[var(--accent)]`

## Motion

All transitions use brand easing: `cubic-bezier(0.4, 0, 0.2, 1)`.

- **Micro** (150ms): Hover states, focus rings, button press, opacity transitions
- **State** (200ms): Theme toggle, chevron rotation, input focus
- **Layout** (300ms): Card entrance (stagger), section fade-in, auth step transitions

### Animation Classes

- `fade-in-section`: Scroll-triggered fade up 16px. Uses `animation-timeline: view()`. Applied to every section after the hero.
- `stagger-cards`: Child cards animate in with 150ms stagger. For 3-column grids (cycles via `nth-child(3n)`).
- `stagger-seq`: Sequential stagger for 2-column grids and lists (`nth-child` 1-5, 150ms apart).
- `stagger-on-open`: Replays stagger when a `<details>` element opens. 80ms between items.
- `hover-lift`: translateY(-2px) + shadow-hover on hover. Applied to every interactive card.

All animations respect `prefers-reduced-motion: reduce`.

## Accessibility

- Skip-to-content link on every page
- `aria-current="page"` on active nav links
- `aria-label` on all icon-only buttons and links
- `aria-hidden="true"` on decorative SVGs
- Focus ring: 2px lavender with 2px offset on all interactive elements
- `prefers-reduced-motion: reduce` disables all animations
- `min-h-dvh` (not `min-h-screen`) for iOS Safari compatibility
- Minimum touch targets: 44px on all interactive elements
- Keyboard navigation: focus trap in mobile menu, Escape closes dropdowns

## Do's and Don'ts

### Brand
- Do keep "duly" always lowercase. Never "Duly", "DULY", or "DuLy".
- Do end every page H1 with a lavender dot in Clash Grotesk.
- Do start every body paragraph with "duly" in wordmark treatment (font-display, semibold, tight tracking).
- Don't capitalize "duly" anywhere — wordmark, running text, URLs, social handles.

### Visual
- Do use lavender only as an accent (heading dots, focus rings, interactive highlights). Never as a large surface fill.
- Do use solid black/white buttons only. No gradients, no blur, no colored button backgrounds.
- Do use hover-lift on every interactive card.
- Do use fade-in-section on every section after the hero.
- Don't use more than one accent color. Lavender is the only accent.
- Don't use shadows with pure black rgba(0,0,0). Light mode shadows use rgba(31,19,63) (desaturated purple).
- Don't use pulse animations, number counter animations, or scroll progress bars.
- Don't put step connector lines between sequential cards.
- Don't use navy (#03045e) for headings. Headings are always black/white.

### Copy
- Do write clear over clever. Say what it does, plainly.
- Do be confident, not corporate. Speak with conviction, skip the hedging.
- Do be technical when needed. Say "PDA" and "USDC" when appropriate.
- Don't use em dashes in copy (reads as AI-generated).
- Don't use emojis anywhere.
- Don't use jargon on marketing pages (save for /docs).
- Don't use placeholder names like "Acme" or "John Doe".
