A persona's colour does two unrelated jobs, and the live app makes one palette do both — badly. This page separates them and mocks the open half on the real 68-persona roster (from prototype/personas/). Two surfaces, two questions: in a running conversation, how do co-present voices stay separable (the seat); and when browsing, what colour — if any — does a persona own (the identity). Every colour below is generated in OKLCH at low, fixed chroma, so the whole set stays in the cream/coral family.
| Identity colour | Seat colour | |
|---|---|---|
| Question | what is this persona's colour | how do voices in this room stay apart |
| Wants | stability — same persona, same hue, everywhere | contrast — whoever's seated, maximally separable |
| Lives in | the picker, cast cards, avatars, @-mentions | the conversation transcript |
These goals fight: identity wants to never change, seat wants to change per-room to dodge clashes. Today the app half-does both — an authored "preferred" hue the room overrides on collision — which is why neither feels right, and why 16 of 68 personas are slate (it's also the silent default).
the hand-tuned brand palette with its one collision fixed: lilac → a bluer violet, plum → a warmer orchid; the other six brand colours unchanged. Shown in seat-assignment (max-contrast) order — this is what's live in the room (v88):
The scheme (per-room rotation · contrast order · colour-follows-selection) stays whichever you pick — this is only the eight colour values. Each palette shown light & dark:
lilac ≈ plum (one purple, used twice) and slate ≈ teal (two blues) muddy together when a room seats both. Now — the OKLCH re-tune: eight genuinely distinct hues 45° apart, but a few lost the brand warmth (coral skews pink, teal pops, olive reads murky). Hybrid (third strip, ★) — the brand palette untouched except the collision: lilac → a bluer violet, plum → a warmer orchid, so all eight stay brand-pretty yet no two muddy together. This is the one — live in the room as of v88.One candidate for the identity colour: derive it from the slug. hash(slug) → hue gives every persona a stable, evenly-spread colour with zero curation and no slate junk-drawer. The earlier version roamed the full HSL wheel and looked garish; this one feeds the hash through a muted OKLCH low-chroma recipe, so the hues stay muted and on-theme — but the colour is still meaningless (it doesn't know who the persona is). Every disc is coloured purely by its slug, shown beneath each name. Identical on every reload, forever.
colour = hash(slug) → hue, rendered in muted OKLCH · deterministic & permanent · flip the theme to e-ink — every hue flattens to grey, so a hashed identity can't survive a greyscale reader (it falls back to glyph + name).
The other candidate, and my recommendation: don't colour personas by who they are at all. On the bench they're neutral — identity rides on the glyph + name, which never collide and never lie. The instant you seat one it adopts the next contrast-tuned seat colour. Click any persona to seat them; click again to retire. Use ↻ new room to re-roll the room — watch the same picks come up in a different colour set (that's §4).
A fixed contrast order has a flaw: seat 1 is always coral, seat 2 always teal. Since real rooms hold 1–4 personas, the same few colours run constantly and seats 5–8 almost never appear — every room looks the same. The fix is one line: each room takes a stable offset from its id (hash(room_id) % 8) and walks the same contrast cycle from there. Within a room, still maximal contrast; across rooms, variety; and the back half of the palette finally gets used.
rotation is append-safe: a mid-room invite takes the next unused colour in the rotated order, so seated personas never re-colour (the WhatsApp lock holds). "Even-spacing by cast size" would have looked tidier but recolours everyone whenever the cast grows — so it's out.
And the payoff reaches the original problem: with one per-room colour truth, the chats-pane rows just show each room's locked seat colours — exactly what you saw inside. No second source of colour to reconcile.
Mockup B in the production modal's clothes — the exact Invite panel, rebuilt. On the bench, a card stays a quiet neutral monogram — no colour, no checkbox. What invites the click is the hover: the card lifts, its border and initial pick up coral. Click a card and only then does it take this room's next rotated seat colour, a ✓ appears, and the count ticks up. Cap honoured at 5. (Compare the live one, where every disc is the persona's authored colour — hence the wall of identical slates and plums.)
Add one or more voices — a newcomer is caught up on the conversation.
a faithful rebuild for the design — search filters live; selection caps at 5; the seat colours are this room's rotated set. In production these discs are the persona's authored colour (the repetition you flagged); here colour is born on selection.