# ConnectIQ Design Language

Version: 1.1  
Scope: visual style only  
Themes: light (default) · dark · presentation  
Primary reference: `tokens.json`

## 1. Purpose

ConnectIQ is a compact, operational B2B application for CRM, deployment, subscriptions, inventory, support, and customer-facing dashboards. Its interface should feel calm, precise, trustworthy, and efficient rather than decorative.

This file defines visual rules only. It does not define component APIs, business logic, page structure, database behaviour, or domain ownership.

As of 1.1 the system carries three themes. **Light** is the default and governs every operational screen. **Dark** is the same application on dark surfaces — identical density, identical hues, different ground. **Presentation** is a looser theme for decks, reports and customer-facing dashboards, derived from the Ember Dark study. Sections 1–20 describe the light theme and the rules common to all three. Section 21 covers dark, section 22 covers presentation. Where those sections are silent, the common rules apply.

## 2. Source of truth

Use this order when visual sources disagree:

1. Semantic values in `tokens.json`
2. Rules in this `DESIGN.md`
3. Approved Figma screens
4. Existing implementation patterns

Do not sample new values from screenshots after implementation begins. The screenshots contain minor inconsistencies that have been normalized in the tokens.

## 3. Design review and normalization decisions

The supplied Figma screens have a clear visual language:

- white working surfaces over a warm off-white application canvas
- black primary actions and headings
- orange for brand identity, active navigation, tabs, links, and focused emphasis
- mint green for selected states, successful completion, and positive metrics
- yellow for warning, pending, or scheduled states
- red for errors, destructive actions, and ticket spikes
- blue mainly for informational or in-progress data visualization
- thin neutral borders, low shadow usage, compact typography, and high information density

The supplied screens also contain values that should not be reproduced as separate tokens:

- orange appears near both `#FF6700` and `#F4701D`
- green appears near both `#62C696` and `#76C299`
- red appears near both `#FF4848` and `#F2584B`
- pale canvas and field backgrounds vary slightly
- control heights and corner radii vary between examples
- purple dashed outlines are Figma selection indicators, not ConnectIQ brand styling

The normalized values in `tokens.json` resolve these differences.

## 4. Visual character

Use these adjectives as a quality check:

- operational
- compact
- calm
- precise
- clean
- lightly warm
- trustworthy
- data-forward

Avoid these visual directions:

- marketing-site styling
- glassmorphism
- heavy gradients
- oversized cards
- large empty hero areas
- excessive shadows
- highly rounded “bubble” interfaces
- playful multicolour decoration
- purple as a brand, navigation, focus or interaction colour
- orange-filled large areas
- raw black borders around every element

## 5. Colour rules

### 5.1 Core hierarchy

- Primary text and primary action backgrounds use neutral black.
- Main surfaces use white.
- The app canvas and quiet sections use the warm neutral background tokens.
- Orange is the brand accent, not the default primary button colour.
- Green is reserved for successful, completed, active, connected, or selected states.
- Yellow is reserved for warning, pending, scheduled, expiring, or attention-needed states.
- Red is reserved for errors, destructive actions, severe exceptions, or negative spikes.
- Blue is reserved for informational and in-progress visualization where green or orange would be misleading.

### 5.2 Semantic use

Always use semantic variables such as:

- `background.canvas`
- `background.surface`
- `foreground.primary`
- `foreground.muted`
- `border.default`
- `action.primaryBackground`
- `state.successBackground`
- `state.warningBorder`

Never place raw hex values in application components. Raw values belong only in token/theme files.

### 5.3 Status is never colour-only

Every status must also include at least one of:

- readable status text
- icon
- shape or border treatment
- position or label

Do not rely on green, yellow, red, or blue alone.

### 5.4 Gradients

Do not use gradients for interface chrome, buttons, panels, navigation, forms, or modal surfaces.

Subtle vertical alpha gradients are allowed inside charts only, as seen in the supplied dashboard screens. Chart gradients should fade toward transparency or a very pale neutral.

### 5.5 Modelled values, and the purple exception

`chart.modelled` (`#9B8FD8`) means **projected, forecast, scenario, or otherwise not yet real**. It exists because forecasting appears throughout the strategy and CRM documents and the palette previously had no way to distinguish a modelled bar from an actual one.

