Skip to content

Equestrianism design system

Equestrianism is a suite of open-source tools for operating LLMs in production. Each tool is a small, single-binary Go CLI with one job, named after something from horsemanship. The tools have no interface of their own. This design system gives them a shared visual identity for documentation, marketing and any future web surfaces.

The look in brief: parchment and warm ink, British racing green, oxblood and brass, engraved type and hairline rules.


The suite

Tool Name refers to What it is
stirrup the tack that steadies the rider A coding harness for safe autonomous operation: five deterministic safety rings, a pure-function core, a declarative RunConfig, a gRPC control plane, and evals as a first-class peer.
chiron the wise centaur, the teacher The researcher. Drives a Gemini Deep Research agent end-to-end from the CLI and emits a cited, structured Markdown report. Research-only: no shell, no edits.
dressage the discipline of refined training An LLM invocation-log analyser. Fetches provider logs (Bedrock, Azure, Vertex), normalises them, groups them into conversations, and generates a self-contained HTML report.
steeplechase the long course, the fences A lightweight OTLP telemetry router. Receives OpenTelemetry metrics, logs and traces and fans them out to stdout, other OTLP backends or MQTT.
paddock (proposed) the enclosure, turned out to rest The suite's context and memory store: content-addressed blobs, records and semantic recall behind one ContextStore interface.
stint (proposed) a fixed period of work Cost and budget attribution across the suite.

The codebases share a set of conventions: pure-function cores with pluggable backends, secrets never in config, minimal auditable dependencies, OTel-native, air-gapped-friendly, and a single static Go binary per tool.


Sources

The system was built by reading the suite's repositories. They contain no branding or visual assets, so every visual decision here is original to this system. Read the repos when designing for a specific tool:


Content fundamentals

The tools have no UI, so most people meet the brand through its writing.

  • Locale: en-GB. analyse, normalise, visualise, colour, behaviour, air-gapped. Currency is £ (GBP).
  • Register. Precise, dry and declarative, in the manner of good internal engineering documentation. Example from stirrup: "Secret leakage through logs is structurally impossible." Avoid hedged phrasing such as "we help prevent leaks".
  • Tool names are lowercase, set in mono: stirrup, chiron, dressage. They stay lowercase at the start of a sentence. The suite name, Equestrianism, is capitalised.
  • The horse metaphor appears once per tool. Explain the name in one line ("chiron is the wise centaur to stirrup's tack"), then write about the engineering.
  • Person. Describe a tool in the third person ("stirrup runs LLM-produced code…"). Use "you" in usage and how-to material. Use "we" only in philosophy and decision documents; avoid marketing "we".
  • Structure. Tenets as bold lead-ins. Tables for anything enumerable (flags, providers, exit codes). Prefer commas, colons and full stops; use an em-dash only where an aside interrupts the sentence. Inline code for every flag, path, env var and value.
  • Headings name their content: "Executors", "Design principles", "Cost controls". No aphorisms, slogans or "X, not Y" constructions. A hero headline says what the product is.
  • Numbers are exact. "Most under 20 minutes, hard max 60"; "≈ £1.58 (envelope £0.79–£2.37)". Give ranges and envelopes rather than rounded figures, and state costs plainly.
  • No emoji, exclamation marks or hype words ("blazing", "revolutionary", "seamless", "effortless").
  • Don't describe your own precision. Show the exact figure without adding a line saying it is exact.

Say: "Composability via a single declarative RunConfig, allowing easy swapping of components without modifying the loop." Avoid: "Our flexible, powerful config system makes it easy to customise everything! 🚀"


