---
brand: iceConnect
system: Slate & Brass
style: Minimal, calm, confident
version: "2.8"
colors:
  slate: "#0F172A"        # dark grounds, body text
  brass: "#C8A35B"        # the single accent — CTAs, key figures (use sparingly)
  steel: "#4E7CA1"        # muted secondary — charts & info only
  offwhite: "#FAFAF8"     # page background
  tint: "#F1F5F9"         # subtle fills
  brasstint: "#F6F3EB"    # callout / highlight panels
  muted: "#64748B"        # secondary text
  border: "#E2E8F0"       # hairlines & dividers
  success: { bg: "#DCFCE7", base: "#22C55E", text: "#15803D" }
  warning: { bg: "#FEF3C7", base: "#D97706", text: "#B45309" }
  error:   { bg: "#FEE2E2", base: "#DC2626", text: "#B91C1C" }
  info:    { bg: "#E8EFF5", base: "#4E7CA1", text: "#3B5F7D" }
typography:
  heading: { fontFamily: "Bricolage Grotesque", weight: 700, use: "titles, headlines, big numbers, hero" }
  body:    { fontFamily: "DM Sans", weight: 400, use: "paragraphs, labels, UI, buttons" }
  scale:   { display: 56, title: 32, heading: 22, subheading: 18, body: 16, small: 14, caption: 11 }
spacing: { base: 8, half: 4, steps: [4, 8, 12, 16, 24, 32, 48, 64] }
radius: { sm: 6, md: 8, lg: 12, xl: 20, full: 9999 }
breakpoint: { sm: 375, md: 768, lg: 1024, xl: 1440 }
zIndex: { base: 0, dropdown: 1000, sticky: 1100, overlay: 1200, modal: 1300, popover: 1400, toast: 1500 }
components:
  button-primary:   { backgroundColor: "#C8A35B", textColor: "#0F172A", rounded: 7, label: "verb, e.g. Set up monitoring" }
  button-secondary: { backgroundColor: "#4E7CA1", textColor: "#FFFFFF", rounded: 7 }
  card:             { backgroundColor: "#FFFFFF", border: "1px solid #E2E8F0", rounded: 12, shadow: "elevation.sm" }
  callout:          { backgroundColor: "#F6F3EB", borderLeft: "3px solid #C8A35B", rounded: 8 }
  input:            { border: "1px solid #E2E8F0", rounded: 7, focusRing: "#C8A35B" }
---

# iceConnect — DESIGN.md · Complete Brand & Build System

> One-paste source of truth for on-brand output — **marketing assets** (decks, pages, adverts) **and product/app UI** (components, screens, apps). Paste this whole file into Claude (or any AI tool), then describe what you need; apply **every** rule below to **all** output, without exception. For "vibe coding", drop this file into your repo as `CLAUDE.md`, `AGENTS.md` or `.cursorrules`.
>
> Latest system & downloadable assets: **https://brand.iceconnect.com**
> Machine-readable tokens: **https://brand.iceconnect.com/dist/tokens.json** · CSS variables: **https://brand.iceconnect.com/dist/theme.css**
>
> The six sections below (Overview · Colors · Typography · Elevation · Components · Do's and Don'ts) are the canonical spec; the appendices carry agent recipes, responsive/performance, navigation & forms, asset rules and services. The `tokens.json` block at the end is machine-readable and auto-generated — never hand-edit it.

---

## Overview

iceConnect — UK Managed Service Provider (MSP). "Twenty years of innovation." We deliver IT support, cyber security, cloud, communications and AI services to small and mid-sized UK businesses.

- Offices: London HQ (Finchley), Chelmsford, Johannesburg.
- Strapline style: "Reliable. Scalable. Secure."
- Audience: business owners and managers — **NOT** IT specialists. They buy outcomes (uptime, security, predictable monthly cost), never technology for its own sake.
- Web www.iceconnect.com · Email hello@iceconnect.com · Tel 020 3358 0000 · Support portal support.iceconnect.com

**House style — the brand in three words: minimal, calm, confident.** Slate-dominant, brass used sparingly, generous whitespace, restrained motion, plain language. We look like a trusted advisor, not a loud vendor. **Never use emoji as icons or decoration** — use Lucide line icons only (see Appendix D).

**ICP firmographic:** 30–200 staff, regulated/process-heavy sectors. Primary: financial services (wealth managers, insurance brokers, corporate finance, IFAs, accountancy). Secondary: dental, manufacturing, logistics.

**Personas (canonical set):** Overwhelmed Self-Manager · Dissatisfied Customer · Post-Incident Survivor · Ambitious Scaler · Strategic Augmenter.

**How to use this file:** read top-to-bottom; the rules compound. Reference design tokens by ROLE (Appendix E), never raw hex in components. Ship light AND dark. Every asset gets ONE clear call to action. UK English, £ GBP, absolute ISO dates (e.g. 2026-06-24).

### Services — ten pillars

Use these names exactly; every asset speaks to at least one.