This is the single sanctioned use of a purple hue in ConnectIQ, and it is **chart-scoped**:

- allowed: a chart series, a chart legend entry, a chart area fill
- not allowed: brand marks, navigation, tabs, links, focus rings, buttons, badges, borders, selected states, or any interaction affordance

The prohibition in section 4 was written to stop the purple Figma selection outlines from being reproduced as product styling. That intent is unchanged. A forecast series is not interface chrome.

Because a modelled value is a claim about certainty rather than a status, it must carry a second cue as well as the hue — a dashed or hatched fill, a "forecast" label, or a legend entry. Section 5.3 applies here with no exception.

## 6. Typography

### 6.1 Font family

Use `Inter` for the main interface with the fallback stack from `tokens.json`.

The exact Figma font metadata was not available in the screenshots, so Inter is the normalized recommendation. Replace it only after confirming the original Figma library uses another family.

Use `font.family.display` — **Neue Montreal**, the licensed Giant Pumpkin brand face, with Inter as its automatic fallback — for display headings, page titles, and all presentation-theme headings. Do not use it for body copy, controls, or dense table text.

The Ember Dark study specified Poppins and IBM Plex Mono. Both were placeholders in that document's own terms; Neue Montreal and the existing data stack replace them and neither Poppins nor IBM Plex Mono is part of ConnectIQ.

Use the data/monospace stack only for:

- compact uppercase table headers
- KPI micro-labels
- identifiers
- serial numbers
- codes
- tightly aligned tabular data

Do not use monospace for regular body copy.

### 6.2 Density and scale

The default application font size is `14px` (`font.size.base`), with `12px` allowed for secondary data and `11px` for compact labels. Use `16px` (`font.size.lg`) for modal copy and less dense customer-facing views.

`base` was `13px` through 1.0. It moved to `14px` in 1.1: the product is still compact and data-forward, but 13px sat below comfortable reading size for sustained operational use. Density comes from spacing, control heights and information hierarchy — not from shrinking body text.

`font.size.md` was retired in the same change. It held `14px` and would have duplicated `base`. Use `base` for 14px and `lg` for 16px.

Recommended hierarchy:

- dashboard greeting or major display heading: 28–32px, 800
- page title: 24px, 700
- section title: 16–18px, 600–700
- regular body: 14px, 400
- emphasized body or labels: 14px, 500–600
- table and metadata text: 12px, 400–500
- uppercase data label: 11px, 500, `0.06em`
- large KPI value: 32–36px, 500–600

Table and metadata text stays at `12px`. It is deliberately denser than body copy — that is what a data table is for — and section 13 chose that value independently of the base size.

Use sentence case for headings and labels. Uppercase is limited to compact data labels and table headers.

### 6.3 Line length

Long explanatory text should not span the full application width. Keep prose to approximately 60–80 characters per line.

## 7. Spacing and density

Use a 4px base grid with an 8px primary rhythm.

Preferred spacing sequence:

`4, 8, 12, 16, 20, 24, 32, 40, 48, 64`

Rules:

- 4px: icon-to-label micro-gap
- 8px: closely related controls or metadata
- 12px: compact internal grouping
- 16px: normal control and content grouping
- 24px: section padding or major row separation
- 32px: page-level separation
- 40px and above: major layout spacing only

Do not introduce arbitrary values such as 13px, 17px, 22px, or 30px unless matching a documented browser or chart constraint.

The product should remain compact. Do not automatically apply generous marketing-site spacing.

## 8. Shape, borders, and elevation

### 8.1 Corner radius

Use:

- 6px for compact tags and small controls
- 8px for normal controls and fields
- 12px for cards, tables, chart panels, and grouped sections
- 16–20px for dialogs or large floating surfaces
- full pill radius only for statuses, compact badges, and switches

Do not make every surface pill-shaped.

### 8.2 Borders

- Default border: 1px neutral
- Strong or active boundary: 2px only when necessary
- Selected controls use a green border and very pale green background
- Focus uses an orange focus ring, not a persistent orange border
- Cards and tables should use borders before shadows

### 8.3 Shadows

The design is primarily flat.

Use:

