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:
- stirrup: https://github.com/rxbynerd/stirrup (
docs/philosophy.md,docs/architecture.md,docs/safety-rings.md) - chiron: https://github.com/rxbynerd/chiron (
docs/PROPOSAL.md,docs/PADDOCK.md) - dressage: https://github.com/rxbynerd/dressage (its self-contained HTML report is the only visual surface)
- steeplechase: https://github.com/rxbynerd/steeplechase
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
codefor 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
Platecomponent 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 inexplorations/): the E cipher,· EQVESTRIANISM ·round the top (classical V for U),FESTINA LENTEround the base, andMMXXVIunder 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; write2026elsewhere.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 (Cormorant300, 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-900rather 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-hoveron hover);--border-strongis for rules, table headers and hollow rings only.Shadows. Low, warm and ink-tinted. Cards sit on a hairline and
--shadow-sm.--shadow-lgis for overlays and dialogs only. Sunken wells use--shadow-inset.Motion.
120–320mson--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-ceremonyis 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)). Nobackdrop-filter; sticky navs are opaque--nav-bgover 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-gapand the control heights intokens.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,InlineHintandErrorStateare 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-visiblering: 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 inguidelines/app-theming-exceptions.
Iconography
The codebases ship no icons.
- Lucide as a stand-in. The system uses Lucide at a
1.5pxstroke, 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-secondaryor--brandat 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:
translateYor 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.cssis generated from it; link it beforecomponents/bundle.css.components/bundle.css: global entry point, imports only. Consumers link it aftertokens.css.tokens/:fonts.css(the Google Fonts import), plus whattokens.jsoncannot hold: thetransparentstate fills incolors.cssand the motion values ineffects.css. The other sheets keep only their explanatory comments; the originals are inarchived/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·ColophonBadgeandStatusDotaccept workflowstateanddecisionvalues as well as outcomestatus; 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 itsREADME.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) andAI 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.