Files
boc/design/DESIGN_SYSTEM.md
T

399 lines
14 KiB
Markdown
Raw Normal View History

# Design System Documentation
## quiXzoom & Landvex
> Last updated: 2026-06-24
> Status: Production-ready v1.0
---
## Table of Contents
1. [Token System Architecture](#1-token-system-architecture)
2. [quiXzoom Brand Rules](#2-quixzoom-brand-rules)
3. [Landvex Brand Rules](#3-landvex-brand-rules)
4. [Shared Constraints](#4-shared-constraints)
5. [Typography Deep-Dive](#5-typography-deep-dive)
6. [Spacing & Grid](#6-spacing--grid)
7. [PR Audit Checklist](#7-pr-audit-checklist)
8. [Do / Don't Reference](#8-do--dont-reference)
---
## 1. Token System Architecture
### How It Works
Each brand ships a single CSS custom properties file (`:root { ... }`). All component CSS references these tokens — **never raw values**.
```
design/
├── quixzoom-tokens.css ← Import first, sets all --qx-* vars
├── landvex-tokens.css ← Import first, sets all --lv-* vars
├── quixzoom-hero.html ← Self-contained, inline tokens
└── landvex-hero.html ← Self-contained, inline tokens
```
### Token Naming Convention
| Prefix | Brand |
|--------|-------|
| `--qx-` | quiXzoom |
| `--lv-` | Landvex |
### Token Categories
Every token file provides these exact categories in this order:
1. **Grayscale** — 4 stops from white → deep carbon
2. **Accent colors** — primary + secondary + alpha variants
3. **Semantic aliases** — bg, text-primary, border, etc. (reference grayscale/accents)
4. **Spacing** — 8px-grid-aligned steps
5. **Typography** — font stacks, locked type scale, weights, line-heights, tracking
6. **Easing** — named timing functions + duration values
7. **Border radius** — 5-step scale
8. **Shadow system** — layered shadows appropriate to each theme
9. **Z-index scale** — consistent stacking context
10. **Transition helpers** — shorthand transition values
### Why Semantic Aliases?
```css
/* ✅ Correct — uses semantic alias */
color: var(--qx-text-primary);
/* ❌ Wrong — hardcodes the raw color */
color: #FFFFFF;
/* ❌ Also wrong — bypasses semantic layer */
color: var(--qx-white);
```
Semantic aliases (`--qx-text-primary`, `--lv-bg-surface`) let you reskin a component
for dark/light variants by swapping token values — not rewriting component CSS.
---
## 2. quiXzoom Brand Rules
### Philosophy
**Sport-Tech / Nike-vibes.** Energy, kinetic motion, dark precision.
quiXzoom never feels corporate. It feels like it was built by athletes, for athletes.
### Theme
- **Always dark-first.** Default background: `--qx-deep-carbon` (`#0D0D0D`)
- **Light theme is only permitted** for marketing landing pages with explicit design approval
### Colors
| Token | Value | Use |
|-------|-------|-----|
| `--qx-neon-primary` | `#00FF87` | CTAs, highlights, focus rings, glow effects |
| `--qx-neon-secondary` | `#00D1FF` | Links, hover states, secondary actions |
| `--qx-deep-carbon` | `#0D0D0D` | Page background |
| `--qx-gray-700` | `#2A2A2A` | Surface / card backgrounds |
**Accent usage rules:**
- Neon green (`--qx-neon-primary`) is the **only** primary CTA color
- Never use neon on a light background — contrast degrades to unusable
- Glow effects (box-shadow with neon alpha) are **permitted** on CTAs only
- Never use neon as body text color — always gray-400 or white for prose
### Typography
- **Font:** Inter (900 Black for display, 700 Bold for headings, 400 Regular for body)
- **Display sizes:** `--qx-text-xl` (64px) desktop, `--qx-text-lg` (48px) minimum
- **Locked scale:** 12 / 16 / 24 / 48 / 64px — no values between these
- **Letter spacing on display:** always `-0.03em`
- **Line height on display:** always `1.0` — never more
### Animation
- **Signature easing:** `--qx-ease-snap` = `cubic-bezier(0.16, 1, 0.3, 1)`
- **All hero animations** use `ease-enter` = `cubic-bezier(0.22, 1, 0.36, 1)`
- **Stagger hero elements:** 0.1s increments (eyebrow → headline → sub → CTA)
- **Respect prefers-reduced-motion** — wrap animations in media query
```css
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
```
### Forbidden in quiXzoom
- ❌ Light backgrounds (without explicit approval)
- ❌ Serif fonts
- ❌ Rounded corners above `--qx-radius-md` (8px) on interactive elements
- ❌ Easing other than the defined set
- ❌ More than 2 accent colors in a single view
- ❌ Drop shadows without neon tinting in dark context
---
## 3. Landvex Brand Rules
### Philosophy
**German Enterprise / Siemens-vibes.** Precision, system, authority.
Landvex never feels playful. It feels like the most reliable tool in the room.
### Theme
- **Always light-first.** Default background: `--lv-white` (`#FFFFFF`)
- **Dark theme is not supported** — Landvex has no dark mode in v1
### Colors
| Token | Value | Use |
|-------|-------|-----|
| `--lv-enterprise-blue` | `#1B4FBF` | CTAs, links, active states, accent rules |
| `--lv-enterprise-dark` | `#0F2E6E` | Hover/pressed on blue elements |
| `--lv-gray-200` | `#DEDEDE` | Separator lines, dividers |
| `--lv-gray-800` | `#222222` | Primary body text |
**Accent usage rules:**
- Enterprise blue is reserved for **interactive** elements only (buttons, links, focus)
- Never use enterprise blue as a background color for large areas
- Never use more than one accent color per screen
- Decorative use of blue (icon fills, rule lines) is permitted at reduced opacity
### Typography
- **Sans:** IBM Plex Sans — headings, labels, body, UI
- **Serif:** IBM Plex Serif — long-form editorial content, quotes, executive reports only
- **Mono:** IBM Plex Mono — code, API keys, data tables
- **Body line-height:** always `1.55` (`--lv-leading-base`) — non-negotiable
- **Display sizes:** `--lv-text-lg` (48px) max, `--lv-text-md` (24px) for sections
- **Tracking on overlines/labels:** `0.080.10em` with uppercase
### Separator Lines
Thin horizontal rules are core to Landvex's visual language.
Use `border-top: 1px solid var(--lv-border)` to:
- Divide major content sections
- Separate items in lists
- Create structural grouping without whitespace alone
**Never use decorative thick rules**`border-top` should always be `1px`.
The only permitted `2px` rule is `--lv-separator-accent` used to highlight the active tab/section.
### Grid
- **Base unit:** 8px (`--lv-grid-base`)
- **All spacing values must be multiples of 8px**
- **Exception:** 4px (`--lv-space-xs`) permitted only for internal component padding (badges, labels)
- **Content max-width:** `--lv-container-lg` (1200px) for standard pages
### Forbidden in Landvex
- ❌ Dark backgrounds
- ❌ Neon or high-saturation accent colors
- ❌ Rounded corners above `--lv-radius-md` (4px) on structural elements
- ❌ Animation durations above `--lv-dur-slow` (350ms)
- ❌ Drop shadows with colored glow
- ❌ Text ALL-CAPS for body copy (labels/overlines only)
- ❌ Font weights below 400 for body text
- ❌ Decorative illustrations or icons — data visualization only
---
## 4. Shared Constraints
These rules apply to **both brands** without exception.
### Currency
- ✅ Always use **EUR (€)** or **USD ($)**
- ❌ Never use SEK or any other currency in UI copy or examples
### Responsiveness
- **iPhone-first** — design for 390px viewport, scale up
- Test breakpoints: `390px` / `640px` / `1024px` / `1440px`
- No horizontal scroll at any breakpoint above 320px
### Performance
- No external CSS frameworks (Bootstrap, Tailwind, etc.)
- No JavaScript required for hero sections — pure HTML/CSS
- Google Fonts loaded with `display=swap` — always
- Images must have `width` and `height` attributes — prevent CLS
### Accessibility
- Semantic HTML: `<nav>`, `<section>`, `<h1>` one per page, `<aside>`
- All interactive elements must have visible focus styles
- `aria-label` on all navigation regions
- Decorative elements marked `aria-hidden="true"`
- Color is never the sole indicator of state
### Type Scale — Locked
Both brands use the **same locked type scale**:
| Token | Size | Use |
|-------|------|-----|
| `*-text-xs` | 12px | Labels, captions, badges, overlines |
| `*-text-sm` | 16px | Body text, nav links, button labels |
| `*-text-md` | 24px | Section headings, card titles |
| `*-text-lg` | 48px | Page-level headings |
| `*-text-xl` | 64px | Hero display (quiXzoom primary, Landvex upper bound) |
**No interpolated values between steps.** If 20px looks right, it's wrong — use 16px or 24px.
---
## 5. Typography Deep-Dive
### quiXzoom Typography
```
Display (hero): Inter Black 900 / 64px / lh 1.0 / ls -0.03em
Heading 1: Inter Black 900 / 48px / lh 1.0 / ls -0.02em
Heading 2: Inter Bold 700 / 24px / lh 1.2 / ls -0.01em
Body: Inter Regular 400 / 16px / lh 1.5 / ls 0
Label/Eyebrow: Inter Bold 700 / 12px / lh 1 / ls +0.15em / UPPERCASE
```
**Why Inter?**
Inter's tight metrics at high weights create the dense, athletic look appropriate for
a sport-tech product. The `-0.03em` letter-spacing on display text echoes Nike/Adidas
brand typography conventions.
### Landvex Typography
```
Display (hero): IBM Plex Serif Semibold 600 / 48px / lh 1.2 / ls -0.01em
Heading 2: IBM Plex Sans Semibold 600 / 24px / lh 1.35 / ls 0
Body: IBM Plex Sans Regular 400 / 16px / lh 1.55 / ls 0
Caption: IBM Plex Sans Regular 400 / 12px / lh 1.55 / ls 0
Label/Overline: IBM Plex Sans Medium 500 / 12px / lh 1 / ls +0.10em / UPPERCASE
Data/Code: IBM Plex Mono Regular 400 / 14px / lh 1.5 / ls 0
```
**Why IBM Plex?**
IBM Plex is the house typeface of IBM — the canonical German-enterprise-technology voice.
Its Sans variant has mechanical precision without coldness. Its Serif variant provides
editorial gravity for boardroom-level reports. The family cohesion eliminates font-pairing risk.
**line-height 1.55:**
The `1.55` body line-height is Landvex's typographic signature. It provides maximum
reading comfort for high text-density layouts (1218 words per line) without
requiring increased font size. Never change this value.
---
## 6. Spacing & Grid
### 8px Base Grid
Both systems use an 8px base unit. All spacing must be a multiple of 8.
```
4px = --qx-space-xs / --lv-space-0.5 → micro (badge padding only)
8px = --qx-space-sm / --lv-space-1 → tight grouping
16px = --qx-space-md / --lv-space-2 → standard gap
24px = --lv-space-3 → section internal padding (Landvex only)
32px = --qx-space-lg / --lv-space-4 → section spacing
48px = --lv-space-6 → large section gap
64px = --qx-space-xl / --lv-space-8 → major section break / hero padding
96px = --qx-space-2xl / --lv-space-12 → page-level rhythm
128px = --qx-space-3xl / --lv-space-16 → XL layout breathing
```
### When to Use 4px
4px is **only** permitted for:
- Internal padding on small components (badge pill, tag, inline chip)
- Icon-to-text gap in compact lists
- Fine-tuning vertical rhythm within a text block
Never use 4px as a layout spacing unit.
---
## 7. PR Audit Checklist
Copy this block into your PR description when touching design files.
```markdown
## Design System Audit
### Token Compliance
- [ ] No hardcoded hex values in component CSS
- [ ] No hardcoded px values outside of the locked type scale
- [ ] All spacing values are multiples of 8px
- [ ] Semantic aliases used (e.g. `--qx-text-primary` not `--qx-white`)
### Brand Rules
- [ ] quiXzoom: dark background maintained
- [ ] Landvex: light background maintained
- [ ] Currency is EUR or USD only — no SEK
- [ ] Type scale uses only: 12 / 16 / 24 / 48 / 64px
- [ ] No external CSS frameworks added
### quiXzoom Specifics (if applicable)
- [ ] Neon green used only for interactive/CTA elements
- [ ] Easing uses `--qx-ease-snap` or `--qx-ease-enter`
- [ ] Hero animation stagger is ≤ 1.0s total
- [ ] `prefers-reduced-motion` respected
### Landvex Specifics (if applicable)
- [ ] Body line-height is `1.55`
- [ ] Separator lines are `1px solid var(--lv-border)`
- [ ] All spacing is on 8px grid
- [ ] No rounded corners above `--lv-radius-md` (4px) on structural elements
- [ ] No colored shadows
### Accessibility
- [ ] One `<h1>` per page
- [ ] All interactive elements have focus styles
- [ ] Decorative elements have `aria-hidden="true"`
- [ ] Color is not the sole indicator of state
- [ ] `<img>` tags have `alt`, `width`, and `height`
### Responsiveness
- [ ] Tested at 390px (iPhone 14)
- [ ] Tested at 640px (tablet)
- [ ] Tested at 1024px (desktop)
- [ ] No horizontal scroll at any breakpoint
```
---
## 8. Do / Don't Reference
### quiXzoom
| ✅ Do | ❌ Don't |
|-------|----------|
| Use `--qx-neon-primary` for CTAs | Use neon on light backgrounds |
| Use Inter Black 900 for display | Use system fonts for display |
| Animate with `--qx-ease-snap` | Use `ease-in-out` or `linear` |
| Keep display line-height at `1.0` | Add padding between headline words |
| Use dark overlays for card hover | Use light overlays or color fills |
| Price in EUR / USD | Price in SEK |
### Landvex
| ✅ Do | ❌ Don't |
|-------|----------|
| Use `1px solid var(--lv-border)` for dividers | Use thick rules or decorative lines |
| Keep body `line-height: 1.55` | Change body line-height for "breathing" |
| Use IBM Plex Serif for editorial | Use IBM Plex Serif for UI labels |
| Use 8px-grid spacing always | Use arbitrary pixel values |
| Use `--lv-enterprise-blue` for interactive only | Paint large areas enterprise-blue |
| Animate with `--lv-ease-standard` | Use spring/bounce easing |
| Price in EUR / USD | Price in SEK |
---
*Design system maintained by the quiXzoom/Landvex platform team.*
*Questions → design@quixzoom.com / design@landvex.com*