- no shadow for normal cards and inline sections
- small shadow for menus or compact popovers
- medium shadow for dropdowns and dialogs
- large shadow only for major modal overlays

Avoid stacking borders and strong shadows unless required for an overlay.

## 9. Layout

### 9.1 Application shell

- desktop sidebar target width: 224px
- collapsed sidebar target width: 64px
- maximum page content width: 1440px
- typical page padding: 24px desktop, 16px compact desktop/tablet, 12px mobile
- main content should align to a consistent left edge across pages

### 9.2 Responsive behaviour

The screenshots indicate both wide dashboard use and narrower field/deployment use.

At narrower widths:

- convert the fixed sidebar into a drawer or compact rail
- stack two-column form and checklist layouts
- allow tabs to horizontally scroll instead of wrapping unpredictably
- keep primary actions visible without covering form content
- preserve dense tables through horizontal scrolling, column priority, or detail disclosure
- do not simply shrink all text

### 9.3 Data-first hierarchy

Operational data should appear before decorative elements.

Use whitespace, borders, alignment, and typography to organize information. Do not add illustrations or oversized icons to fill space.

## 10. Forms and interaction styling

This section defines visual behaviour, not component implementation.

- Default control height: 40px
- Compact control height: 32px
- Large/customer-facing control height: 48px
- Field backgrounds may use white or the muted warm neutral, but remain consistent within a form
- Labels sit above fields
- Helper and validation text appear directly below the related field
- Required fields use text or a small marker; do not use colour alone
- Searchable selects visually match text inputs
- Disabled controls remain readable and visibly inactive
- Destructive actions use red and require clear wording

Focus treatment:

- 2px orange focus ring
- 2px visual offset where possible
- focus must remain visible on white, pale green, and pale neutral surfaces

## 11. Navigation and active states

- Sidebar active state uses a quiet warm-neutral or pale green surface with a narrow orange indicator
- Tabs use orange text and a thin orange underline for the active item
- Inactive navigation uses muted or secondary text
- Hover should be subtle and should not visually compete with the active state
- Orange identifies current context; it should not turn all navigation into orange text

## 12. Feedback and status styling

Inline feedback uses tinted backgrounds. Floating toasts use white surfaces with a semantic border and icon.

Success:
- mint icon/border
- pale mint background for inline messages
- plain, direct text

Warning:
- yellow icon/border
- pale yellow background

Error:
- red icon/border
- pale red background

Information:
- blue icon/border when the message is neutral information
- the brand orange may be used for process guidance closely tied to navigation or workflow

Keep feedback copy concise and actionable.

## 13. Tables and dense operational data

- white surface
- 1px neutral row and outer borders
- 12px body text
- 11px uppercase data headers with small letter spacing
- numeric data aligned consistently
- identifiers and serial numbers may use the data/monospace family
- row hover is a quiet neutral
- expanded rows use a very pale neutral background
- actions should not dominate the row
- status labels use text plus semantic colour

Avoid zebra striping unless testing shows it materially improves scanability.

## 14. Charts and metrics

Use the semantic chart palette from `tokens.json`.

- green: completed, compliant, positive
- yellow: scheduled, pending, caution
- blue: in progress or informational
- orange: brand-related comparison or highlighted series
- red: incidents, errors, spikes, negative exceptions
- modelled: projected, forecast, or scenario values — see section 5.5
- neutral: baseline, inactive, or normal volume

Rules:

- chart labels use muted text
- grid lines use subtle borders
- tooltips use a dark neutral surface and white text
- avoid more than five simultaneous categorical colours
- never reuse the same colour for conflicting meanings in one view
- include labels, legends, or patterns; do not depend on colour alone

## 15. Iconography

Use one consistent outline icon family, preferably Lucide.

- 16px for most controls and navigation
- 20px for prominent actions or empty states
- 24px only for major status or informational messages
- stroke width should remain visually consistent
- icons support labels; they do not replace ambiguous text

Do not mix filled, outlined, cartoon, and multicolour icon styles.

## 16. Motion

Motion should communicate state, not decorate the interface.

- 120ms for hover and pressed feedback
- 180ms for standard transitions
- 240ms for dialogs and drawers
- use the standard easing token
- respect `prefers-reduced-motion`
- do not animate large dashboard areas on every data refresh
- avoid bouncing, elastic, or playful motion

