Defender Design

Shared visual system for every Defender module. One source of truth for color, type, motion, and the core primitives that should look identical wherever they appear.

v1 · stable

Quickstart

Drop into the top of any embed's <head>. No build step, no npm, no version pinning to manage. Update once at the CDN, propagates everywhere.

<!-- Both tokens and primitives: --> <link rel="stylesheet" href="https://design.defender-cdn.app/design/v1/all.css"> <!-- Or load them separately for finer control: --> <link rel="stylesheet" href="https://design.defender-cdn.app/design/v1/tokens.css"> <link rel="stylesheet" href="https://design.defender-cdn.app/design/v1/primitives.css">

Colors

Primary actions are slate. Blue and amber are decorative-only — focus rings, status dots, chart accents, never primary buttons.

Brand & action

#3b4652
--slate-pri
primary buttons
#45505c
--slate-pri-h
primary hover
#63aaff
--blue
accents, focus, links
#63aaff
--accent
→ var(--blue): brand accent
#fbbf24
--amber
warnings, required-field dot

Status

#4ade80
--green
up / success
#f87171
--red
down / critical
#3c4756
--inert
unmapped / unknown

Surfaces & text

#171717
--bg
primary surface
#1c1c1c
--surface
cards, panels
#222
--surface-2
hover, elevated
#f5f5f5
--t1
primary text
#a3a3a3
--t3
muted text

Typography

Inter for everything readable. JetBrains Mono only for values that are data (IPs, MAC addresses, IDs, code, monitor IDs).

3xl / 28Asset Health Metrics
2xl / 22Page heading
xl / 18Section title
lg / 15Card heading
md / 13 (base)Body text — Inter regular, the base size.
sm / 12Muted helper text and meta.
mono192.168.1.42 · 572208000000475080

Loaders — never spinners

Pulsing dots only. Default 9px for section-level loading; 6px small variant for inline use.

Default · .boot-pulse
Small · .boot-pulse.boot-pulse-sm
<div class="boot-pulse"> <span></span><span></span><span></span> </div>

Entrance — .stage

Staggered fade-up. Mark each child with .stage and an inline style="--d:N" for the stagger index. Reload the page to replay.

1. First card
2. Second card
3. Third card
4. Fourth card
<div class="card stage" style="--d:1"></div> <div class="card stage" style="--d:2"></div> // Cap at ~8 children — past that the stagger reads as slow. // IMPORTANT: don't add a second style= attribute. HTML5 drops it silently. // Merge into one: style="--d:4; margin-bottom:14px"

Buttons

Primary = slate, always. "Update" not "Edit". Danger sparingly.

Segmented controls

View toggles and range pickers. Default view always on the LEFT.

Status pills

Semantic colors only. Don't invent new pill colors — pick the closest semantic.

Up Down Trouble Active Unmapped Neutral

Cards & grids

Default card grid: repeat(auto-fill, minmax(280px, 1fr)). Use .card-soft for tinted variants.

CPU
42%
15-min average
Memory
68%
15-min average
Disk
71%
15-min average

Empty & error states

Always styled placeholders. Never an empty chart canvas.

No data in range
This asset hasn't reported metrics during the selected window. Try a wider range, or check the monitor configuration.

Section header pattern

Title on the left, actions on the right. Wraps gracefully on narrow iframes.

Comments

12 total · 3 unread

Forms

Field wrappers, labels, inputs, selects, textareas, checkboxes, radios. Required fields use a small amber dot, never an asterisk. Error state is a red left border + .error-text below — never red-flood the whole field.

Used in nav, exports, and the asset directory.
Format must be 6 hex pairs separated by colons.
https:// :443

Tabs

Section-internal navigation. Use .segmented for binary or 2–3 view toggles; use .tabs when there's a list of distinct sub-views.

Tags & chips

Freeform labels (group names, owners, categories). Distinct from .pill which is reserved for status. Tags don't carry a leading dot.

North Campus Owner: Laura B. Pending intake v2 hardware Reviewed Pending update Decommissioned
Lobby — Building 12 CRISPR Wing v1.4.2 beta

Status dots

A small standalone colored dot — useful when a full status pill would be visually heavy (e.g. inside a dense table row or next to a label).

Operational Degraded Offline In review Unmapped Live

KPI tiles

One number per tile. Use a .card wrapper plus .kpi contents. Deltas are semantic — up/down — the module decides which direction is good.

Active monitors
142
+8 this week
Open alerts
3
−5 vs. yesterday
Uptime, 30d
99.94%
no change
Avg. response
128ms
Drill into trace →

Tables

For simple data tables. Tabulator remains the right pick for filtering / column reordering / heavy interactivity.

Monitor Type Status Avg. response Uptime 7d
MIT-Lobby-Cam-04 HTTPS Up 98 ms 100.0%
MIT-Stair-Cam-12 PING Trouble 412 ms 98.2%
MIT-Server-Rack-A SERVER Down 87.4%
MIT-Garage-Cam-09 HTTPS Unmapped

Compact variant for dense readouts:

FieldValue
IP address10.42.18.204
MACa4:5e:60:38:bc:1c
Firmware10.12.149
Last seen2026-05-22T00:48:11Z

Definition lists

Label : value pairs. Horizontal by default — use .dl-stack when labels are long or narrow viewports demand it.

Site MIT — Stata Center Building 32 Floor 2 Owner Laura Bunt Installed 2025-09-14 Last serviced not yet
IP 10.42.18.204 MAC a4:5e:60:38:bc:1c Monitor ID 5688410000000401

Progress bars

Set percentage via style="--p:62" — no unit. Color modifiers map to semantic states.

Commissioning checklist12 / 18
Disk usage71%
Memory94%
Importing — indeterminate

Skeleton placeholders

Use .boot-pulse when you have nothing to show yet. Use skeletons when the page chrome is already laid out and you're waiting for the content shape.

Avatars

Circle with initials or image. Set background tint via --c. Use a stack for crowded contexts (assignees, recent commenters).

MI LB JK DR AB MI LB JK
MI LB JK +4

Toolbar

Utility bar between the section header and the content — search, density toggle, group-by, CSV export.

Density

Banners

Inline status messages at the top of a section. Use for prolonged states ("Read-only mode — your role can't update monitors"). Use toasts for transient feedback after writes.

Drawer

Inline side panel — replaces a region of the section rather than overlaying the whole viewport. Sections render inside Glide iframes, so fixed-fullscreen overlays don't behave correctly. The module decides the layout (split, stacked, or animated slide-in within a relative parent).

Monitor list
…the section's primary content sits here while the drawer is open.

Popover & menu

Anchored panels — the module positions them relative to a trigger. Use .popover for confirm prompts, hints, mini-forms. Use .menu for action lists.

Delete this monitor?
It will be removed from the asset's active checks. History is preserved.

Tooltips

CSS-only — set the message on data-tt. Default direction is up; modifiers are tt-down, tt-left, tt-right.

Up 128 ms trace →

Toasts

Transient feedback after writes. Module mounts a .toasts container inside the section (absolute, anchored bottom-right by default) and appends .toast children. Auto-dismiss is the module's responsibility.

…section content…
Saved
Threshold profile updated for 12 monitors.
Couldn't save
The upstream service didn't respond. Try again.
Importing 142 monitors — this may take a minute.