Visual foundations

  • Palette. Pages are parchment with warm-ink text. The brand colours are British racing green (principal), oxblood (secondary), cognac and brass (the metallic accent). Polo navy is for informational tone; signal red is reserved for alarms. Use colour sparingly: most surfaces are parchment, ink and a hairline. Colour also encodes workflow. The --state-* tokens order the lifecycle by how much attention it needs from a person (stone → racing → brass → oxblood → signal), and --decision-* covers approvals. Queued and done share a hue and are distinguished by their mark (guidelines/colors-workflow-states).

  • The seal. The Plate component draws marks from type and rules alone: a double-hairline rectangular plate, or a circular seal with an italic monogram. The brand mark is the inscribed seal (<Plate variant="seal" inscribed />, direction v2 · 2B in explorations/): the E cipher, · EQVESTRIANISM · round the top (classical V for U), FESTINA LENTE round the base, and MMXXVI under the cipher. Below 96px drop the inscription; below 48px drop the date. Use it at most once per page, on a cover or footer, with nothing arranged around it. Roman numerals appear only inside the seal; write 2026 elsewhere. Colophon, a plain mono caption naming the typefaces and locale, is optional and suits long-form documents such as reports.

  • Typography. Three families, each with a role:

    • Cormorant Garamond, a high-contrast old-style serif, for mastheads, headings, report numerals, drop caps and discipline lines.
    • IBM Plex Mono for documentation and marketing body text, labels, code and every literal value.
    • IBM Plex Sans for application chrome only: nav, form labels, table cells, lane headers. It was added when Carousel adopted the system (onboarding/carousel.md, guidelines/type-interface). It shares Plex Mono's skeleton, so it adds a role without a new voice.

    Documentation and marketing body text is mono at line-height 1.62; app chrome uses --lh-ui (1.5) and rows --lh-ui-tight (1.35).

    Headings are Cormorant, upright, sentence case, in one weight and colour, with no italic or coloured accent clause. Labels are sentence-case mono captions (--text-caption, 500, --label-engraved) that label a block of data or a card; they never sit above a section heading. Uppercase tracking is only for table and column headers and the seal inscription. Buttons, nav and links are sentence case. Italic is for emphasis in body text, foreign phrases (festina lente), titles of works, and each tool's discipline line on its card (the tack that steadies the rider). Light numerals (Cormorant 300, large) are for figures that are the content of a report and don't belong in marketing stat rows. The drop cap (.dropcap) opens a product page's lede, once, as part of the marketing surface's heritage styling.

  • Backgrounds. Flat parchment or flat ink. No decorative gradients; a near-flat parchment-to-white on a hero is the limit. If texture is needed, use a faint paper grain or a thin ruled keyline, never a photographic wash. Dark sections use warm ink --ink-900 rather than black.

  • Corners. 2–6px. Pills are only for status dots and tags.

  • Borders. The default edge is a 1px hairline: parchment-300 on light grounds, a gilt hairline rgba(brass, .22) on ink. A thin brass keyline marks the single most important card or the active nav item. Where an ink section meets parchment, use the gilt edge (--edge-gilt), a 1px brass border on the top and bottom. Form controls and outline buttons take --border-control (3:1 on every surface, --border-control-hover on hover); --border-strong is for rules, table headers and hollow rings only.

  • Shadows. Low, warm and ink-tinted. Cards sit on a hairline and --shadow-sm. --shadow-lg is for overlays and dialogs only. Sunken wells use --shadow-inset.

  • Motion. 120–320ms on --ease-standard, with no overshoot or bounce. Fades and short translations only. Under reduced motion, show end states. The drawn-rule animation was retired in September 2026 pending a motion review: <Rule draw> is accepted and ignored, and --dur-ceremony is unused. Don't add scroll-triggered entrances until that review has happened.

  • Hover. Fills deepen one step (racing-700 → racing-900) and filled buttons gain a 1px gilt inner edge. Ghost and quiet elements and interactive cards gain a faint wash (--bg-sunken / parchment-100). Links turn brass. Nothing moves on hover: no lift, scale or growing shadow.

  • Press. A 1px downward nudge (translateY(1px)) and a slightly deeper fill. No shrink transform.

  • Transparency. Limited to the gilt hairline, status-chip tints and dialog scrims (rgba(ink-900,.5)). No backdrop-filter; sticky navs are opaque --nav-bg over a hairline.

  • Imagery. The suite ships no photography. If imagery is used, keep it warm-toned with generous margins and a hairline frame. Prefer set type, rules and the wordmark to stock images.

  • Cards. Parchment or white fill, --radius-md, 1px hairline, --shadow-sm. The feature variant adds a brass keyline along the top.

Light and dark themes