1. **IT Support** — day-to-day support that keeps people productive (service desk & remote support, onsite, on/offboarding, device deployment, hardware procurement, asset management, RMM, patch management, vendor management)
2. **Cyber Security** — protection for people, devices and data (EDR/XDR, MDR, 24/7 SOC, email security & anti-phishing, DNS/web filtering, MFA & conditional access, identity & PAM, awareness training, dark-web monitoring)
3. **Governance, Risk & Compliance** — proving and maintaining security posture (vulnerability management, pen testing, DLP, Cyber Essentials & Plus, GDPR & data protection, data governance, risk assessments, audits, policy support)
4. **Microsoft 365 & Productivity** — helping teams work better together (licensing & optimisation, tenant management, Exchange Online, Teams, SharePoint & OneDrive, email migration, training)
5. **Cloud & Infrastructure** — the platforms everything runs on (Azure & AWS, private & hybrid cloud, hosting & co-location, virtualisation, server & storage, infrastructure design, monitoring, migration, capacity planning)
6. **Network & On-Premise Infrastructure** — the on-site backbone (switching & LAN/WAN, Wi-Fi & guest networks, managed routers & firewalls, structured cabling, network design & monitoring, site surveys)
7. **Communications & Connectivity** — voice and connectivity (business internet & leased lines, SD-WAN, VoIP & hosted telephony/SIP, Teams Calling, contact centre, call recording, auto attendants, business mobiles, continuity telephony)
8. **Backup & Business Continuity** — confidence you can recover from anything (M365 backup, server & endpoint backup, cloud backup, disaster recovery, continuity planning, recovery testing, ransomware recovery, high availability)
9. **AI & Automation** — emerging technology put to work (Copilot adoption, AI readiness assessments, AI governance & security, process automation, Power Automate, chatbots, knowledge management, custom AI)
10. **Strategy & Projects** — guidance and delivery for what comes next (vCIO/CIO services, IT roadmaps, technology & budget planning, digital transformation, project delivery & migrations, office moves, M&A support, due diligence)

---

## Colors

Reference by role, never raw hex in components (Appendix E). The palette is slate-led; brass is the single accent.

### Core (hex · RGB · CMYK · Pantone)

| Token | Hex | RGB | CMYK | Pantone | Role |
|---|---|---|---|---|---|
| slate | `#0F172A` | 15,23,42 | 64,45,0,84 | 5255 C | dark grounds, body text |
| brass | `#C8A35B` | 200,163,91 | 0,18,55,22 | 4006 C | THE single accent: CTAs, highlights, key figures. Use sparingly. |
| steel | `#4E7CA1` | 78,124,161 | 52,23,0,37 | 5415 C | muted secondary: charts & info only |
| offwhite | `#FAFAF8` | 250,250,248 | — | — | page background |
| tint | `#F1F5F9` | 241,245,249 | — | — | subtle fills / alternating bands |
| brasstint | `#F6F3EB` | 246,243,235 | — | — | callout & highlight panel fills |
| muted | `#64748B` | 100,116,139 | — | — | secondary text |
| border | `#E2E8F0` | 226,232,240 | — | — | hairlines & dividers |

### Supporting (UI status states ONLY)

Never decorative, never in headings, CTAs, illustrations or backgrounds. Each status is a SET: tint background · base (icon/fill) · text (AA on white). Never use the base hue as text — use the text shade for words.

- success — bg `#DCFCE7` · base `#22C55E` · text `#15803D`
- warning — bg `#FEF3C7` · base `#D97706` · text `#B45309` (deeper than brass — never confuse)
- error — bg `#FEE2E2` · base `#DC2626` · text `#B91C1C`
- info — bg `#E8EFF5` · base `#4E7CA1` · text `#3B5F7D`

### Colour rules

- **60/30/10** — 60% slate & neutrals / 30% steel & supporting / 10% brass.
- Approved pairings: white on slate · slate on brass · slate on off-white · white on steel.
- **NEVER white text on brass** — brass is light; always slate text on brass fills, including buttons.
- For print, hand the CMYK/Pantone values to the printer — never auto-convert from RGB.

### Data visualisation (charts, dashboards, reports — decks AND product UI)

Keep series muted to match the brand; apply via your charting library's theme.

- categorical (use IN ORDER — steel & brass lead): `#4E7CA1` steel · `#C8A35B` brass · `#4F9D8C` teal · `#8C6A93` plum · `#C0795B` clay · `#64748B` slate. Past six series, group the tail into "Other" or rethink the chart.
- sequential (one measure low→high, single-hue steel): `#ECF2F7` · `#C2D5E3` · `#8FB1CB` · `#5E8BAC` · `#3B5F7D`
- diverging (around a midpoint; status red/green ends): `#B91C1C` · `#F2B8B8` · `#F1F5F9` (neutral midpoint) · `#A7E3BE` · `#15803D`
- In-chart status: success `#22C55E` · warning `#D97706` · error `#DC2626`.
- ALWAYS pair colour with a second cue (label, value or pattern) so charts read for colour-blind users and in greyscale. Dark mode: re-theme the chrome (gridlines, axes, background) — keep the series colours fixed. Use tabular figures for numbers.

---

## Typography

Both fonts are free on Google Fonts.

- Headings: `Bricolage Grotesque` Bold — titles, headlines, big numbers, hero only.
- Body: `DM Sans` Regular/Bold — paragraphs, labels, captions, UI text, buttons.
- NEVER use optical-size variants (e.g. "DM Sans 14pt") — plain family names only.
- NEVER set body copy in Bricolage Grotesque; never use the heading font below 18px.
- Line-height: headings tight (0.95–1.0×); body 1.2–1.3× (print) / 1.5 (screen).
- Left-align everything except cover and section titles. Never centre body copy.

**Print / deck scale (points):** Display/Hero 54–60pt Bricolage Bold · H1 30pt · H2 18–20pt · Body 11–14pt DM Sans · Caption 9–10pt tracked uppercase.

**Screen scale (rem on 16px base; iOS pt & Android sp use the same numbers):**