## 17. Accessibility

Minimum requirements:

- WCAG AA contrast for normal text
- visible keyboard focus on all interactive elements
- 44px effective touch target for field/mobile workflows, even when the visual control is smaller
- labels connected to form controls
- status meaning not conveyed by colour alone
- error text identifies both the field and the correction
- charts provide textual values or accessible summaries
- modal focus is trapped and restored correctly
- reduced-motion preference is respected

## 18. Implementation rules

For Tailwind/shadcn implementations:

1. Define CSS variables from `tokens.json` in the central theme file.
2. Map Tailwind semantic names to those variables.
3. Use semantic classes only, such as `bg-background`, `text-foreground`, `border-border`, `text-accent`, and state-specific semantic classes.
4. Never hard-code raw Tailwind palette classes such as `orange-500`, `green-400`, `gray-200`, `bg-black`, or `text-white` in feature code.
5. Never introduce a new colour, radius, spacing value, shadow, or font size before checking the token file.
6. Do not modify the design tokens as a side effect of building a feature.
7. Keep style changes separate from functional changes where practical.
8. Preserve the compact 14px application density.
9. Use charts as the only normal exception for subtle gradients.
10. Treat Figma purple selection outlines as editor chrome and never implement them.

## 19. AI anti-drift rules

When generating or editing UI:

- read `tokens.json` and this file first
- inspect nearby existing screens before changing style
- reuse the established visual language
- do not invent a “better” palette
- do not add new shadows, gradients, radii, or font scales
- do not redesign unrelated areas
- do not convert operational pages into marketing layouts
- do not add components solely for visual decoration
- do not use placeholder colours from framework defaults
- explicitly state any token that must be added and why before adding it
- when a screenshot conflicts with the normalized token set, follow the token set

## 20. Change control

Design-token changes affect every ConnectIQ build.

Any change to a primitive or semantic token should include:

- reason for change
- affected screens
- accessibility impact
- before/after value
- version increment
- implementation migration note

Feature branches may consume design tokens. They should not redefine them locally.

### 20.1 Change record — 1.0.0 → 1.1.0

**Reason.** Merge the Ember Dark study into the system. The study was derived from four presentation slides and arrived as a self-contained dark visual language; adopting it wholesale would have replaced the operational light theme with a slide language. It was instead split into a dark theme for the application and a presentation theme for decks and reports.

**Method.** Every Ember hue was measured against Ember's own surfaces before any value was accepted.

**Finding that shaped the merge.** All five existing ConnectIQ semantic hues already pass WCAG AA against `#000000`, `#13151A` and `#1E1E1E`:

| Hue | on `#000000` | on `#13151A` | on `#1E1E1E` |
| --- | --- | --- | --- |
| orange `#FF6700` | 7.19 | 6.25 | 5.71 |
| success `#62C696` | 10.04 | 8.73 | 7.97 |
| warning `#F1BF00` | 12.19 | 10.60 | 9.68 |
| danger `#F2584B` | 6.27 | 5.46 | 4.98 |
| info `#4C8FF7` | 6.58 | 5.72 | 5.22 |

There was therefore no accessibility argument for replacing them, and the two palettes proved perceptually close — the brand hues differ by 1.3 points of CIE L\*, the danger hues by 2.7. The existing hues were kept.

**Affected screens.** Every screen, but only through type size. No light-theme *colour* value changed. The one non-additive change in 1.1.0 is `font.size.base` moving from `13px` to `14px`, which reflows body copy everywhere. Colour, spacing, radii, control heights and layout dimensions are untouched, so nothing needs relaying out.

**Accessibility impact.** Positive on balance.

- Ember's `text-low` `#636363` was **rejected as specified**. It was assigned to units, footnotes and column captions — real text — but scores 3.50 / 3.04 / 2.77 on the three dark surfaces, failing AA, which section 17 requires. Corrected to `#858585` (5.69 / 4.95 / 4.52), the smallest change that passes on all three.
- Ember's claim that its extended hues sit at equal perceptual lightness does not hold — they span L\* 61.1 to 78.5. The claim was not relied on.
- Every dark-theme state pair was verified composited: hue foregrounds score 4.78–7.02 on their tinted backgrounds, body text 9.71–10.58.