Only the semantic token layer changes between themes; the base colour ramps stay the same. Set data-theme="dark" on <html>, or on any wrapper to theme just that subtree. The dark theme uses warm near-black grounds (#15110B), parchment text, brighter racing green and brass to hold contrast, and darker status and tag tints.

Components read semantic aliases (--bg-surface, --text-primary, --status-*-bg/-fg, --tag-*), so Button, Card, Tag, Badge and Callout switch themes without extra work. New components must use semantic tokens for surfaces, text, borders and tints, never a hardcoded hex. CodeBlock stays on warm ink in both themes. Persist the user's choice in localStorage under eq-theme.


The application register

Since Carousel adopted the system (onboarding/carousel.md) it has served dense, stateful applications as well as documentation. These rules keep the two consistent:

  • One spacing scale. App surfaces use the lower end of it, via --app-pad, --app-gap and the control heights in tokens.json (guidelines/app-density).
  • Type by role. Sans for interface text, mono for literal values, serif for headings (guidelines/type-interface).
  • Distinct feedback states. Skeleton, EmptyState, NotFound, InlineHint and ErrorState are separate components, and a failed read never renders as an empty state (guidelines/app-state-honesty).
  • Nothing important off-screen. Lane and column layouts break out of the reading width and reflow when space runs out; they never hide content behind a scroll (guidelines/app-visibility).
  • Breakpoints: 640 / 900 / 1200 (guidelines/app-responsive).
  • Focus and motion. Every interactive app control takes the brass :focus-visible ring: a solid 2px --focus-shadow, never a translucent halo. Streaming and pulsing surfaces define their reduced-motion behaviour.
  • Theming exceptions for Mermaid (token-to-theme maps in components/app/mermaid-themes.js), sandboxed iframes and syntax highlighting are listed in guidelines/app-theming-exceptions.

Iconography

The codebases ship no icons.

  • Lucide as a stand-in. The system uses Lucide at a 1.5px stroke, loaded from CDN. It is a substitute rather than a brand asset; replace it if the team adopts an official set.
  • Usage. Line icons only, in --text-secondary or --brand at rest, at 18–20px. Use them for navigation, status and actions, not decoration.
  • Prefer type. Where a bold lead-in, a hairline or a keyline would do, use that instead of an icon. Never place icons in tinted tiles beside feature text.
  • No emoji, no coloured or filled icon families, and no unicode dingbats or CSS diamonds as ornaments. A · mid-dot is fine as a separator in metadata.

Guardrails: the September 2026 pattern review

In September 2026 the system was reviewed for generic, template-derived design patterns of the kind that make a page look machine-generated, and those patterns were removed. The review and its before/after examples are in explorations/AI Pattern Review.html. Future sessions must not reintroduce them, including when asked to make a surface "richer", "more premium" or "more on-brand"; add richness through content, type and layout. If a request seems to need one of these patterns, raise it with the user instead of quietly reversing the decision.

Do not reintroduce:

  • Italic or coloured accent clauses in headlines (<h1>Tools for <em>agentic</em> work</h1>). Headings are upright and one colour.
  • Eyebrow labels above section headings, whether uppercase, tracked, brass or otherwise. The heading opens the section.
  • Numbered section labels (01 / 02 / 03, I. II. III., §1). Use ordinals only where order matters, as in install steps and procedures.
  • Aphoristic or slogan headings, and "X, not Y" constructions.
  • Vanity stat rows of small integers on marketing surfaces ("4 tools · 0 secrets"). Show a real command, output or table instead.
  • Hover lift: translateY or growing shadows on cards and links.
  • Three-up feature strips and icons in tinted tiles. Present principles and features as bold lead-ins or ruled rows.
  • Ornament stacks: brass diamonds, dingbats, or a seal surrounded by italic lines and slogans. One mark per page, set alone.
  • Uppercase tracked text as the default for buttons, nav, links or captions.
  • Frosted glass (backdrop-filter).
  • Self-describing copy ("every figure exact", "written like engineering").
  • Scroll-triggered animations, until the motion review says otherwise.

Kept by decision: the drop cap on product-page ledes; the italic discipline lines on tool cards; brass in its current roles (labels, link hover, focus rings, the seal, keylines); light numerals in reports; the seal.

Open for future work: the marketing tool list. The review proposed flattening it into ruled rows; that was rejected as a regression for a marketing page. It stays a card grid, and a future session may make it more elaborate and visually distinctive, provided it stays within the guardrails above (no hover lift, eyebrows over headings, stat rows, ornament stacks or icon tiles).


Logo and mark

There is no drawn logo. The mark is the inscribed seal (Plate variant="seal" inscribed, described above) for covers, footers and avatars. Elsewhere, set the name in type: Equestrianism in Cormorant Garamond, tool names in lowercase IBM Plex Mono. The Wordmark component does this. FESTINA LENTE is a placeholder motto; change it with the motto prop if the team adopts another. If a drawn mark is commissioned, add it under assets/ and replace these.


Fonts

All three families load from Google Fonts via @import in tokens/fonts.css, as agreed at the August 2026 export review. Because the @font-face rules live in Google's stylesheet, the compiler reports "Fonts: none"; this is expected and the fonts do load. For offline or air-gapped use, self-host Cormorant Garamond and the IBM Plex families and replace the @import with local @font-face rules.


Index

Foundations (root):

  • tokens.json: every colour (light and dark), spacing, radius, shadow and type value. tokens.css is generated from it; link it before components/bundle.css.
  • components/bundle.css: global entry point, imports only. Consumers link it after tokens.css.
  • tokens/: fonts.css (the Google Fonts import), plus what tokens.json cannot hold: the transparent state fills in colors.css and the motion values in effects.css. The other sheets keep only their explanatory comments; the originals are in archived/tokens/.
  • guidelines/: specimen cards for type, colour, spacing and brand, plus the application rules: colors-workflow-states, type-interface, app-state-honesty, app-visibility, app-theming-exceptions, app-responsive, app-density.
  • onboarding/carousel.md: the first application adoption, covering the token migration table, the type decision, the currency resolution and Carousel-side fixes.

Core components (components/<Name>/, usage in each README.md):

  • Wordmark · Button · IconButton · Tag · Badge · StatusDot · Callout · Card · CodeBlock · Rule · Plate · Colophon
  • Badge and StatusDot accept workflow state and decision values as well as outcome status; queued renders hollow, done filled.

Application components (components/<Name>/, docs in each <Name>.d.ts):

  • Shell: AppShell
  • Forms: Field · Input · Textarea · Select · Checkbox · Radio · Fieldset · FormActions
  • Feedback states: Skeleton · EmptyState · NotFound · InlineHint · ErrorState
  • Board: Board · Lane
  • Streaming: Transcript
  • Data: DataTable · Estimate · KeyValueList · EntityRow · Stat
  • Decisions and notices: DecisionBar · Dialog · Banner
  • Artifacts: Prose · ArtifactFrame · mermaid-themes.js (token-to-theme maps)
  • Gallery: TaskGrid · TaskCard

Templates (templates/): static, editable starting pages, checked against the kits, for the implementing agent to rebuild from components.

  • marketing-home/: hero with a real command, tool cards, ink design-principles list, footer with the seal.
  • docs-page/: three-column documentation page with side nav, prose, tables, code and a contents rail.
  • app-console/: shell, rail, needs-input banner and five-lane workflow board.
  • app-form/: full form page with fields, hints, a live error, fieldset groups and an action row.
  • report/: self-contained report with a sealed cover, light numerals, tables and a generation footer.

UI kits (ui_kits/):

  • site/: the documentation and marketing site (home → product → docs page), with a persisted dark-mode toggle and ⌘K search over the docs index.
  • app/: a working supervised agent console showing the shell, board, a full form, the approvals review surface, budget tables, a live transcript, and connections with a destructive-action confirm. See its README.md.

Other:

  • assets/notes/SKILL.from-standalone.md: Agent Skills entry point for using this system from Claude Code.
  • explorations/: archived explorations. Includes the two Monogram Directions canvases (v2 · 2B became the inscribed seal) and AI Pattern Review.html, the September 2026 review behind the Guardrails section.

Why these components exist: the source repos define no UI, so every component was written for this system. The core set was sized for the documentation and marketing site; Wordmark, CodeBlock, Callout and Rule are there because technical documentation needs them. The components/app/ layer was added when Carousel, a supervised operational application, adopted the system. Carousel-specific notes live in onboarding/carousel.md.

Set in Cormorant Garamond, IBM Plex Mono and IBM Plex Sans.

@equestrianism/design-system 0.1.0 · Apache License 2.0