| Style | Font · weight | Size | Line-height | Notes |
|---|---|---|---|---|
| Display / Hero | Bricolage 800 | 56px / 3.5rem | 1.0 | -0.02em |
| Title · H1 | Bricolage 700 | 32px / 2rem | 1.05 | -0.01em |
| Heading · H2 | Bricolage 700 | 22px / 1.375rem | 1.1 | |
| Subheading · H3 | Bricolage 700 | 18px / 1.125rem | 1.25 | |
| Body Large | DM Sans 400 | 18px | 1.55 | |
| Body | DM Sans 400 | 16px | 1.5 | base |
| Body Small | DM Sans 400 | 14px | 1.45 | helper text |
| Label | DM Sans 600 | 13px | 1.3 | |
| Caption | DM Sans 600 | 11px | — | 0.12em UPPERCASE |
| Pill / Badge | DM Sans 600 | 12px | 1.0 | status & metadata labels |

Use tabular/monospaced figures for data columns, prices and timers. On Android use sp (never dp); on iOS map to Dynamic Type styles.

---

## Elevation

The depth-and-rhythm primitives: spacing, radius, elevation, layering and motion. All on an 8px base.

### Spacing

8px base, 4px half-step: `4 · 8 · 12 · 16 · 24 · 32 · 48 · 64`. Page margins: 24px web, 0.85in slides. Section rhythm tiers: 16 / 24 / 32 / 48. Generous whitespace; align to a consistent left edge.

### Radius

sm 6 (controls, inputs) · md 8 (buttons) · lg 12 (cards) · xl 20 (panels) · full 9999 (pills, avatars).

### Elevation (shadow)

Soft slate shadows on a consistent scale — never random values.

- `elevation.sm` `0 1px 2px rgba(15,23,42,0.06)` — inputs, chips
- `elevation.md` `0 2px 8px rgba(15,23,42,0.08)` — cards, popovers
- `elevation.lg` `0 8px 24px rgba(15,23,42,0.12)` — modals, sheets

**In dark mode, shadows mostly disappear — separate surfaces with a `border.default` hairline instead of elevation.**

### Layering (z-index)

One scale, seven named tiers — overlapping surfaces never fight. Stay on the scale; never invent ad-hoc values like `z-index: 9999`.

| Tier | z | Use |
|---|---|---|
| base | 0 | page content, normal flow |
| dropdown | 1000 | menus, selects, comboboxes |
| sticky | 1100 | sticky headers & toolbars |
| overlay | 1200 | modal scrim / backdrop |
| modal | 1300 | dialogs & sheets |
| popover | 1400 | popovers & tooltips |
| toast | 1500 | transient alerts — above all |

### Motion

- duration — fast 120ms (hovers, toggles) · base 180ms (most transitions) · slow 280ms (modals, drawers)
- easing — `cubic-bezier(0.2,0,0,1)` for entrances/moves; linear only for spinners. Exit ~60–70% of enter duration.
- micro-interactions 150–300ms; animate transform/opacity only; always honour `prefers-reduced-motion` (drop non-essential animation to instant).
- **pulse** — a single named looping primitive (2.4s ease-out infinite): an expanding `box-shadow` ring radiating from a live status dot (colour inherits from status), fading by 70% then resting. Pure CSS, no JS; honour reduced-motion.

---

## Components

Build each core component once, with every state, and reuse everywhere. Reference tokens by role.

### Spec tables (Default / Hover / Active / Focus / Disabled)

Exact values are the `component.*` group in `tokens.json` and ship as `.ic-*` classes in `theme.css`; `build-tokens.py --check` keeps them identical to the live demos on the page, so these specs can't drift.

**Primary button** (`.ic-btn .ic-btn--primary` · `component.button`) — brass fill, slate label (white fails contrast on brass).

| Property | Default | Hover | Active | Focus | Disabled |
|---|---|---|---|---|---|
| Background | brass `#C8A35B` | `#BC9550` | `#B89149` | brass | brass @ 40% |
| Text | slate | slate | slate | slate | slate @ 40% |
| Ring | — | — | — | 2px brass, 2px offset | — |

Hover values are for light surfaces; on **dark** surfaces hover LIGHTENS instead — `action.primary-hover` (dark) = `#D4B373`.

**Geometry (all buttons):** radius **7px** · DM Sans **700** · padding md **11×20**, sm **8×14** (`.ic-btn--sm`), lg **14×26** (`.ic-btn--lg`) · font md 14 / sm 12.5 / lg 15px · disabled 40% opacity.

**Secondary button** (`.ic-btn--secondary`) — steel `#4E7CA1` fill, white label; hover `#456E8E`. **Ghost** (`.ic-btn--ghost`) — transparent, slate text, 1px `#E2E8F0` border; hover tint (`#F1F5F9`) fill.

**Card** (`.ic-card` · `component.card`) — white fill, 1px `#E2E8F0` border, `elevation.sm`, radius **12**, padding **24**. The core content container.

**Callout** (`.ic-callout` · `component.callout`) — brasstint fill + **3px** brass left border, radius **8**, padding **16×20**.

**Input** (`.ic-field` · `component.input`) — white fill, 1px `#E2E8F0` border, radius **7**, padding **10×13**. States: default · focus (brass border + **3px** brass-tint ring) · error (red border + 3px red-tint ring `rgba(220,38,38,0.12)`) · disabled (tint fill, muted text). Min height ≥**44px** on mobile.

### Status indicators — pills, banners & live dots

Built from the supporting-colour SET (tint bg · base · AA text). Always pair colour with an icon or text so the state reads in greyscale and for colour-blind users.

