# Ten31 CRM — Design contract (DESIGN.md)

*The durable brand brief. Any agent (or person) building or changing user-facing UI reads
this file and `design/tokens.tokens.json` first and conforms to them. Extracted **as-built**
from `frontend/index.html` on 2026-06-18 (document-as-is); this is a faithful record of the
look that grew in the code, not an aspirational redesign. The mobile-first redesign in
`design/BRIEF.md` builds **on top of** this contract — it changes layout/navigation/touch,
not the visual language below.*

## 1. Visual theme

A dense, professional, **dark** venture-CRM workspace (a **light** theme ships as an
optional toggle — see §8 — but dark is the default and the brand's primary identity) — calm,
data-forward, slightly
"terminal/financial." Cool blue-greys throughout, a single saturated blue as the only vivid
accent, and IBM Plex's engineered-but-humane character. Monospace (IBM Plex Mono) carries
all numbers, dates, and codes, reinforcing the data-tool feel. The mood is *trustworthy
instrument*, not consumer-app playful: restraint, legibility, and information density over
decoration. It is used by a ~5-person fund team handling sensitive LP data, so it should
read as serious and discreet.

## 2. Color palette

Canonical values live in `design/tokens.tokens.json`. Summary:

- **Backgrounds (darkest → lightest):** base `#0b1118` → panel `#111a27` → elevated
  `#152233` → hover `#1b2a3a`. Recessed input/table-header surface: `#0d1622`.
- **Borders:** default `#263548` (the workhorse — borders, dividers, every table grid line),
  strong `#35506a` (hover/emphasis).
- **Text:** primary `#e5edf5`, secondary `#c7d3e0`, muted `#8ea2b7` (most common),
  subtle `#70859b`.
- **Accent (the one brand color):** `#3b82c4`. Hover/gradient-end `#2f6ea9`, tint
  `#3b82c422`, on-tint text `#93c5fd`. Used for primary actions, active nav, links, focus.
- **Semantic:** success `#10b981`, warning `#f59e0b`/`#fcd34d`, due-soon `#e0b341`,
  danger `#dc2626`/`#e06c6c`, error-text `#fca5a5`. Badges render semantic color at low
  alpha for the fill with a lighter tint for the text.

White (`#ffffff`) appears only as text on accent fills and in the brand mark.

- **Pipeline-stage chips (redesign)** reuse existing semantic tints — no new hues: lead =
  subtle grey, engaged = accent blue, diligence = due-soon `#e0b341`, commitment = success
  `#10b981`/`#6ee7b7`. **Staleness** (last-contact age) overlays the same ramp: fresh grey →
  due-soon amber `#e0b341` → danger-soft red `#e06c6c`/`#f87171`. Both are tinted-fill + tinted-
  text badges, consistent with the badge rule above.
- **Light theme (implemented, P6)** mirrors every slot above in `tokens.tokens.json` `color.light`
  (e.g. base `#eaeef3`, panel `#ffffff`, text-primary `#16202c`); accent `#3b82c4` is unchanged. Dark
  is the default — see §8.

## 3. Typography

- **Families:** `IBM Plex Sans` (UI/body), `IBM Plex Mono` (numbers, dates, badges, logs,
  nav icons). Loaded from Google Fonts; weights 400/500/600/700 sans, 500/600 mono.
- **Scale (as-built):** 11px micro/table-header/badge · 12px help/meta · **13px body / table
  / inputs (desktop base)** · 14px nav · 16px section title · 18px modal title · 20px page
  title · 24px login title & KPI value.
- **Treatments:** global letter-spacing `0.01em`; table headers uppercase with `0.08em`
  tracking; badges uppercase `0.5px`; numbers use `font-variant-numeric: tabular-nums`.
- **Mobile scale (redesign, sourced from the 2026-06-19 comps):** body/inputs/list rows
  **15px** (up from desktop's 13px); card investor name 16/600; mono amounts 15/600; screen
  title 21/600 (vs desktop 20); full-screen detail title 22/600; sheet title 18/600; section
  labels mono-uppercase 11/600 `0.08em`; chips mono-uppercase 10–11/600; meta/last-contact
  mono 12; bottom-tab label mono 10. Inputs are 44–46px tall for touch. The mono-for-numbers
  and uppercase-tracked-badge rules are unchanged — only the base size grows.

## 4. Component styling

- **Buttons:** primary = top-to-bottom gradient `#3b82c4 → #2f6ea9`, white text, radius 6px,
  padding 10×16, lift on hover (`translateY(-1px)` + soft blue shadow). Secondary = flat
  `#1b2837`. Danger = `#dc2626`.
- **Cards / sections:** panel `#111a27`, 1px `#263548` border, radius 8px, padding 16–20px,
  composite drop shadow + inset top highlight. Hover lifts 1px and strengthens the border.
- **Tables:** recessed header `#0d1622`, uppercase muted 11px headers, sticky header +
  sticky first column, 1px grid lines, row hover `#172435`, sticky aggregate footer.
- **Forms:** inputs on `#0d1622`, 1px border, radius 6px, accent focus ring; label 13/500,
  help 12px muted, error 12px `#fca5a5`.
- **Badges:** radius 4px, 11px/600 uppercase, low-alpha semantic fill + tinted text.
- **Overlays:** modal (centered, radius 12, max-width 500, blurred backdrop) and slide-over
  (right drawer, 400px) for detail/edit.
- **Other:** kanban cards (radius 6), toasts (bottom-right), accent spinner, shimmer
  skeletons, left-marker timeline for activity feeds.

**Mobile component states (redesign, from the 2026-06-19 comps — see §8 and `_imports/`):**
- **Bottom tab bar:** exactly four tabs (Grid · Pipeline · Reminders · Contacts), 56px tall,
  border-top, translucent panel bg + `backdrop-filter: blur(8px)`, `padding-bottom` for
  `env(safe-area-inset-bottom)`. Active tab = accent (icon + 10px mono label); inactive =
  subtle. 20px line-icons.
- **Bottom sheet** (replaces the centered modal + right slide-over on mobile): panel bg,
  strong top border, **radius-20 top corners**, 38×4 grey drag handle, slide-up
  (`translateY(100%)→0`, 280ms `cubic-bezier(.2,.8,.2,1)`), scrim `rgba(4,9,16,0.55)` fade-in,
  max-height ~88–90%, scroll-body; tap-scrim or × to dismiss. One field/action per sheet.
- **Mobile card** (the table→card transform): panel, 1px border, **radius-10**, card shadow,
  12–14px padding, `overflow:hidden` (clips the corner earmark). Three rows: (1) investor
  name 16/600 left + a right-aligned **PRIORITY text pill** (mono 10/600 amber, only when
  flagged); (2) mono amount 15/600 (green if committed, muted `text-subtle` at zero) + the
  **4-stage chip**; (3) mono recency 12 (amber ≥10d, red ≥30d). **Existing-LP = a quiet accent
  corner earmark** (top-left corner-triangle, a reusable `EarmarkCorner` component) — *not* a
  ★ star and *not* a per-card banner (both were option-history, rejected 2026-06-19; finalized
  in Phase 8a). The **Contacts** card is the sibling pattern: a 40px elevated avatar with
  two-letter mono initials, an **accent ring** when the person is an existing LP (the linked
  investor's committed > 0), org **+ a small stage pill** under the name, and a mono recency at
  right (no disposition/type badge). Detail surfaces carry an **"Existing LP" pill** (accent-
  tinted) beside Priority instead of the retired ★.
- **Full-screen detail** (promotes the desktop slide-over): `screenIn` slide (translateX 14px,
  200ms), "‹ Grid" back affordance, grouped read-only sections with per-field edit entry points.
- **Swipe actions** (Reminders): pointer-drag a card to reveal complete (swipe-left) / snooze
  (swipe-right) at a 70px threshold; the action color tints in under the card.
- **Snap-scroll stages** (Pipeline): full-width stage columns, `scroll-snap-type: x mandatory`,
  a segmented stage control + page dots; per-card `‹ / ›` stage move.
- **Account control:** a top-bar avatar opening a small popover (profile + logout) — the only
  non-tab navigation on mobile.
- **Toast:** mobile position is bottom-center **above the tab bar** (not bottom-right).

## 5. Layout

Desktop shell = **fixed 250px left sidebar + flexible main content** with a top header bar
(page title + user). Content max-width 1400px, padding 20px. Primary content patterns:
wide data table (Fundraising Grid), KPI grid + timelines (Dashboard), kanban columns
(Pipeline), list + detail drawer (Contacts/Reminders), two-column (Thesis). Auto-fit grids
are used for KPI cards (`minmax(180px,1fr)`) and kanban columns (`minmax(300px,1fr)`).

## 6. Depth / elevation

Elevation is built from three stacked cues, not just one shadow: (a) a **layered radial-
gradient page background** (two soft blue glows top-left and top-right over `#0b1118`),
(b) panel-color steps (base → panel → elevated), and (c) composite drop shadows with a
1px inset white top-highlight (`inset 0 1px 0 #ffffff07-08`) that gives panels a faint lit
edge. Hover states lift elements 1px and deepen the shadow. Keep this restrained, cool, and
low-contrast — depth should be felt, not seen.

## 7. Do's and don'ts

- **Do** keep `#3b82c4` as the only vivid accent; everything else stays in the blue-grey
  range. **Don't** introduce a second bright hue for emphasis — use weight, tint, or the
  semantic colors.
- **Do** use IBM Plex Mono for every number/date/code. **Don't** set tabular data in the
  sans face.
- **Do** reach for tinted-fill + tinted-text badges for status. **Don't** use solid
  saturated fills for status chips.
- **Do** keep borders at `#263548` and lean on them for structure (this is a grid-lined,
  bordered aesthetic). **Don't** switch to borderless/shadow-only cards.
- **Do** preserve the restrained 1px hover-lift motion. **Don't** add bouncy or long
  animations (and honor `prefers-reduced-motion`, already wired).

## 8. Responsive behavior

**Current (as-built): desktop-first.** Breakpoints are `max-width` (900px, 768px); the
sidebar simply `display:none`s below 768px with no real mobile navigation; wide tables
overflow horizontally; the 400px slide-over overflows a 375px screen. A correct viewport
meta tag is present.

**Target: mobile-first, mobile-preferred.** The design landed via a Claude Design round-trip
(2026-06-19; source + per-surface interaction model in `design/_imports/2026-06-19/`, input
brief in `design/BRIEF.md`). The system:

- **Author base = a 375px column, enhance up** with `min-width` breakpoints for tablet/desktop
  (inverting today's `max-width` rules). **Prerequisite:** responsive layout must live in the
  CSS `<style>` block / utility classes — the ~1,300 inline `style={{}}` objects can't respond
  to media queries, so an **inline-style→CSS migration** gates this work (tracked in `ROADMAP.md`).
- **Mobile is a focused subset, not the whole app:** only **four surfaces** ship on mobile —
  **Fundraising Grid · Pipeline · Reminders · Contacts** — in a **bottom tab bar**; every other
  screen (Dashboard, Thesis, Outreach, Settings, …) is desktop-only and absent, with just a
  minimal top-bar account/logout control.
- **Navigation:** the 250px sidebar → a safe-area-aware **bottom tab bar of four**. No "More"
  menu.
- **Transforms:** wide data table → **investor card list + full-screen detail**; Pipeline kanban
  → **swipe-between-stages** (snap-scroll, segmented control, per-card stage move); centered
  modal + 400px slide-over → **drag-to-dismiss bottom sheets** / full-screen detail; Grid saved
  *views* → a tappable view-name opening a **bottom-sheet view picker**.
- **Editing on mobile** is the on-the-go core only — investor name, contact pills, notes/comm
  log, pipeline stage, reminders, and new-investor create (via the Grid, the canonical write
  path). Commitments/amounts and the full column set stay **read-only / desktop-only**. (Write
  paths use the targeted one-row `log-communication` endpoint + the pipeline link→stage flow,
  **not** whole-grid saves — see `BRIEF.md` §3a "Backend reality.")
- **Touch + safe areas:** 44px minimum primary touch targets; body type bumped 13→15px (§3);
  sticky bottom nav respects `env(safe-area-inset-bottom)` and content gets bottom padding so
  the nav never overlaps it.
- **Light theme — implemented (P6, 2026-06-19).** The light palette (`tokens.tokens.json`
  `color.light` + the per-component tints from the Claude Design export) ships behind a
  `:root[data-theme="light"]` switch, applied by a pre-paint boot script from
  `localStorage.venture_crm_theme` and toggled app-wide (desktop sidebar footer + mobile top-bar
  icon). **Dark stays the default and the brand's primary identity;** light is the optional
  alternative (no `prefers-color-scheme` auto-switch). Colors are driven by ~44 themed `:root` CSS
  vars whose dark values equal the original literals (so dark mode is unchanged). **Known gaps
  (Phase 7 conformance pass):** some bespoke desktop `<style>` shades (login glow/scrollbar/
  table-hover/KPI), the legacy off-palette `.badge-*` family, and shadows are not yet themed.
  Full per-component light tints (stage/staleness/note badges) live in
  `_imports/2026-06-19_zip-file/` (`store.js` + the four `*App.dc.html` `DCLogic` palettes).

The gap between this section and the current `index.html` is the implementation backlog in
`ROADMAP.md` (incl. the inline-style→CSS migration and the locked pipeline-stages/flags spec).
The **per-surface mobile visual-conformance reference** is `design/phase8-conformance.md` (the
8a–8i build spec, anchored on each `*.dc.html` default — not the `screenshots/` PNGs). The
**Grid + Contacts card anatomy is finalized (Phase 8a)** — earmark corner-triangle, PRIORITY
text pill, 4-stage chip, Contacts avatar ring (see the §4 mobile-card bullet). The **Contacts +
Pipeline detail surfaces are drag-dismiss bottom sheets (Phase 8b)** — email-copy pill + Log/Email
actions + Organization card (Contacts); stat tiles + inline move-stage list + notes timeline + Log
sheet (Pipeline); both log through `POST /api/communications`. **Phase 8 is complete (8a–8i)** —
8c–8h added the quick-log pencil, sort sheets, reminders/Pipeline-card polish, add-investor sheet,
and the Grid detail's G4/G5/G6 stage-card/reminder-card/timeline restructure; **8i** swapped the
bottom-tab emoji glyphs for the dc SVG line-icons (`BottomTabIcon`) and added the `·Ten31·` top-bar
wordmark (the page title is now desktop-only). The Grid detail stays full-screen (its dc default).
What remains is **deploy + real-phone device-test** (light/dark), not further build.

## 9. Agent prompt guide

When building or changing UI here:
- Pull every color, size, radius, and space value from `design/tokens.tokens.json` — do not
  hand-pick new hexes. The app still inlines many values; prefer the `:root` CSS variables
  (and grow that set) over fresh literals.
- Match the established components above; if you need a new one, compose it from existing
  tokens and the bordered-panel + tinted-badge idiom rather than inventing a new visual style.
- Numbers/dates/codes → IBM Plex Mono + tabular-nums. Status → tinted badge. Primary action →
  the blue gradient button. Destructive → `#dc2626` and a confirm step.
- **Building anything mobile/responsive?** Read `design/BRIEF.md` first — it holds the
  mobile-first layout, navigation, and interaction decisions this section will eventually
  absorb.
- Reminder: inline `style={{}}` objects cannot respond to media queries — put any
  responsive layout in the CSS `<style>` block (or a utility class), not inline.
