Compare commits

..

No commits in common. "d1ed66b7ae65bd4612c04183d5c1d0085e0ed107" and "c0480e0ae0044d54ef939fbe8077b158e181fbc0" have entirely different histories.

2 changed files with 37 additions and 30 deletions

View File

@ -1,31 +1,35 @@
import { AGENTS } from '../api/agents.js' import { AGENTS, initialsOf } from '../api/agents.js'
import './AgentChip.css' import './AgentChip.css'
/** /**
* TWO SYMBOLS, ONE CONTRAST: a sparkle for the machines, a person for the * ROLE ICONS one per AI employee, true to what it does.
* people.
* *
* The sparkle is the settled 2026 signal for AI the mark Claude, Gemini and * People are shown by their initials; the machines are shown by a symbol. That
* Copilot all use so an agent's disc reads as "made by AI" without a legend, * contrast is the point: an operator can tell a human step from an autonomous
* in the agent's own colour. A person's disc carries a plain head-and-shoulders * one at a glance, before reading a name, and the symbol says which machine
* glyph, so a human step reads as human at the same glance. The contrast is the * the one that CHECKS a lead, the one that TALKS to the customer, the one that
* whole message: which of these did the machine do, and which did a person. * recommends COVER, the one that verifies IDENTITY, the one that prepares a
* Who exactly is said by the name beside the disc and by the colour. * REFERRAL. Monoline at disc size, so they stay legible on every hue.
*/ */
function SparkleGlyph() { const ICONS = {
return ( // a magnifier Intake checks the lead is real and scores it
<svg className="who__glyph" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"> inspect: <><circle cx="6.6" cy="6.6" r="3.4" /><path d="M9.2 9.2 12 12" strokeLinecap="round" /></>,
<path d="M8 .8c.25 2.4.9 3.9 1.9 4.9 1 1 2.5 1.65 4.9 1.9v.8c-2.4.25-3.9.9-4.9 1.9-1 1-1.65 2.5-1.9 4.9h-.8c-.25-2.4-.9-3.9-1.9-4.9-1-1-2.5-1.65-4.9-1.9v-.8c2.4-.25 3.9-.9 4.9-1.9 1-1 1.65-2.5 1.9-4.9z" /> // a speech bubble Engage talks to the customer
</svg> chat: <path d="M2.6 3.4h10.8v6.4H7l-2.8 2.2v-2.2H2.6z" strokeLinejoin="round" />,
) // a shield the Advisor recommends the cover that protects them
shield: <path d="M8 2.2 12.6 4v3.4c0 2.8-2 4.7-4.6 6.1C5.4 12.1 3.4 10.2 3.4 7.4V4z" strokeLinejoin="round" />,
// an ID badge KYC verifies identity
id: <><rect x="2.6" y="3.4" width="10.8" height="9.2" rx="1.4" /><circle cx="6.2" cy="7" r="1.5" /><path d="M9.2 6.4h2.6M9.2 8.6h2.6M4.2 10.4h5" strokeLinecap="round" /></>,
// balance scales the Referral prepares a file for a human to weigh
scales: <path d="M8 2.4v10.4M4 12.8h8M3 5.2h10M3 5.2 1.6 8.4h2.8zM13 5.2 11.6 8.4h2.8zM8 3.2 4 5.2M8 3.2l4 2" strokeLinecap="round" strokeLinejoin="round" />,
} }
function PersonGlyph() { function AgentGlyph({ name }) {
const g = ICONS[name]
if (!g) return null
return ( return (
<svg className="who__glyph who__glyph--person" viewBox="0 0 16 16" fill="none" <svg className="who__glyph" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.35" aria-hidden="true">
stroke="currentColor" strokeWidth="1.5" aria-hidden="true"> {g}
<circle cx="8" cy="5.6" r="2.7" />
<path d="M2.9 13.8a5.1 5.1 0 0 1 10.2 0" strokeLinecap="round" />
</svg> </svg>
) )
} }
@ -44,6 +48,7 @@ function PersonGlyph() {
export default function AgentChip({ agentKey, name, size = 'sm', showName = true, onOpen }) { export default function AgentChip({ agentKey, name, size = 'sm', showName = true, onOpen }) {
const a = agentKey ? AGENTS[agentKey] : null const a = agentKey ? AGENTS[agentKey] : null
const label = a ? a.short : (name || 'System') const label = a ? a.short : (name || 'System')
const initials = a ? a.initials : initialsOf(name)
const tone = a ? a.tone : 'grey' const tone = a ? a.tone : 'grey'
const body = ( const body = (
@ -58,8 +63,14 @@ export default function AgentChip({ agentKey, name, size = 'sm', showName = true
Only agents get it. A trail where a human's disc also carried one Only agents get it. A trail where a human's disc also carried one
would say nothing at all. */} would say nothing at all. */}
<span className={`who__disc who__disc--${tone}`} aria-hidden="true"> <span className={`who__disc who__disc--${tone}`} aria-hidden="true">
{/* A machine wears the sparkle; a person wears the person. */} {/* A machine wears its role icon; a person wears their initials. */}
{a ? <SparkleGlyph /> : <PersonGlyph />} {a && a.icon ? <AgentGlyph name={a.icon} /> : initials}
{a ? (
<svg className="who__ai" viewBox="0 0 12 12" aria-hidden="true">
<path d="M6 .9 7.2 4.3 10.6 5.5 7.2 6.7 6 10.1 4.8 6.7 1.4 5.5 4.8 4.3Z" />
<path d="M10 8.2 10.5 9.6 11.9 10.1 10.5 10.6 10 12 9.5 10.6 8.1 10.1 9.5 9.6Z" />
</svg>
) : null}
</span> </span>
{showName ? <span className="who__name">{label}</span> : null} {showName ? <span className="who__name">{label}</span> : null}
{a ? <span className="who__sr"> (AI)</span> : null} {a ? <span className="who__sr"> (AI)</span> : null}

View File

@ -93,15 +93,11 @@
at 14, and 12px is the FLOOR reserved for uppercase eyebrows, never at 14, and 12px is the FLOOR reserved for uppercase eyebrows, never
for anything a person has to read. Size does the prioritising so the for anything a person has to read. Size does the prioritising so the
reader does not have to. */ reader does not have to. */
/* Shifted up one notch after an audit found 124 of ~200 sizings sitting at
12-13px the "meta" tier had quietly become the body size, so the whole
app read tiny and uniform with nothing for the eye to land on. Body is 14
now, values 15, emphasis 16; 12px stays for uppercase eyebrows only. */
--fs-3xs: 0.75rem; /* 12px — uppercase eyebrows only */ --fs-3xs: 0.75rem; /* 12px — uppercase eyebrows only */
--fs-2xs: 0.875rem; /* 14px — was 13; the app's dominant size, now comfortable */ --fs-2xs: 0.8125rem; /* 13px — timestamps, meta */
--fs-xs: 0.9375rem; /* 15px — field labels */ --fs-xs: 0.875rem; /* 14px — field labels */
--fs-sm: 1rem; /* 16px — body, field values */ --fs-sm: 0.9375rem; /* 15px — body, field values */
--fs-md: 1.0625rem; /* 17px — emphasis */ --fs-md: 1rem; /* 16px — emphasis */
--fs-lg: 1.125rem; /* 18px — panel titles */ --fs-lg: 1.125rem; /* 18px — panel titles */
--fs-xl: 1.375rem; /* 22px — section headings */ --fs-xl: 1.375rem; /* 22px — section headings */
--fs-2xl: 1.75rem; /* 28px — page title */ --fs-2xl: 1.75rem; /* 28px — page title */