- **Status pill** — compact inline state: a pill (radius full) with 1px border, short label and a status-coloured dot. Light surfaces: white fill, hairline border, muted text. Dark surfaces: translucent white fill/border, light text. For live/real-time states (uptime, recording, monitoring) the dot uses the **pulse**. Examples: "All systems operational", "Certificate expiring", "Agent offline".
- **Status banner** — inline message: a box filled with the status **bg** tint, a matching status icon, a bold title and a line of detail, text in the status **text** shade. One state per banner.
- Ready-made CSS ships in `theme.css` (`.ic-pill`, `.ic-banner--*`, `.ic-dot`). Reference by role (`status.success | warning | error | info`), never raw hex.

### Forms & validation

Always a visible label (never placeholder-only). Mark required fields (asterisk). Helper text below the input. Validate on blur, not on keystroke. Put the error message beside the field with both an icon and words ("Choose a band so we can tailor your quote", not "Invalid input"). Use semantic input types (email, tel, number) for the right mobile keyboard; show/hide toggle on password fields; autofill attributes on. After a submit error, move focus to the first invalid field.

### Empty & loading states

- **Empty state** — never a blank panel: an icon, a short title, one line of context, and ONE clear next action ("No tickets yet → Raise your first ticket").
- **Loading** — for loads over ~300ms show a **skeleton** (shimmer placeholders that reserve the final layout so nothing shifts — keep CLS < 0.1), not a blocking spinner. Skeleton shimmer honours `prefers-reduced-motion`.

### Navigation (see Appendix C for full patterns)

Current location always marked with a brass indicator and slate weight; everything else muted until hovered or active. **Active-indicator by surface:** top-bar links & tabs use a **brass underline** (2px links, 3px tabs); sidebar rows & mega-menu items use a **brass-tint fill + a 2px brass left-edge line that follows the corner radius** (inset box-shadow, so it curves with rounded corners and never shifts the text). One primary action per bar. Icons always carry a text label — never icon-only. Patterns: top bar (wide), **mega-menu** (multi-column top-bar dropdown for deep catalogues), tabs (within a page), breadcrumb (3+ levels deep), sidebar (app shells ≥1024px, collapsible groups), mobile (top bar + burger overlay, bottom tabs ≤5).

### Microcopy

Buttons are verbs ("Set up monitoring", "Download report"). Errors say what happened + the fix. Empty states give one next action. Labels are plain ("Work email"). Never vague buttons ("Submit", "OK", "Click here"), raw codes ("Error 0x80004005"), or shouting ("INVALID INPUT!!!").

### Spacing & component rhythm

8px base; multiples of 8 for padding/gaps/section spacing. Cards and panels breathe — generous inner padding. Don't cram; don't centre body copy.

---

## Do's and Don'ts

### Voice — the audience runs businesses; they are NOT IT specialists

Sound like: plain English a busy owner understands at a glance · confident and reassuring ("we've got this handled") · benefit before technology · warm and human, like a trusted advisor · specific and honest over vague or salesy.

NEVER: acronym-stuffed, boastful or hyped, cold/corporate/robotic, patronising, or vague ("solutions", "synergy", "best-in-class").

Say this, not that:
- "keep your systems running" NOT "maximise uptime / high availability"
- "protect your business" NOT "endpoint threat mitigation"
- "back up your data" NOT "immutable backup architecture"
- "we'll set it up for you" NOT "seamless deployment & onboarding"
- "help when you need it" NOT "24/7 SLA-backed support tiers"

Example rewrite —
- BAD: "Our proactive RMM platform leverages enterprise-grade SIEM and EDR to deliver best-in-class threat remediation across your entire estate."
- GOOD: "We watch over your computers around the clock and stop most problems before you'd ever notice them — so your team can just get on with work."

### Do

- Tie every asset to a campaign, offer, CTA and KPI before producing it. One clear CTA per asset.
- Let slate and neutrals dominate; use brass sparingly; slate text on every brass fill.
- Bricolage Grotesque headings / DM Sans body — nothing else.
- Reference tokens by role; ship light AND dark; visible focus ring + ≥44px / 48dp tap target on every control.
- UK English, £ GBP, absolute ISO dates.

### Don't

- Don't set white text on brass, or use supporting colours decoratively (status only, with the AA text shade for words).
- **Don't use emoji as icons** — Lucide line icons only.
- Don't generate, redraw or recolour the logo — use the supplied files (Appendix D).
- Don't centre body copy, invent off-scale spacing/z-index, or remove focus rings without replacing them.
- Don't produce "content" with no campaign, offer and measurable conversion path attached.

### Output checklist — verify before you finish

- [ ] UK English, £ GBP, absolute ISO dates (e.g. 2026-06-24)
- [ ] Slate dominant, brass sparing, slate text on every brass fill
- [ ] Bricolage Grotesque headings / DM Sans body — nothing else
- [ ] Lucide line icons only (no emoji); logo from supplied files, never generated, ≥120px wide
- [ ] Supporting colours used for status only, with the AA text shade for any words
- [ ] Charts: brand palette in order, colour paired with a label/value, readable in greyscale
- [ ] One clear call to action per asset
- [ ] Every sentence understandable by a non-technical business owner
- [ ] Product: every token referenced by role, light AND dark both handled
- [ ] Product: visible focus ring + ≥44px / 48dp tap target on every control; mobile-first at 375/768/1024/1440
- [ ] z-index on the named scale; skeletons for >300ms loads; CLS < 0.1

---

## Appendix A — Agent prompts (paste-ready recipes)

Load this file first, then add one recipe. Each is a complete brief — role, audience persona, structure, the single CTA and the output format. Swap the service, sector and CTA to retarget. (Bigger builds like a full landing page or product dashboard deserve their own considered brief, not a one-paragraph recipe.)

