| name | Monoscope | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| description | OpenTelemetry-native observability — dense, calm, incident-first. Dark by default with full light parity. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| colors |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| typography |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rounded |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| spacing |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| components |
|
Creative North Star: "The Instrument Panel"
Monoscope is read like a cockpit, not browsed like a website. Its user is an on-call engineer at 3 AM following a shared trace link with an error clock ticking — so the interface behaves like an instrument panel: every readout carries meaning, every color is a gauge rather than paint, and density is a form of respect. The visual system exists to get someone from an alert to a root cause without a single glance being wasted. The emotional target is relief — the feeling of the system finally telling you what happened — never spectacle.
Density is the load-bearing value. Experienced users scan; the waterfall, the log stream, and the field list are packed tight within rows and spaced generously between logical groups so structure reads at a glance. Color is strictly signal: brand blue means clickable, red means error, green means success, service and status hues identify. Where a color has no meaning, no color is used. The reference point is Datadog APM — information-rich, cross-linked, color-as-meaning — but stripped of its glossier edges. Progressive disclosure earns its keep during incidents: summary counts up front, detail one click away, never the exception type buried two clicks deep in a 29-error trace.
The system defaults to dark until the user selects a theme, with full light parity — every semantic token is defined in both themes and verified in both. Shared views are first-class: a link may open on a stranger's phone mid-panic, so every surface must read standalone. This system explicitly rejects playful illustrations and mascots, decorative icons above headings, neon-on-dark, glassmorphism as decoration, gradient text, and cartoony empty states.
Key Characteristics:
- Instrument-panel density: tight within rows, generous between groups.
- Color is signal, never decoration — brand blue for action, semantic hues for state.
- OKLCH semantic-token system with strict light/dark parity.
- Inter for UI and data; JetBrains Mono for code, IDs, and raw telemetry.
- Tonal surfaces + 1px strokes carry depth; shadows are reserved for floating layers.
An OKLCH semantic-token palette organized by role (fill / text / stroke / icon / bg), anchored by a single confident brand blue, with a tightly-controlled semantic set and a categorical series palette for data viz.
- Signal Blue (
oklch(56.7% 0.239 261)): The brand color and the one interactive accent. Used for primary buttons, current selection, focus rings, links, and "clickable" affordances only. In dark mode it lifts tooklch(64% 0.18 261)for contrast. Available asfillBrand-strongand a 12%-alphafillBrand-weakfor selected backgrounds.
- Semantic Error Red (
oklch(51.3% 0.197 21)): Errors, failed spans, 5xx. Paired always with a non-color signal (icon, position, text). - Semantic Warning Amber (
oklch(54.7% 0.126 69)): Degraded state, 4xx, elevated latency. - Semantic Success Green (
oklch(47.8% 0.130 162)): Healthy, resolved, 2xx. - Semantic Information Blue (
oklch(53% 0.16 261)): Informational callouts and the default chart line. It shares the brand hue. Lower chroma and contextual use distinguish information from interaction.
Each semantic color ships -strong (text/icon/border) and -weak (8–12% alpha fill) variants, and each lifts in lightness for dark mode.
- Ink (
oklch(14.4% 0.069 263 / 0.9)):textStrong— primary body and heading text. - Muted Ink (
oklch(16.7% 0.086 263 / 0.84)):textWeak— secondary text, still comfortably above 4.5:1 on base surfaces. - Base Surface (
oklch(98.5% 0.006 261)):bgBase, the cool page canvas. - Raised Surface (
oklch(100% 0 0)):bgRaised, the content plane for tables and charts. - Overlay Surface (
oklch(99.5% 0.004 261)):bgOverlay, reserved for transient top-layer content. - Sunken Surface (
oklch(94.5% 0.014 261)):bgSunken, the strongest recessed plane. - Alternate Surface (
oklch(97% 0.01 261)):bgAlternate, table headers and toolbars. - Strokes:
strokeWeakis decorative. Essential control boundaries usestrokeStrong, which reaches 3:1 against the light canvas.
Dark mode swaps the neutral base to a subtle warm charcoal (bgBase: oklch(12.5% 0.004 260)) with clear surface steps (bgSunken → bgBase → bgRaised → bgOverlay). Decorative dividers and explicitly quiet metadata controls use a 5%-white strokeWeak; essential controls use a quieter 35%-white strokeStrong that still reaches 3:1.
The Signal Rule. Color is signal, not decoration. Brand blue means clickable; red means error; green means success; a service or status hue means identity. If an element carries no meaning, it carries no color — it is neutral ink on a neutral surface.
The Latency Rule. Breakdown color shows where time was spent: the track carries the row's service or span-kind color, and child segments keep their stable dimension colors. Durations from 1s add a warning triangle; durations from 5s add a critical-circle marker without replacing the breakdown palette. Missing duration is an em dash, never a zero-value bar. The numeric duration remains visible in every measured state.
The One-Blue Rule. There is a single blue hue in the system: 261. It carries interaction at full strength and informational state at a lower chroma. Semantic distinction comes from strength, context, and labels, not from a rival hue.
The Contrast Rule. Normal text reaches 4.5:1. Large text, essential control boundaries, focus indicators, and essential data marks reach 3:1. Color-coded state always has a text, icon, shape, or position cue.
Display / Body Font: Inter Variable (with ui-sans-serif, system-ui, sans-serif fallback)
Mono Font: JetBrains Mono (with monospace fallback)
Character: One humanist sans carries the entire UI — headings, labels, body, and dense data — tuned with Inter's OpenType features (ss01, ss02, cv01, cv02, contextual ligatures) for a precise, engineered read. JetBrains Mono is the counter-voice: it appears anywhere the content is machine truth — code, trace/span IDs, raw log lines, JSON, KQL. The pairing contrasts on the humanist-sans / monospace axis, never on two similar sans families.
Type steps come from a fixed rem scale — Tailwind's default ladder extended with two custom small steps — never a fluid clamp(). Product UI is viewed at consistent DPI, so a heading that reflows in a sidebar reads worse, not better. Roles map onto scale steps; the ratio stays tight (~1.125–1.14) because a dense tool has many type elements and exaggerated contrast is noise.
| Step | Size / line-height | Role |
|---|---|---|
text-2xl |
1.5rem / 2rem | Display — page titles (weight 600, -0.01em) |
text-xl |
1.25rem / 1.75rem | Large headings, empty-state titles |
text-lg |
1.125rem / 1.75rem | Headline — panel/section headers (600) |
text-base |
1rem / 1.5rem | Title — card and group headers (600) |
text-sm |
0.875rem / 1.25rem | Body — the workhorse: labels, table cells, prose (400) |
text-xs |
0.75rem / 1rem | Label — field labels, badges, meta, dense data (500) |
text-2xs |
0.625rem / 0.875rem | Caption — micro-labels, chart ticks |
text-3xl–5xl |
1.875–3rem | Reserved — rare hero moments only, not app chrome |
Body is text-sm (0.875rem), not text-base. The everyday UI runs one step below the web default because density is the point; text-base is for the occasional emphasized lead. Prose caps at 65–75ch; dense tables and data may run to 120ch+.
The Machine-Truth Rule. If the content is something a machine emitted verbatim — a span ID, a status code, a log line, a query — it is set in JetBrains Mono at the same text-sm/text-xs steps as its neighbours. Human-authored chrome is Inter. The font tells the reader which is which.
The Fixed-Scale Rule. Every type size is a named step on the scale above. No fluid clamp() headings, no one-off rem values, no separate display typeface. Weight and a chosen scale step create hierarchy; text-3xl and larger are reserved for rare hero moments and never appear in app chrome.
Depth is tonal-first. Surfaces step through a tonal ramp — bgSunken (recessed) → bgBase (content) → bgRaised → bgOverlay — reinforced by hairline 1px strokes, and that tonal layering does most of the structural work. Shadows are reserved for elements that genuinely float above the plane: dropdowns, modals, toasts, popovers. This keeps flat surfaces flat and makes a shadow itself a signal that something is transient and layered.
- shadow-xs (
0 1px 2px -1px rgba(0 0 0 / 0.06)): Badges, subtle chips. - shadow-sm (
0 2px 8px -2px rgba(0 0 0 / 0.08), 0 4px 12px -4px rgba(0 0 0 / 0.04)): Dropdowns, popovers, raised cards. - shadow-md (
0 4px 12px -2px rgba(0 0 0 / 0.12), 0 8px 20px -4px rgba(0 0 0 / 0.08)): Modals, command palette. - shadow-lg (
0 8px 25px -5px rgba(0 0 0 / 0.1), 0 4px 10px -5px rgba(0 0 0 / 0.04)): Highest floating layers. - shadow-toast (
0 4px 12px rgba(0 0 0 / 0.12)): Toast notifications.
Dark mode deepens every step (up to rgba(0 0 0 / 0.6)) so float still reads against charcoal surfaces.
The Float-Only Shadow Rule. A shadow means "this floats above the page." Resting surfaces earn depth from tone and stroke, never from a drop shadow. If a card at rest has a shadow, remove it.
Components feel tactile and confident: standard affordances tuned well, with crisp state feedback and no decoration. Every interactive component defines default, hover, focus, active, disabled, and (where relevant) loading and error. Radii come from the token scale — fields/selectors at 0.4rem, boxes at 1rem.
- Shape: Field radius (
0.4rem). - Primary: Signal-blue fill, white content,
0.5rem 1rempadding. In dark mode, hover drops toopacity: 0.9with astrokeBrand-weakring rather than a lighter fill. - Press feedback: All buttons scale to
0.98on:activeover 75ms — the tactile signature. - Loading: During HTMX requests the button drops to
0.7opacity, disables pointer events, and appends a spinningcurrentColorring — no layout shift, no separate spinner. - Secondary / Ghost: Neutral fill (
fillWeak) or transparent with a hairline stroke; text intextStrong/textWeak.
- Solid (
.badge):fillStrong-family background, inverse text,shadow-xs,rounded-md,text-xs font-medium. - Outline / Ghost: 1px stroke or no fill with
textWeak. Used for status labels and counts; never as decoration.
- Style:
bgBasesurface, 1pxstrokeWeakborder, field radius,0.375rem 0.625rempadding. - Focus: Border shifts to
strokeFocus(Signal Blue) with a matching focus ring — the same blue used for selection, so focus reads as "active." - Error / Disabled: Error uses
strokeErrorplus a non-color signal; disabled drops tofillDisabledwithtextDisabled.
- Style: Inactive tabs use
textWeakon transparent; active state is handled by HTMX morph swaps (no imperative class toggling). Nav tabs preload on hover. - Behavior: Presentational state (open/expand, chevron rotation, selection) is expressed with Tailwind state variants (
peer/group-has-[:checked]), which survive HTMX morph swaps, not hyperscript toggles.
Monoscope's charts are the product's heroes, so color mapping is codified, not ad-hoc:
- Categorical series: a fixed 20-step vivid-boundary palette (500-weight where it clears 3:1 on the light chart surface, otherwise the brightest passing 600-weight value) assigned in order so series stay stable across renders. Dark mode uses the lighter 400-weight family.
- HTTP status → hue: 2xx = blues/greens, 3xx = cyans/teals, 4xx = yellows/oranges, 5xx = reds/pinks. Status color is semantic and consistent everywhere a status appears.
- Percentile → performance gradient: p50 green → p90 amber → p95 orange → p99/p100 harsh red. Latency severity reads as temperature.
State-conveying only, 75–250ms, exponential ease-out (--ease-out-expo, --ease-out-quint) — no bounce, no elastic, no page-load choreography. Legitimate motions: button press (75ms), modal fade-scale-in (150ms), drawer slide (250ms), and staggered list reveals (.stagger-fade, 50ms steps). Every animation collapses to near-instant under prefers-reduced-motion: reduce, which is wired globally.
- Do treat color as signal — brand blue for interaction, semantic hues for state, service/status hues for identity. No meaning, no color.
- Do pack density where power users scan: tight within rows, generous between logical groups.
- Do keep Signal Blue and Information Blue in the same hue-261 family; distinguish their roles with chroma, strength, context, and labels.
- Do set machine-emitted content (IDs, status codes, logs, queries) in JetBrains Mono; human chrome in Inter.
- Do convey depth with tonal surface steps and 1px strokes; reserve shadows for floating layers.
- Do verify every token and every state in both light and dark — dark parity is required, not optional.
- Do give every error state a second signal beyond color (icon, position, shape, text). WCAG AA is the floor.
- Do express presentational state with Tailwind variants (
peer/group-has-[:checked]) so it survives HTMX morphs.
- Don't use playful illustrations, mascots, or decorative icons above headings.
- Don't ship neon-on-dark, glassmorphism as decoration, gradient text, or cartoony empty states.
- Don't add
border-left/border-rightgreater than 1px as a colored accent stripe. - Don't warm the neutral base toward cream/sand — the base is faintly cooled toward the brand hue, never warmed.
- Don't introduce a display font, fluid
clamp()heading, or one-off rem size; every type size is a named step on the scale, and weight + step carry hierarchy. - Don't add a second blue hue. The system has one blue (brand hue 261); "info" is that hue at a lighter weight, not a rival hue — if you reach for another blue, you're drifting.
- Don't put a resting shadow on a card that isn't floating.
- Don't reinvent standard affordances (custom scrollbars, non-standard modals, weird form controls) for flavor.
- Don't reach for a modal as the first thought — exhaust inline and progressive-disclosure alternatives first.