Design philosophy

Make the right thing easy and the wrong thing hard.

Justin's users operate in stressful, critical situations where outcomes depend on getting things right. Every rule below serves that one goal: guide people toward successful actions and make mistakes difficult to make.

HTML first, CSS second, JavaScript last

Native elements before custom widgets: <details> for disclosure, <dialog> for modals, <select> for dropdowns. Modern CSS (:has(), light-dark(), container queries) before reaching for JavaScript. JavaScript only when HTML and CSS demonstrably can't do the job.

A stack of three layers: a wide HTML base carries a narrower CSS layer, with a small JavaScript layer on top — the wider the layer, the more of the job it should do.JavaScriptlast resortCSSmodern selectors and statesHTMLnative elements first
The lower in the stack a solution lives, the less there is to break: native elements bring keyboard handling, focus, and semantics for free.

Tokens are the source of truth

Colors, spacing, typography, radii, shadows: one shared vocabulary, expressed as CSS custom properties on the web and Kotlin objects in Compose. No hardcoded design values anywhere in component code — a component asks for a role, never a raw value.

One box of design tokens branches into two outputs: CSS custom properties for Svelte and Kotlin theme objects for KMP.Design tokensone definition per color, type, spacing, radiusSvelte--color-primaryCSS custom propertiesKMPcolorScheme.primaryKotlin theme objects
One vocabulary, two idiomatic outputs — the same role name resolves on both platforms. The generation step is planned, not built yet — both platforms maintain their token files by hand today. One JSON source: PRD-2278; Style Dictionary generation: PRD-2284.

The rest of the rules

  • Accessibility is a default, not a feature

    Every component ships with semantic markup, keyboard navigation, sufficient contrast, focus indication, and respect for prefers-reduced-motion and prefers-color-scheme. Accessibility is part of "done", not part of "later".

  • Material 3 Expressive

    Justin's vocabulary derives from Material 3 Expressive — color roles, type scale, motion easing, surface containers. Familiar to any Material consumer, customised to Davidhorn's brand.

  • Two platforms, one feel

    A button in Capture (KMP) and a button in Ark (Svelte) use the same color role, the same corner radius, the same spacing. Either codebase looks like the same product.