**Email sequence** — "Act as a lifecycle copywriter for iceConnect. Write a 3-email onboarding sequence for a newly-signed managed-IT client (ops lead at a 30–200-staff firm, time-poor, non-technical): (1) welcome + what happens next, (2) meet your service desk + how to raise a ticket, (3) your first 30-day review. One CTA per email; subject + preview line. Voice: warm, plain English, benefit before tech. UK spelling; £. Deliver text, then an HTML version in DM Sans, slate text on white, a single brass button per email."

**Review deck** — "Act as a strategy consultant. Build a 5-slide quarterly business review deck: where we started → what we did → results (the hero number) → risks handled → what's next. One idea per slide, one chart max. Bricolage headings, DM Sans body, left-aligned (centre only the cover); slate grounds with brass on the single key figure per slide; charts in the categorical palette, paired with labels. Tabular numbers; UK English; ISO dates. Output self-contained HTML slides importing theme.css, with keyboard navigation and a progress bar."

**Social ad** — "Act as a paid-social creative director. Produce a LinkedIn single-image ad (1200×1200) for our Backup & Business Continuity service. Audience: finance-sector ops leaders worried about ransomware. 3 concepts, each with headline (≤7 words, outcome-led), one-line subhead and a layout note. Text under 20% of area; critical content in the central 80% safe zone. Slate background, one brass accent, Bricolage headline / DM Sans subhead, the iceConnect logo on a slate scrim, one Lucide icon. No emoji, no stock clichés. CTA: 'Test your recovery plan'. Output HTML/CSS at exact 1200×1200."

**Case study** — "Act as a B2B content designer. Write a one-page case study in Challenge → Solution → Results structure. Subject: a wealth-management firm we moved off ageing on-prem IT. Audience: similar finance-sector firms (the 'Ambitious Scaler'). 3 quantified results as big Bricolage figures (brass), one client pull-quote, and a 'services used' list mapped to our ten pillars. Voice: specific and honest, benefit before tech. CTA: 'Book a 20-minute IT health check'. Output a responsive HTML one-pager using theme.css tokens, light + dark, print-friendly."

---

## Appendix B — Responsive & performance

### Breakpoints (mobile-first min-widths)

`sm 375` (phone) · `md 768` (tablet) · `lg 1024` (laptop) · `xl 1440` (desktop). Design for the narrowest screen first, then layer enhancements up at each min-width. No horizontal scroll, no fixed-px containers; keep a consistent desktop max-width. Large screens (≥1024px) prefer a sidebar; small screens use top bar + bottom nav.

### Performance essentials

- **Fonts** — `font-display: swap` on every face so text is never invisible while loading; preload only the two we use.
- **Photos** — serve as WebP/AVIF with `srcset` and `loading="lazy"` below the fold. Logos and icons stay **SVG** — never rasterise the mark.
- **Layout stability** — set `width`/`height` or `aspect-ratio` and reserve space for async content; keep CLS < 0.1.
- **Perceived speed** — skeletons for loads over ~300ms, not blocking spinners; defer non-critical scripts; split by route. Input latency < 100ms; tap feedback within 100ms.

---

## Appendix C — Navigation & forms (detail)

### Navigation patterns

The same brass-active discipline across every layout. Hover lifts muted links to slate; current location is brass + slate weight.

- **Top bar** — primary navigation for the marketing site and wide layouts: logo left, links centre/left (one active, 2px brass underline), one primary CTA (brass) right.
- **Mega-menu** — a multi-column dropdown hung off a top-bar link for deep catalogues (e.g. Services): white panel, soft shadow, radius 14, column headers in muted caps. Active item = brass-tint fill + a **2px brass left-edge line that follows the corner radius** (inset box-shadow). Equal padding around the panel edge and between columns. Click to open; outside-click closes.
- **Tabs** — switch between views inside one page or record; active tab has a 3px brass underline sitting on a hairline baseline track (so the line never collides with a rounded corner).
- **Breadcrumb** — orientation once a hierarchy is 3+ levels deep; last item is the current page (slate, no link).
- **Sidebar** — app shells & dashboards on ≥1024px: a padded card of icon+label rows; the active row gets a brass-tint fill, brass icon and a **2px brass left-edge line that follows the row's corner radius**; groups are collapsible `<details>` sections with headers in muted caps; equal whitespace above and below the logo.
- **Mobile** — a real-width frame (~300px+): top bar with logo + an interactive burger that morphs to an X and slides in a full-height overlay menu (with a collapsible sub-menu for Services and a brass CTA), plus a bottom tab bar of ≤5 icon+label items (active icon brass). Never nest sub-navigation in the bottom bar.

Rules: navigation placement stays the same across pages; don't mix tab + sidebar + bottom nav at one hierarchy level; current location always visually highlighted; back behaviour predictable (preserve scroll/state); all key screens reachable by URL/deep link; separate destructive actions from normal nav.

### Forms & feedback (detail)

Visible label per input; required indicator; persistent helper text below complex inputs; validate on blur; error below the field with icon + words + a recovery path; group related fields; mark read-only distinct from disabled (disabled = reduced opacity 0.38–0.5 + no action). Multi-step flows show a step indicator and allow back. Long forms auto-save drafts; confirm before dismissing a sheet with unsaved changes. Toasts auto-dismiss in 3–5s, don't steal focus, use `aria-live="polite"`. Confirm before destructive actions; offer undo for bulk/destructive actions.

---

## Appendix D — Logo, icons & photography

### Logo — never generate, redraw or re-export it; use the supplied files only

