Brand & UI/UX
Locked design direction: Neumorphism (soft UI). The interface is built from a single tinted surface, with depth created entirely by paired soft shadows — a light highlight top-left, a darker shadow bottom-right. Elements that are actionable or elevated are raised (extruded out of the surface); inputs, active states, progress tracks and wells are inset (pressed into it). Both a light and a dark theme ship first-class.
Visual reference (canonical): three working single-file mockups with mock data —
Dashboard ·
Compliance ·
Findings.
Open any of them and use the moon/sun toggle (top bar) to switch light ↔ dark. These files are the source of truth for the look; this page is the rulebook behind them. Brand assets live in C:/Users/PC/Downloads/ (logo.png, set_icons_transparent.png, S.E.T Platform Pitch Deck.pdf).
Aesthetic
Neumorphic enterprise — soft, tactile, calm. One continuous surface; no hard borders, no card outlines, no drop-shadow "floating" cards. Separation and hierarchy come from the shadow model alone. Layout stays exec-friendly: generous whitespace, large readable numbers, status pills, gentle motion. No SOC-analyst density on summary screens. If a power-user / operator audience emerges later, ship a separate "Operator" view rather than degrading the exec experience.
Neumorphism's known weakness is low contrast — soft same-surface controls can be hard to perceive. S.E.T deliberately counters this: text and semantic status colors always meet WCAG AA, interactive elements get a visible affordance, and state is never signalled by shadow alone (see Accessibility discipline). The softness lives in the surfaces; the data stays legible.
Themes (both first-class)
- Light — default. Base surface
#E6E7EE(a soft lavender-grey, not pure white — pure white cannot show a white highlight). Premium, trustworthy first impression. - Dark — toggleable. Base surface
#24262F, tuned so the tonal gap between the dark shadow and light highlight stays perceptible (the main reason naïve neumorphism fails in dark mode). Command-center feel without aggression. - Theme preference persists per user. Both modes are defined as CSS-variable token sets and swap at the
:root/html.darklevel.
The depth model (the core of the system)
Everything is one of three elevation roles. Nothing floats with an outer drop shadow; nothing has a border.
| Role | Meaning | Used for |
|---|---|---|
| Raised | Extruded out of the surface | Cards, the sidebar panel, buttons, KPI tiles, icon chips, the outer posture ring |
| Inset | Pressed into the surface | Search fields, the active nav item, tabs, progress tracks, badges/pills, list "wells", the posture-ring core |
| Pressed (transient) | Momentary push-in | :active on any raised control; hover raises, click presses |
CSS recipe (Tailwind v4 CSS variables; the mockups implement exactly this):
:root{ /* LIGHT */
--bg:#E6E7EE; --sd:#BEC0CC; --sl:#FFFFFF; /* surface, shadow-dark, highlight */
--text-1:#3A3D55; --text-2:#767B96; /* primary / muted text */
--accent:#7B2FFF; /* brand violet */
--dist:6px; --blur:14px; --radius:20px;
}
html.dark{ /* DARK */
--bg:#24262F; --sd:#1B1D24; --sl:#2E313C;
--text-1:#E7E8F0; --text-2:#9A9EB4;
--accent:#A277FF;
}
.neu { background:var(--bg); border-radius:var(--radius);
box-shadow: var(--dist) var(--dist) var(--blur) var(--sd),
calc(var(--dist)*-1) calc(var(--dist)*-1) var(--blur) var(--sl); }
.neu-inset { background:var(--bg); border-radius:14px;
box-shadow: inset 5px 5px 10px var(--sd), inset -5px -5px 10px var(--sl); }
.neu-press { transition:box-shadow .18s, transform .18s; }
.neu-press:hover { box-shadow: 8px 8px 18px var(--sd), -8px -8px 18px var(--sl); }
.neu-press:active { box-shadow: inset 4px 4px 9px var(--sd), inset -4px -4px 9px var(--sl); }
Discipline rules:
- One light source, always top-left. Highlight is up-left, shadow is down-right, on every element, in both themes. Never mix directions.
- The element shares the page's background color. Depth is shadow, not fill. A card is not "white on grey" — it is the same grey, lifted.
- No borders, ever. If you reach for a
1pxborder, you're fighting the system — use elevation instead. (The one exception: a hairlinecolor-mixseparator between dense table rows, where inset-per-row would be too heavy.) - Distinct radii by role — card/panel 20px, tile/button 14px, pill 999px. Consistent shadow physics, varied radius, reads as designed.
- Signature primitive: the neumorphic posture ring — a raised outer ring → inset inner well → the score numeral. It replaces the earlier 3D "posture orb" and is repeated at login, onboarding, and the dashboard hero. It carries the brand; everything else stays quiet.
3D treatment
Pure neumorphism supplies the product's depth, so no WebGL / live 3D runs inside the app — dashboards, lists, cards, and modals are all shadow-based. Optional brand 3D moments are permitted only on the login/marketing splash (separate perf budget), lazy-loaded, prefers-reduced-motion-aware, with a pre-rendered static fallback. The AI-assistant avatar is a small neumorphic pulsing chip, not a 3D scene.
Component Library
- Base UI: shadcn/ui (Radix primitives + Tailwind) — copy-paste, owned in-repo. Components are re-skinned to the neumorphic token set (the raised/inset/pressed classes above) rather than shadcn's default bordered look.
- Dashboard primitives: Tremor — KPI tiles, charts, sparklines, gauges, themed onto the neumorphic surface (recessed chart wells, no card borders).
- Styling: Tailwind v4 with CSS variables for theme switching.
- Icons: Lucide stroke icons, seated in small raised neumorphic chips; one custom gradient SVG mark (the hex shield) as the brand logo.
Typography
- UI / body: Switzer (Indian Type Foundry, free via Fontshare, commercial OK).
- Code / IDs / numerals: IBM Plex Mono (IBM, free via Google Fonts, OFL).
The reference mockups use Geist + JetBrains Mono as near-identical stand-ins (both are clean geometric grotesque / mono pairs). Production stays on the locked Switzer + IBM Plex Mono from the Tech Stack — the switch is visually negligible.
Mono usage rule (validated against Stripe, Linear, Vercel, Vanta, Mercury, Ramp):
Use mono ONLY when character-by-character identity matters — i.e., the user might copy, diff, type, or read it aloud as a code.
Mono allowed: asset IDs (i-0abc12d7f), control codes (CC6.1), CVEs, hashes, IPs/CIDRs, file paths, big KPI numerals, log lines. Mono forbidden: trend indicators, timestamp captions, prose-like metadata — those use Switzer with font-variant-numeric: tabular-nums and a muted color (--text-2).
Navigation Pattern
Raised neumorphic sidebar panel; active item pressed in. The sidebar is a single raised neu panel. Each nav item is a neu-press row: it lifts slightly on hover and the active item sits inset (pressed into the panel) with violet label + icon. The reference mockups show the full-label state.
The slim hover-expand rail behavior is retained as an interaction option: collapsed ~68px icon-only rail → expands to ~240px on mouse-enter (150ms delay) → flyout popovers for items with sub-pages. Built on shadcn Sidebar + Radix Popover, both re-skinned neumorphic.
Accessibility / touch fallbacks: touch taps open a full drawer (no hover-expand on touch); keyboard focus expands the rail and opens the focused item's flyout; flyouts stay open while the pointer is in the icon OR the menu.
Dashboard Density Philosophy
Summary-first, narrative-led. The landing dashboard shows:
- Hero posture ring (raised ring → inset well → big editorial numeral).
- Asymmetric KPI grid (e.g. hero + 2×3 tiles) — not a symmetric 4-up strip.
- "What needs your attention" — a calm list of inset action-item wells, not a table.
No dense data tables on the landing. Click into any tile for the detail view — those may be operator-grade dense (see the Findings screen's soft table).
Color Discipline
Monochrome surfaces, restrained accent, high-contrast status. The whole UI is one grey surface in soft relief. Color appears only where it earns attention:
- Violet accent (
--accent) — active nav/tab label, primary CTA text, the brand mark, links, the posture-ring accent. 1–2 accented actions per screen. - Semantic colors — success/warning/danger/info for KPI values, status pills, severity, trend arrows, and the small "status dot" (a colored dot with a soft outer glow ring). These are kept saturated and high-contrast on purpose — non-technical users must read critical status instantly, so status colour is the one place softness yields to legibility.
Color Tokens
Surface & text
LIGHT DARK
bg (surface) #E6E7EE #24262F
shadow-dark #BEC0CC #1B1D24
highlight #FFFFFF #2E313C
text-1 #3A3D55 #E7E8F0
text-2 (muted) #767B96 #9A9EB4
accent (violet) #7B2FFF #A277FF
accent-soft #EDE7FF #312B4A
Semantic (tuned per theme for contrast on the grey surface)
LIGHT DARK
critical #E5484D #FF6166
high #F2760C #FF9038
medium #E0A800 #FFC53D
low #C4A700 #E9C93B
info #3E7BFA #5B8DEF
success #12A150 #3DD68C
seafoam #0F9B6E #3DD6A0
Motion Language
"Calm/effortless" — motion communicates state, never decorates. No bouncy springs. The characteristic neumorphic motion is the raise↔press shadow transition on interaction.
| Element | Duration | Easing |
|---|---|---|
| Hover raise / press-in | 180ms | ease |
| Card lift on hover | 200ms | ease |
| Sidebar expand on hover | 200ms | cubic-bezier(0.4, 0, 0.2, 1) |
| Card / modal enter | 250ms | ease-out |
| Theme swap (light↔dark) | 350ms | ease (background + color) |
| Page transitions (optional) | 300ms | fade only, no slide |
| Loading states | 1.5s pulse loop | skeleton (recessed shimmer) — never spinners |
prefers-reduced-motion | 80ms or instant | honored |
Accessibility discipline (non-negotiable for neumorphism)
Neumorphism's soft, same-surface controls are the design's biggest accessibility risk. Rules that ship on every screen:
- Text contrast ≥ WCAG AA —
--text-1on--bgclears 4.5:1 in both themes; muted--text-2is reserved for non-essential metadata only. - State is never shadow-only — active/selected/disabled always pair the inset/raised cue with colour + label/icon (e.g. active nav = inset and violet). A user who can't perceive the soft shadow still gets the state.
- Visible focus — a solid
2px--accentfocus ring (offset2px) on every interactive element; never removed. - Interactive affordance — anything clickable is a
neu-press(it visibly lifts on hover / presses on click), so "is this a button?" is answerable. - Semantic status stays saturated — severity/status colours do not get softened into the surface.
- Tested with
@axe-core/playwrightin CI (see Testing & QA); automated axe catches ~a third of issues, so a periodic manual keyboard/contrast pass is required too.
Anti-generic discipline
Patterns that keep the design reading as crafted, not templated:
- Consistent shadow physics, varied radius — one light direction everywhere; distinct radii by role (panel 20 / tile 14 / pill 999).
- Lived-in mock data —
87.3%not87%,1,247 assetsnot100, real timestamps (Tue 03:17 UTC), real-sounding tenants (Aldera Health) and people (tomer.h). - Asymmetric layouts — hero + 2×3 KPI, not a symmetric 4-up strip.
- Editorial numerals — one large mono display number per screen (the posture score) with a tiny muted caption beneath.
- Restraint — accent violet on only 1–2 actions per screen; the softness carries everything else.
Reference Implementation
The rules above are wired together in the three canonical mockups — each a single self-contained HTML file with mock data and a working light/dark toggle:
- Dashboard — hero posture ring, asymmetric KPI grid, recent findings + top-risk systems.
- Compliance — framework cards with recessed progress tracks, inset status badges, activity wells.
- Findings — KPI tiles, neumorphic filter bar, and the soft table pattern (press-in rows, hairline separators).
Share these files with developers as the canonical visual reference alongside this spec.