Sheet A-01 / 04
Design systemsMichelangelo
Picasso keeps the skeleton. Michelangelo provides the skin.
Tellius had a working React component library and a product that looked like eleven different products. Michelangelo is a token layer that re-skins the whole surface without asking engineering to rewrite a single component.
- Client
- Tellius
- Product
- AI analytics: Vizpads, Kaiya chat, Missions
- Year
- 2026
- Scope
- 47 component sets · 52 primitives · 54 icons · 30 chart types
- Role
- Sole designer, token system and skin
- Team
- With the Picasso engineering team
Impact at a glance
- semantic tokens, replacing direct palette references
- 116
- stroke colours consolidated
- 226 → 3
- inline styles removed
- 338
- chart types restyled
- 30
The situation
Tellius ships an analytics platform: dashboards its users call Vizpads, a chat assistant called Kaiya, and scheduled jobs called Missions. The React library behind it, Picasso, was healthy. The surface was not.
Screens built in different quarters had drifted apart. Stroke colour alone had sprawled to 226 distinct values, none of them named. A refresh was wanted. A rewrite was not on any roadmap.
From the docs
Picasso keeps the skeleton. Michelangelo provides the skin.
That sentence is the constraint. Michelangelo may change how a component looks. Never what it is, what it is called, or the props an engineer writes.
Before and after
Before · Kaiya as it ships
After · the same screen on Michelangelo
- The type changes. The heading takes the display serif; everything else moves onto the named text styles.
- The colour changes. Blue accent and unrelated icon tints become one primary role and a tinted set bound to the visualisation tokens.
- The rail collapses to icons, which is the only structural move in the frame, and it was made by the product team, not by the skin.
- Nothing else moves. Card size, gutter, corner radius, control height, pager placement and the button on the right are all untouched.
Only fonts and colour move
Type and colour were in scope. Geometry was not.
- The button is the same button: 32px, same padding, same radius, four levels, five states, three sizes. Only what the states resolve to changed.
- Disabled became a flat token instead of an opacity, because opacity fades an icon and its label by different amounts and the control looks broken.
- Every change stayed reviewable. A colour move reads in a minute; a padding move is a layout change and an argument.
The span ladder in one line: 888 heading, 736 assistant body, 584 user bubble, 432 chart card, 280 prompt card, 204 filter. Prose stops at ten of the twelve columns, so answer text never runs the full width.
Two collections, one direction of travel
Values flow one way. Primitives are hidden from publishing, the semantic collection aliases them, and components bind semantic tokens only. Never a primitive, never a raw hex.
Hiding the primitives is what makes the rest enforceable. A visible palette gets bound directly, by someone, in a hurry, and breaks silently when retuned. The 116 semantic tokens each name a job, so the picker teaches the rule.

Colour, role by role
The board reads as the thought process:
- Text has six steps because an analytics screen has six levels of voice, from a metric value down to a disabled hint.
- Surface separates
hoverfromselected. Pointed at and chosen are different statements; before this file they were the same grey. - Border is four roles, because 226 stroke values collapsed into hairline, divider and ink, plus focus.
- The violet accent means interactive: six states of one hue, not six hues.
Data visualisation is its own colour system
An analytics product lives or dies on its charts, so the visualisation palette is its own token family, built to answer three different questions.
Twelve categorical series in a fixed order, and the order is the spec: series five is the same hue on every chart ever drawn. Measures bind meaning, not position. Revenue owns a colour, so two charts about revenue agree.
The icon layer
Icons are where a system falls apart, because nobody audits them. The audit found 338 inline vector copies pasted across the file.
Stroke weight resolves to stroke/icon, the canvas to the size/icon scale.
Colour may be overridden per instance. Weight may not. That is the entire
policy.
Typography is two voices, not one font
Who is allowed to talk like what:
- Fraunces, the serif, is the product’s voice: greetings, insight questions, the sentences Kaiya writes.
- Geist runs the working interface. Geist Mono carries data and identifiers.
- Headings sit at Medium, and body reads through
text/bodyrather thantext/primary, because near-black at heavy weight is how dashboards shout.
A user can tell, before reading a word, whether the product is speaking, offering a control, or citing a value.
Designing the surface where the product reasons
Tellius is an analytics product whose main interface is a conversation, and a conversation with a model is a trust problem before it is a layout problem. Three decisions carry most of the weight.
The plan is shown before the answer. Kaiya posts its working plan as numbered steps that check off as they run. A reader who can see step three running trusts step five’s conclusion differently.

The answer is typeset, not dumped. Headed sections, bold figures, every claim carrying its number, and the dashboards’ own charts rendered inline on the same tokens.

The voice is specified like a component. You and your, never we. Status reads reasoning, never thinking, never loading. A banned list keeps the marketing register out of an analyst’s tool. That restraint is a large part of why people trust the numbers.

What changed
52 primitives hidden from publishing. 116 semantic tokens in the one collection a designer sees, named for jobs. The foundations page keeps a live light and dark pair of the same card, so the mode override is proven on the sheet rather than promised.
Stroke was the clearest win: 226 values collapsed to hairline, divider and ink, and all 338 inline styles were replaced with bound variables. Without that, the mode switch would not have been possible.
Two grids govern layout: a workspace preset for dense surfaces at 40px margins, and a conversation preset for Kaiya at an 888 measure.

The calls that could have gone another way
A system is decided in a handful of moments where more than one path was defensible. Three mattered here, with the options that lost kept on the sheet.
What I would do next
In order:
- Measure adoption: library insertions and detach rates per component. A detach is feedback with coordinates.
- Retire the 25 reconstructed icons as production assets land, so the gap ledger closes.
- Open a contribution path, so a missing component becomes a proposal rather than a local copy.
How it stays alive with engineering
A token layer that only lives in Figma is a mood board. The contract has three parts:
- The variable collection is the source. Every component set binds to it. A role changes in one place; nothing is corrected screen by screen.
- Storybook is where we agree. A token change lands as a pull request and is reviewed against the stories, not a screenshot in a ticket.
- A standing half hour, every week. Engineering brings what had no token, I bring what drifted. Most weeks it is a component using the wrong role.
One rule: I do not file a design bug without proposing the token that fixes it. A proposal is a thing an engineer can merge.
Where it stands
Foundations and Components are rebuilt, Vizpads run on the workspace grid, Kaiya on the conversation grid. Component sets expose variant properties only, which keeps the contract with engineering narrow.
One number is deliberately missing. The skin shipped in 2026 and the detach-rate baseline is still accruing, so there is no adoption figure yet. Quoting one this early would be decoration.
Revisions
- Δ1
- Foundations page rebuilt on a single variable collection.
- Δ2
- Component sets rebound from raw hex to semantic tokens.
- Δ3
- Stroke palette collapsed from 226 values to three roles.
- Δ4
- Chart styling moved onto viz tokens, six categorical and four measure roles.
- Δ5
- Kaiya chat surfaces added on the conversation grid.