Four-colour circular "C" mark (blue/orange/lime, magenta centre) + lowercase "iceconnect" wordmark — grey wordmark on light grounds, white on dark.

Files: the `/assets/logo/` folder is **not browsable** — never guess a filename or generate the mark. Exact paths under `https://brand.iceconnect.com/` (SVG is the primary web format):

- Full logo, light ground → `assets/logo/svg/iceconnect-logo-light-bg.svg`
- Full logo, dark ground → `assets/logo/svg/iceconnect-logo-dark-bg.svg`
- Full logo, one-colour → `assets/logo/svg/iceconnect-logo-mono-black.svg` (on light) / `...-mono-white.svg` (on dark)
- Icon only, the "C" mark → `assets/logo/svg/iceconnect-icon.svg` (+ `...-icon-mono-black.svg` / `...-icon-mono-white.svg`)
- Favicon / app icons → `assets/logo/favicon/iceconnect-favicon.svg` (+ `-32.png`, `-64.png`), `assets/logo/png/apple-touch-icon.png`, `web-app-icon-192.png`, `web-app-icon-512.png`, `maskable-icon-512.png`
- Other formats, same base names: `png/<name>-<size>.png` (full logo 300/600/1200, icon 128/256/512/1024) · `pdf/<name>.pdf` · `eps/<name>.eps` (print). Previews: `https://brand.iceconnect.com/#logo-downloads`

Place ONLY on slate, off-white or white. NEVER on brass, steel, any colour fill, or a busy photo without a slate scrim. Clear space = height of the "i" on all sides. Minimum 120px wide on screen / 25mm in print — smaller, use the icon-only mark. Never stretch, recolour, rotate, add effects, or rebuild in another font. SVG is primary web format; PNG only as fallback.

### Icons

Lucide line icons ONLY (lucide.dev) — never filled/solid, never mixed sets, never multi-colour, **never emoji**. ~1.75px stroke. Slate by default; brass for ONE key highlight per layout.

- Working set: users · server · gauge · triangle-alert · headset · shield-half · scale · app-window · cloud · network · phone · database · bot · target · circle-check · chart-line · clock-4 · pound-sterling · lock · trending-up · handshake · map-pin
- Pillar pairings: 01 headset · 02 shield-half · 03 scale · 04 app-window · 05 cloud · 06 network · 07 phone · 08 database · 09 bot · 10 target
- List bullets: small brass circle-check — not dashes, not dots.
- Packages: `lucide-react` (web) / `lucide-react-native` (mobile).

### Photography

Premium, calm, real: real people in real UK workplaces, natural light, shallow depth of field, uncluttered compositions with breathing room, cool slightly desaturated grade that sits with slate. Brand tone where needed: subtle slate overlay or light brass highlight.

AVOID: cheesy handshake/headset stock, harsh saturated colour, server-room clichés, heavy filters, busy backgrounds behind logos, staged or low-res images.

---

## Appendix E — Design tokens (by role), platform & accessibility

### Reference tokens by ROLE, never raw hex

- text.primary / text.secondary / text.inverse / text.on-accent
- bg.page / bg.surface / bg.muted / bg.inverse · border.default / border.strong
- action.primary (brass, slate label) / action.secondary (steel, white label)
- focus.ring (brass) · status.success | warning | error | info