**Before / after values.**

| Token | 1.0.0 | 1.1.0 |
| --- | --- | --- |
| `font.size.base` | `13px` | **`14px`** |
| `font.size.md` | `14px` | **retired** — would duplicate `base` |
| `font.family.display` | — | Neue Montreal → Inter fallback |
| `color.warning.dark` | — | `#E0A83A` (dark theme only) |
| `color.modelled.500` | — | `#9B8FD8` (chart-scoped) |
| `color.darkSurface.*` | — | `#000000` `#0A0B0D` `#13151A` `#1E1E1E` |
| `color.darkText.*` | — | `#FFFFFF` `#D2D2D2` `#94959D` `#858585` |
| `semantic.dark.*` | — | full dark semantic set |
| `presentation.font.*` | — | presentation type scale, body `16px` |
| `presentation.layout.*` | — | split, margins, accent bar, caps |
| `radius.*` | 4/6/8/12/16/20/pill | **unchanged** |
| section 4 purple rule | "purple as a product accent" | "purple as a brand, navigation, focus or interaction colour" |

`warning` is the one hue where the dark theme diverges: `#F1BF00` scores 10.60 on `#13151A` and out-shouts the brand accent there, so the dark theme uses `#E0A83A`. The light theme keeps `#F1BF00`.

**Rejected from the incoming study.** Recorded so they are not proposed again:

| Ember value | Why rejected |
| --- | --- |
| `#636363` caption grey | Fails AA on all three of its own dark surfaces. Corrected to `#858585`. |
| ember `#E87F2E`, mint `#91CEC2`, coral `#EA6E56`, sky `#6FA6D4` | The existing hues already pass AA on dark; replacing them would fork the brand for no measurable gain. |
| 14px card radius, 10px row radius | Off the established radius scale. A presentation theme is not a reason to widen it. |
| Poppins, IBM Plex Mono | Placeholders in the study's own terms. Neue Montreal and the existing data stack replace them. |
| "equal perceptual lightness" claim | Not true of the supplied hues — they span L\* 61.1 to 78.5. Not relied upon. |

**Migration note.** Light-theme colour needs no migration. Two things do:

1. `font.size.base` is now `14px`. Anything that hard-coded `13px` instead of reading the token should be corrected to read the token. Table and metadata text stays `12px` deliberately.
2. `font.size.md` no longer exists. Nothing in the repository referenced it at the time of the change; use `base` for 14px and `lg` for 16px.

Anything building a dark surface must read from `semantic.dark` rather than inverting light tokens by hand. Dark tinted backgrounds and chart fills are alpha washes of the semantic hue, not separate hexes, so the two themes cannot drift apart.

## 21. Dark theme

The dark theme is **the same application on a different ground**. It is not a restyle and not a licence to loosen the rules.

Inherits unchanged from the light theme: the 4px spacing grid, the 14px density, the radius scale, control heights, motion, iconography, layout dimensions, and every semantic meaning in section 5.1.

### 21.1 Surfaces

| Token | Value | Use |
| --- | --- | --- |
| `dark.background.canvas` | `#000000` | Application canvas. Bleeds edge to edge. |
| `dark.background.subtle` | `#0A0B0D` | Recessed, disabled, or de-prioritised blocks. |
| `dark.background.surface` | `#13151A` | The default card, panel and table surface. |
| `dark.background.muted` | `#1E1E1E` | Emphasised row, inline chip, code chip. |

`#13151A` carries a slight blue cast. Keep it. A neutral grey card is what makes a dark interface read as flat black-and-white, and the cast is the cheapest available correction.

### 21.2 Elevation without shadow

Shadows read poorly on dark grounds. On dark, express elevation through the surface step and the border, not through shadow:

- normal card: `dark.background.surface` with a `dark.border.subtle` hairline, no shadow
- emphasised row: step up to `dark.background.muted`, no border change
- menu, popover, dropdown, dialog: `dark.background.muted` with `dark.border.default`, and the corresponding light-theme shadow at most

Do not stack a strong border and a strong shadow.

### 21.3 Primary action inverts