Ship light AND dark — swap the semantic layer; in dark mode separate surfaces with border.default, not shadow. Full machine-readable values are in the `tokens.json` block below (also at https://brand.iceconnect.com/dist/tokens.json). Ready-to-paste CSS variables are in `theme.css` (`var(--ic-*)`).

### Component states (apps)

Build every control with default / hover / active / focus / disabled. Primary = brass + slate label · secondary = steel + white · ghost = bordered. Brass buttons darken on hover/active but keep slate text: hover `#BC9550`, active `#B89149` (on dark surfaces hover lightens to `#D4B373` instead). Steel darkens to `#456E8E` on hover. Inputs show focus (brass ring) & error (red).

### Accessibility (WCAG 2.2 AA — non-negotiable)

- Contrast 4.5:1 for normal text (3:1 large/UI glyphs); test light and dark independently.
- Visible focus ring on every control · tap targets ≥44px iOS / 48dp Android.
- Pair every status colour with an icon or text · label every input & icon-only button.
- Sequential heading hierarchy (no level skips) · skip-to-content link · keyboard nav matches visual order.
- Respect `prefers-reduced-motion` · brass & steel are accents, NOT text on light grounds.

### Platform

Honour native conventions (iOS HIG / Android Material / web) for layout, navigation & gestures — apply iceConnect colour, type, icons & voice on top.

---

## tokens.json (machine-readable — W3C / Style Dictionary format)

<!-- GENERATED from dist/tokens.json by tools/build-tokens.py — do NOT edit the JSON block below by hand.
     Edit dist/tokens.json, then run: python3 tools/build-tokens.py  (see tools/BUILD.md) -->

```json
{
  "color": {
    "primitive": {
      "slate":        { "value": "#0F172A" },
      "slate-800":    { "value": "#1E293B" },
      "slate-700":    { "value": "#334155" },
      "slate-600":    { "value": "#475569" },
      "slate-500":    { "value": "#64748B" },
      "slate-300":    { "value": "#CBD5E1" },
      "slate-200":    { "value": "#E2E8F0" },
      "slate-100":    { "value": "#F1F5F9" },
      "offwhite":     { "value": "#FAFAF8" },
      "white":        { "value": "#FFFFFF" },
      "brass":        { "value": "#C8A35B" },
      "brass-hover":  { "value": "#BC9550" },
      "brass-hover-dark": { "value": "#D4B373", "comment": "hover on dark surfaces LIGHTENS brass (light surfaces darken it)" },
      "brass-active": { "value": "#B89149" },
      "brass-tint":   { "value": "#F6F3EB" },
      "steel":        { "value": "#4E7CA1" },
      "steel-hover":  { "value": "#456E8E" },
      "success":      { "value": "#22C55E" },
      "warning":      { "value": "#D97706" },
      "error":        { "value": "#DC2626" }
    },
    "semantic": {
      "light": {
        "text-primary":           { "value": "{color.primitive.slate}" },
        "text-secondary":         { "value": "{color.primitive.slate-500}" },
        "text-inverse":           { "value": "{color.primitive.white}" },
        "text-on-accent":         { "value": "{color.primitive.slate}" },
        "bg-page":                { "value": "{color.primitive.offwhite}" },
        "bg-surface":             { "value": "{color.primitive.white}" },
        "bg-muted":               { "value": "{color.primitive.slate-100}" },
        "bg-accent":              { "value": "{color.primitive.brass-tint}" },
        "bg-inverse":             { "value": "{color.primitive.slate}" },
        "border-default":         { "value": "{color.primitive.slate-200}" },
        "border-strong":          { "value": "{color.primitive.slate-300}" },
        "action-primary":         { "value": "{color.primitive.brass}" },
        "action-primary-hover":   { "value": "{color.primitive.brass-hover}" },
        "action-primary-active":  { "value": "{color.primitive.brass-active}" },
        "action-primary-text":    { "value": "{color.primitive.slate}" },
        "action-secondary":       { "value": "{color.primitive.steel}" },
        "action-secondary-hover": { "value": "{color.primitive.steel-hover}" },
        "action-secondary-text":  { "value": "{color.primitive.white}" },
        "focus-ring":             { "value": "{color.primitive.brass}" }
      },
      "dark": {
        "text-primary":           { "value": "{color.primitive.slate-100}" },
        "text-secondary":         { "value": "#94A3B8" },
        "text-inverse":           { "value": "{color.primitive.slate}" },
        "text-on-accent":         { "value": "{color.primitive.slate}" },
        "bg-page":                { "value": "{color.primitive.slate}" },
        "bg-surface":             { "value": "{color.primitive.slate-800}" },
        "bg-muted":               { "value": "{color.primitive.slate-700}" },
        "bg-accent":              { "value": "{color.primitive.slate-700}" },
        "bg-inverse":             { "value": "{color.primitive.offwhite}" },
        "border-default":         { "value": "{color.primitive.slate-700}" },
        "border-strong":          { "value": "{color.primitive.slate-600}" },
        "action-primary":         { "value": "{color.primitive.brass}" },
        "action-primary-hover":   { "value": "{color.primitive.brass-hover-dark}" },
        "action-primary-active":  { "value": "{color.primitive.brass-active}" },
        "action-primary-text":    { "value": "{color.primitive.slate}" },
        "action-secondary":       { "value": "{color.primitive.steel}" },
        "action-secondary-hover": { "value": "{color.primitive.steel-hover}" },
        "action-secondary-text":  { "value": "{color.primitive.white}" },
        "focus-ring":             { "value": "{color.primitive.brass}" }
      }
    },
    "status": {
      "success": { "bg": { "value": "#DCFCE7" }, "base": { "value": "#22C55E" }, "text": { "value": "#15803D" } },
      "warning": { "bg": { "value": "#FEF3C7" }, "base": { "value": "#D97706" }, "text": { "value": "#B45309" } },
      "error":   { "bg": { "value": "#FEE2E2" }, "base": { "value": "#DC2626" }, "text": { "value": "#B91C1C" } },
      "info":    { "bg": { "value": "#E8EFF5" }, "base": { "value": "#4E7CA1" }, "text": { "value": "#3B5F7D" } }
    },
    "chart": {
      "categorical": { "value": ["#4E7CA1", "#C8A35B", "#4F9D8C", "#8C6A93", "#C0795B", "#64748B"] },
      "sequential":  { "value": ["#ECF2F7", "#C2D5E3", "#8FB1CB", "#5E8BAC", "#3B5F7D"] },
      "diverging":   { "value": ["#B91C1C", "#F2B8B8", "#F1F5F9", "#A7E3BE", "#15803D"] }
    }
  },
  "font": {
    "family":     { "heading": { "value": "Bricolage Grotesque" }, "body": { "value": "DM Sans" } },
    "weight":     { "regular": { "value": "400" }, "medium": { "value": "500" }, "semibold": { "value": "600" }, "bold": { "value": "700" }, "extrabold": { "value": "800" } },
    "size":       { "display": { "value": "56px" }, "title": { "value": "32px" }, "heading": { "value": "22px" }, "subheading": { "value": "18px" }, "body": { "value": "16px" }, "small": { "value": "14px" }, "caption": { "value": "11px" } },
    "lineHeight": { "display": { "value": "0.95" }, "heading": { "value": "1.0" }, "body": { "value": "1.3" } }
  },
  "space":  { "2xs": { "value": "4px" }, "xs": { "value": "8px" }, "sm": { "value": "12px" }, "md": { "value": "16px" }, "lg": { "value": "24px" }, "xl": { "value": "32px" }, "2xl": { "value": "48px" }, "3xl": { "value": "64px" } },
  "radius": { "sm": { "value": "6px" }, "md": { "value": "8px" }, "lg": { "value": "12px" }, "xl": { "value": "20px" }, "full": { "value": "9999px" } },
  "breakpoint": { "sm": { "value": "375px" }, "md": { "value": "768px" }, "lg": { "value": "1024px" }, "xl": { "value": "1440px" } },
  "zIndex": { "base": { "value": "0" }, "dropdown": { "value": "1000" }, "sticky": { "value": "1100" }, "overlay": { "value": "1200" }, "modal": { "value": "1300" }, "popover": { "value": "1400" }, "toast": { "value": "1500" } },
  "elevation": {
    "sm": { "value": "0 1px 2px rgba(15,23,42,0.06)" },
    "md": { "value": "0 2px 8px rgba(15,23,42,0.08)" },
    "lg": { "value": "0 8px 24px rgba(15,23,42,0.12)" }
  },
  "motion": {
    "duration": { "fast": { "value": "120ms" }, "base": { "value": "180ms" }, "slow": { "value": "280ms" } },
    "easing":   { "value": "cubic-bezier(0.2,0,0,1)" },
    "pulse": {
      "duration":   { "value": "2.4s" },
      "easing":     { "value": "ease-out" },
      "iteration":  { "value": "infinite" },
      "ring": {
        "start": { "spread": { "value": "0 0 0 0" },   "alpha": { "value": "0.7" } },
        "end":   { "spread": { "value": "0 0 0 8px" }, "alpha": { "value": "0" } },
        "fadeBy":{ "value": "70%", "comment": "ring fully expanded & faded by 70% of the loop; remaining 30% is a rest beat" }
      },
      "comment": { "value": "Expanding box-shadow ring that radiates from a live/active status dot and fades, then rests before repeating. Colour inherits from the status the element carries. Pure CSS; honour prefers-reduced-motion." }
    }
  },
  "component": {
    "_comment": "Exact specs for the reusable brand components — the single source of truth that index.html, theme.css (.ic-* classes) and DESIGN.md spec tables all derive from. Colours reference primitives/semantics; dimensions are literal and checked against index.html by build-tokens.py.",
    "button": {
      "radius":        { "value": "7px" },
      "font-size":     { "value": "14px" },
      "font-weight":   { "value": "700" },
      "padding":       { "value": "11px 20px" },
      "padding-sm":    { "value": "8px 14px" },
      "font-size-sm":  { "value": "12.5px" },
      "padding-lg":    { "value": "14px 26px" },
      "font-size-lg":  { "value": "15px" },
      "focus-outline": { "value": "2px" },
      "focus-offset":  { "value": "2px" },
      "disabled-opacity": { "value": "0.4" },
      "primary":   { "bg": { "value": "{color.primitive.brass}" }, "text": { "value": "{color.primitive.slate}" }, "bg-hover": { "value": "{color.primitive.brass-hover}" }, "bg-active": { "value": "{color.primitive.brass-active}" } },
      "secondary": { "bg": { "value": "{color.primitive.steel}" }, "text": { "value": "{color.primitive.white}" }, "bg-hover": { "value": "{color.primitive.steel-hover}" } },
      "ghost":     { "bg": { "value": "transparent" }, "text": { "value": "{color.primitive.slate}" }, "border": { "value": "{color.primitive.slate-200}" }, "bg-hover": { "value": "{color.primitive.slate-100}" } }
    },
    "input": {
      "radius":       { "value": "7px" },
      "padding":      { "value": "10px 13px" },
      "font-size":    { "value": "14px" },
      "min-height-touch": { "value": "44px", "comment": "minimum tap target on mobile" },
      "ring-width":   { "value": "3px" },
      "focus-border": { "value": "{color.primitive.brass}" },
      "focus-ring":   { "value": "{color.primitive.brass-tint}" },
      "error-border": { "value": "{color.primitive.error}" },
      "error-ring":   { "value": "rgba(220,38,38,0.12)" }
    },
    "card": {
      "radius":       { "value": "12px" },
      "padding":      { "value": "24px" },
      "border-width": { "value": "1px" },
      "border":       { "value": "{color.primitive.slate-200}" },
      "bg":           { "value": "{color.primitive.white}" },
      "shadow":       { "value": "{elevation.sm}" }
    },
    "callout": {
      "radius":       { "value": "8px" },
      "padding":      { "value": "16px 20px" },
      "border-left":  { "value": "3px" },
      "border-color": { "value": "{color.primitive.brass}" },
      "bg":           { "value": "{color.primitive.brass-tint}" }
    },
    "pill": {
      "radius":      { "value": "9999px" },
      "padding":     { "value": "9px 17px 9px 15px" },
      "gap":         { "value": "10px" },
      "dot-size":    { "value": "9px" },
      "font-size":   { "value": "11px" },
      "font-weight": { "value": "500" }
    },
    "banner": {
      "radius":      { "value": "10px" },
      "padding":     { "value": "13px 15px" },
      "gap":         { "value": "11px" },
      "font-size":   { "value": "13.5px" }
    },
    "skeleton": {
      "radius":           { "value": "6px" },
      "shimmer-duration": { "value": "1.4s" },
      "base":             { "value": "{color.primitive.slate-100}" },
      "highlight":        { "value": "#E9EEF3" }
    },
    "nav": {
      "_comment": "Active-location indicator by surface — see DESIGN.md Appendix C.",
      "active-line":      { "value": "2px", "comment": "brass left-edge line on sidebar rows & mega-menu items; follows corner radius via inset box-shadow" },
      "active-underline": { "value": "2px", "comment": "brass underline on top-bar links & tabs" },
      "active-bg":        { "value": "{color.primitive.brass-tint}" },
      "tab-underline":    { "value": "3px" }
    }
  }
}
```