On dark, `dark.action.primaryBackground` is white with black text — the light theme's black-on-white primary inverted. Orange remains the brand accent and is still not the default filled primary button colour. Section 5.1 is unchanged.

### 21.4 Tints are washes, not new colours

Every tinted state background is a low-alpha wash of the semantic hue at roughly 12%, and every chart area fill is the same hue at roughly 32%. Do not introduce a solid hex for a dark tint. This is what keeps the dark theme locked to the light one.

### 21.5 De-prioritised is grey, never red

A paused, dormant or deliberately de-prioritised item uses `dark.foreground.subtle` plus `dark.state.pausedOpacity` (0.5). Never danger red. De-prioritisation is a choice, not a failure — and red is reserved for section 5.1's meaning.

## 22. Presentation theme

For slide decks, printed and exported reports, and customer-facing dashboards where the job is to carry one argument rather than to operate the business. Never for an operational screen.

It uses the dark theme's surfaces, hues and semantics from section 21. Only type, radius and layout differ.

### 22.1 What changes

| Aspect | Application themes | Presentation |
| --- | --- | --- |
| Body text | 14px | 16px |
| Largest text | 36px KPI | 48–56px display |
| Card radius | 12px | 12px — unchanged |
| Content width | 1440px page max | 1120px |
| Density | compact, data-forward | air is deliberate |

**Radius does not change.** The presentation theme inherits the application radius scale — 6px tags, 8px controls, 12px cards and panels, 16–20px large floating surfaces, pill for badges. There is no presentation-specific radius token.

The Ember Dark study specified 14px cards and 10px rows. Both were rejected: they sit off the established scale, and a presentation theme is not a reason to widen it. Where a genuinely large presentation surface wants more curvature, `radius.xl` (16px) is already available under section 8.1 and needs no new value.

Where a row carries a left accent bar, keep square corners on that side and the standard 12px on the other three, exactly as in the application themes.

### 22.2 Type roles

| Role | Family | Size / weight | Tracking |
| --- | --- | --- | --- |
| Eyebrow | data | 12 / 500, uppercase | `0.14em` |
| Display | display | 48–56 / 700 | `-0.025em` |
| Heading | display | 32 / 700 | `-0.02em` |
| Card title | display | 20 / 600 | `-0.015em` |
| Lede | sans | 18 / 400, muted | normal |
| Body | sans | 16 / 400 | normal |
| Data label | data | 13 / 400 | `0.04em` |

Monospace is the system's voice — labels, figures, identifiers, anything machine-ish. It is not a decorative texture. Never set body copy in it, and never set a figure inside a data row in the sans face.

Keep uppercase mono at 11px or above. Below that the tracking stops working and it becomes noise.

### 22.3 Layout

- Split roughly 55 / 40 with the remainder as gutter. Evidence left, argument right. Never centred.
- Margins about 4.5% of width. Content never touches the edge; images may bleed inside their own rounded container.
- Eyebrow, headline, optional one-line lede, then a full empty band before content. The air under the title is doing work — do not close it up.
- A left accent bar is `presentation.layout.barAccent` (3px). Rows with a left bar keep square corners on that side; rounded corners belong only to full borders. The radius itself is the standard 12px.
- Sequence diagrams cap at `presentation.layout.maxSteps` (6). Beyond that, split into two diagrams.
- Ratio bars cap at `presentation.layout.maxRatioSegments` (3).

### 22.4 Discipline

The presentation theme is the one place in ConnectIQ where visual restraint has to be enforced by hand rather than by density. Four rules carry it:

- **Spend the accent once.** One eyebrow plus one focal element per view. Scarcity is what makes orange read as emphasis.
- **Let neutral carry structure.** Roughly 80% of any view should be neutral.
- **Depth before hue.** A fifth series is a deeper fill of an existing hue, not a sixth colour. Section 14's five-colour ceiling still applies.
- **Number only what is ordered.** Numbered steps mean the stages genuinely run in sequence. Do not number a list.

Imagery is desaturated and cool-shifted, inside a rounded container with the canvas visible around it. An ambient wash of the accent at very low opacity may sit behind photography. Nothing else glows, and section 5.4's gradient prohibition is otherwise unchanged.
