Align page typography to the unified scale

Sweep the remaining inline type across every page onto the system scale:
oversized metric numbers (22/24px) down to the 18px title step, body text
13px → 14px, captions/meta 11px and 12.5px → 12px, and small control icons
13/11px → 16/14px. No structural or layout changes — the foundation
already gridded spacing, radius, and color; this finishes the type so the
whole app reads from one ramp. Full interactive e2e and the overflow
guards stay green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 4.8 committed 2026-06-10 20:31:24 -04:00
1 parent f5aab15920
commit fa01aa682f
31 files changed
+120 -120

No files matched your search

@@ -143,14 +143,14 @@ function ApprovalDetailDialog({
<IconButton icon="x" label="Close" onClick={onClose} />
</div>
<div className="row" style={{ flexWrap: "wrap", gap: 6, marginBottom: 14 }}>
<span style={{ fontSize: 11, color: tone.color, fontWeight: 540, letterSpacing: "0.02em" }}>{tone.label}</span>
<span style={{ fontSize: 12, color: tone.color, fontWeight: 540, letterSpacing: "0.02em" }}>{tone.label}</span>
<span style={{ color: "var(--text-4)" }}>·</span>
<Pill>{approval.kind}</Pill>
</div>
<p style={{ margin: "0 0 16px", color: "var(--text-2)", fontSize: 13, lineHeight: 1.55, whiteSpace: "pre-wrap" }}>
<p style={{ margin: "0 0 16px", color: "var(--text-2)", fontSize: 14, lineHeight: 1.55, whiteSpace: "pre-wrap" }}>
{approval.details}
</p>
<div style={{ display: "grid", gridTemplateColumns: "100px 1fr", gap: "10px 14px", fontSize: 12.5 }}>
<div style={{ display: "grid", gridTemplateColumns: "100px 1fr", gap: "10px 14px", fontSize: 12 }}>
<span style={{ color: "var(--text-3)" }}>Requested by</span>
<span>{requester}</span>
{approval.sourceEntityType && (<><span style={{ color: "var(--text-3)" }}>Source</span><span>{humanizeKind(approval.sourceEntityType)}</span></>)}
@@ -199,7 +199,7 @@ function StatTile({ label, value, tone }: { label: string; value: string; tone?:
<div className="card-label" style={{ marginBottom: 6 }}>{label}</div>
<div
className="num"
style={{ fontSize: 22, fontWeight: 600, color: tone === "amber" ? "var(--amber)" : "var(--text-1)", letterSpacing: "-0.02em" }}
style={{ fontSize: 18, fontWeight: 600, color: tone === "amber" ? "var(--amber)" : "var(--text-1)", letterSpacing: "-0.02em" }}
>
{value}
</div>
@@ -241,12 +241,12 @@ function ApprovalRow({
<div style={{ width: 3, alignSelf: "stretch", background: tone.color, borderRadius: 2 }} />
<div style={{ minWidth: 0 }}>
<div className="row" style={{ marginBottom: 4 }}>
<span style={{ fontSize: 11, color: tone.color, fontWeight: 540, letterSpacing: "0.02em" }}>{tone.label}</span>
<span style={{ fontSize: 12, color: tone.color, fontWeight: 540, letterSpacing: "0.02em" }}>{tone.label}</span>
<span style={{ color: "var(--text-4)" }}>·</span>
<Pill>{approval.kind}</Pill>
</div>
<div style={{ fontSize: 15, fontWeight: 540, letterSpacing: "-0.01em", marginBottom: 4 }}>{approval.title}</div>
<div style={{ fontSize: 13, color: "var(--text-2)", lineHeight: 1.5, marginBottom: 12, whiteSpace: "pre-wrap" }}>
<div style={{ fontSize: 14, color: "var(--text-2)", lineHeight: 1.5, marginBottom: 12, whiteSpace: "pre-wrap" }}>
{approval.details}
</div>
<div className="row" style={{ gap: 8 }}>
@@ -282,7 +282,7 @@ function DecidedRow({
style={{
gap: 12,
padding: "12px 18px",
fontSize: 13,
fontSize: 14,
borderBottom: last ? "none" : "1px solid var(--border-soft)",
}}
>
@@ -70,7 +70,7 @@ export function DocumentsPage({ snapshot, actions }: PageProps) {
<option value="all">All types</option>
{DOC_TYPES.map((t) => <option key={t} value={t}>{t}</option>)}
</select>
<Button tone="primary" onClick={() => setCreateOpen(true)}><Icon name="plus" size={13} /> New document</Button>
<Button tone="primary" onClick={() => setCreateOpen(true)}><Icon name="plus" size={16} /> New document</Button>
</TopbarActions>
<h1 className="page-h1">Documents</h1>
<p className="page-sub">{documents.length} {documents.length === 1 ? "document" : "documents"}</p>
@@ -75,7 +75,7 @@ export function FilesPage({ snapshot, actions }: PageProps) {
]}
/>
<Button tone="primary" onClick={upload}>
<Icon name="upload" size={13} /> Upload
<Icon name="upload" size={16} /> Upload
</Button>
</TopbarActions>
<h1 className="page-h1">Files</h1>
@@ -104,7 +104,7 @@ export function FilesPage({ snapshot, actions }: PageProps) {
<div className="row" style={{ marginBottom: 10 }}>
<div className="section-label">{labelFor(section)}</div>
<div style={{ marginLeft: "auto", fontSize: 11, color: "var(--text-3)" }}>Modified ↓</div>
<div style={{ marginLeft: "auto", fontSize: 12, color: "var(--text-3)" }}>Modified ↓</div>
</div>
{view === "list" ? (
@@ -148,7 +148,7 @@ function FilesFilter({
<Popover
trigger={({ toggle }) => (
<button type="button" className="button ghost" aria-label="Filter files" onClick={toggle}>
<Icon name="filter" size={13} color={scan !== "all" ? "var(--accent)" : "currentColor"} />
<Icon name="filter" size={16} color={scan !== "all" ? "var(--accent)" : "currentColor"} />
</button>
)}
>
@@ -158,7 +158,7 @@ function FilesFilter({
{options.map((option) => (
<MenuRow key={option.id} active={scan === option.id} onClick={() => onScan(option.id)}>
{option.label}
{scan === option.id && <span className="menu-check"><Icon name="check" size={13} /></span>}
{scan === option.id && <span className="menu-check"><Icon name="check" size={16} /></span>}
</MenuRow>
))}
</>
@@ -62,11 +62,11 @@ export function InboxPage({ snapshot }: PageProps) {
<div className="row" style={{ gap: 10 }}>
{item.agentName && <Avatar name={item.agentName} size="sm" bot />}
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ fontSize: 13, fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{item.title}</div>
<div style={{ fontSize: 14, fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{item.title}</div>
<div style={{ fontSize: 12, color: "var(--text-3)" }}>{item.detail}</div>
</div>
<Pill tone={item.tone}>{humanize(item.kind)}</Pill>
<span className="mono" style={{ fontSize: 11, color: "var(--text-3)", flexShrink: 0 }}>{formatRelative(item.timestamp)}</span>
<span className="mono" style={{ fontSize: 12, color: "var(--text-3)", flexShrink: 0 }}>{formatRelative(item.timestamp)}</span>
</div>
</div>
))}
@@ -155,7 +155,7 @@ function MetricCard({ label, value, sub }: { label: string; value: string; sub?:
<div className="card" style={{ padding: 14 }}>
<div className="card-label" style={{ marginBottom: 6 }}>{label}</div>
<div className="row" style={{ alignItems: "baseline", gap: 4 }}>
<span className="num" style={{ fontSize: 24, fontWeight: 600 }}>{value}</span>
<span className="num" style={{ fontSize: 18, fontWeight: 600 }}>{value}</span>
{sub && <span style={{ fontSize: 12, color: "var(--text-3)" }}>{sub}</span>}
</div>
</div>
@@ -45,7 +45,7 @@ export function KnowledgePage({ snapshot, actions }: PageProps) {
<option value="all">All categories</option>
{CATEGORIES.map((c) => <option key={c} value={c}>{c}</option>)}
</select>
<Button tone="primary" onClick={() => setCreateOpen(true)}><Icon name="plus" size={13} /> Add entry</Button>
<Button tone="primary" onClick={() => setCreateOpen(true)}><Icon name="plus" size={16} /> Add entry</Button>
</TopbarActions>
<h1 className="page-h1">Knowledge Base</h1>
<p className="page-sub">{entries.length} {entries.length === 1 ? "entry" : "entries"}</p>
@@ -61,10 +61,10 @@ export function KnowledgePage({ snapshot, actions }: PageProps) {
<Pill>{entry.category}</Pill>
<Pill tone={importanceTone(entry.importance)}>{entry.importance}</Pill>
</div>
<div style={{ fontSize: 13, color: "var(--text-2)", lineHeight: 1.5, whiteSpace: "pre-wrap", maxHeight: 120, overflow: "hidden" }}>
<div style={{ fontSize: 14, color: "var(--text-2)", lineHeight: 1.5, whiteSpace: "pre-wrap", maxHeight: 120, overflow: "hidden" }}>
{entry.content}
</div>
<div style={{ marginTop: 8, fontSize: 11, color: "var(--text-3)" }}>{formatRelative(entry.updatedAt)}</div>
<div style={{ marginTop: 8, fontSize: 12, color: "var(--text-3)" }}>{formatRelative(entry.updatedAt)}</div>
</article>
))}
</div>
@@ -40,7 +40,7 @@ export function MeetingsPage({ snapshot, actions }: PageProps) {
return (
<div className="page">
<TopbarActions>
<Button tone="primary" onClick={() => setCreateOpen(true)}><Icon name="plus" size={13} /> Schedule</Button>
<Button tone="primary" onClick={() => setCreateOpen(true)}><Icon name="plus" size={16} /> Schedule</Button>
</TopbarActions>
<h1 className="page-h1">Meetings</h1>
<p className="page-sub">{scheduled.length} upcoming · {completed.length} past</p>
@@ -91,7 +91,7 @@ function MeetingCard({ meeting, onDelete }: { meeting: { id: string; title: stri
<Pill>{meeting.durationMinutes}m</Pill>
</div>
{meeting.scheduledAt && <div style={{ fontSize: 12, color: "var(--text-3)" }}>{new Date(meeting.scheduledAt).toLocaleString()}</div>}
{meeting.agenda && <div style={{ fontSize: 13, color: "var(--text-2)", marginTop: 6, whiteSpace: "pre-wrap", lineHeight: 1.5 }}>{meeting.agenda}</div>}
{meeting.agenda && <div style={{ fontSize: 14, color: "var(--text-2)", marginTop: 6, whiteSpace: "pre-wrap", lineHeight: 1.5 }}>{meeting.agenda}</div>}
</div>
);
}
@@ -51,7 +51,7 @@ export function SettingsPage({ snapshot, actions }: PageProps) {
return (
<div className="split-main">
<aside className="secondary-pane">
<div style={{ fontSize: 13, fontWeight: 600, padding: "4px 8px 14px" }}>Settings</div>
<div style={{ fontSize: 14, fontWeight: 600, padding: "4px 8px 14px" }}>Settings</div>
<div className="pane-scroll">
<NavGroup items={TABS} active={tab} onChange={setTab} />
</div>
@@ -82,9 +82,9 @@ export function SocialPage({ snapshot, actions }: PageProps) {
return (
<div className="page" style={{ display: "flex", flexDirection: "column", minHeight: 0, height: "100%", padding: "28px 32px 0" }}>
<TopbarActions>
<Button onClick={() => setConnectOpen(true)}><Icon name="plus" size={13} /> Connect account</Button>
<Button onClick={() => setConnectOpen(true)}><Icon name="plus" size={16} /> Connect account</Button>
<Button tone="primary" onClick={() => setDraftOpen(true)} disabled={accounts.length === 0}>
<Icon name="sparkle" size={13} /> Draft post
<Icon name="sparkle" size={16} /> Draft post
</Button>
</TopbarActions>
<h1 className="page-h1">Social</h1>
@@ -224,12 +224,12 @@ function AccountCard({
<div className="row" style={{ gap: 10, minWidth: 0 }}>
<PlatformIcon platform={account.platform} />
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ fontSize: 13, fontWeight: 540, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{account.handle}</div>
<div style={{ fontSize: 11, color: "var(--text-3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{account.displayName}</div>
<div style={{ fontSize: 14, fontWeight: 540, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{account.handle}</div>
<div style={{ fontSize: 12, color: "var(--text-3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{account.displayName}</div>
</div>
</div>
{authorizedName && (
<div className="row" style={{ fontSize: 11, color: "var(--text-3)", gap: 6 }}>
<div className="row" style={{ fontSize: 12, color: "var(--text-3)", gap: 6 }}>
<span style={{ width: 6, height: 6, borderRadius: 3, background: "var(--green)" }} /> Authorized to {authorizedName}
</div>
)}
@@ -286,10 +286,10 @@ function PostRow({
{post.state === "published" && <Pill tone="green" dot>Published</Pill>}
{post.state === "cancelled" && <Pill tone="red">Cancelled</Pill>}
</div>
<div style={{ fontSize: 13, color: "var(--text-1)", lineHeight: 1.5, marginBottom: 8, whiteSpace: "pre-wrap" }}>{post.bodyMd}</div>
<div style={{ fontSize: 14, color: "var(--text-1)", lineHeight: 1.5, marginBottom: 8, whiteSpace: "pre-wrap" }}>{post.bodyMd}</div>
<div className="row" style={{ gap: 6 }}>
<Avatar name={authorName} size="sm" bot={post.createdByEmployeeId === null} />
<span style={{ fontSize: 11, color: "var(--text-3)" }}>By {authorName}</span>
<span style={{ fontSize: 12, color: "var(--text-3)" }}>By {authorName}</span>
</div>
</div>
<div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
@@ -36,7 +36,7 @@ export function SprintsPage({ snapshot, actions }: PageProps) {
return (
<div className="page">
<TopbarActions>
<Button tone="primary" onClick={() => setCreateOpen(true)}><Icon name="plus" size={13} /> New sprint</Button>
<Button tone="primary" onClick={() => setCreateOpen(true)}><Icon name="plus" size={16} /> New sprint</Button>
</TopbarActions>
<h1 className="page-h1">Sprints</h1>
<p className="page-sub">{sprints.length} {sprints.length === 1 ? "sprint" : "sprints"}</p>
@@ -78,7 +78,7 @@ function SprintCard({ sprint, tasks, onDelete }: { sprint: SprintRecord; tasks:
<Pill tone={sprintStatusTone(sprint.status)}>{sprint.status}</Pill>
<Pill>{sprint.startDate} to {sprint.endDate}</Pill>
</div>
<div style={{ fontSize: 13, color: "var(--text-2)", lineHeight: 1.5, marginBottom: 12 }}>{sprint.goal}</div>
<div style={{ fontSize: 14, color: "var(--text-2)", lineHeight: 1.5, marginBottom: 12 }}>{sprint.goal}</div>
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
<ProgressBar label="Time" pct={progressPct} />
<ProgressBar label="Tasks" pct={taskPct} />
@@ -97,9 +97,9 @@ export function TeamPage({ snapshot, actions }: PageProps) {
<div className="page">
<TopbarActions>
<Button tone="ghost" onClick={() => cycleFilter(filter, setFilter)} title="Filter">
<Icon name="filter" size={13} /> {filterLabel(filter)}
<Icon name="filter" size={16} /> {filterLabel(filter)}
</Button>
<Button tone="primary" onClick={openHireDialog}><Icon name="plus" size={13} /> Hire</Button>
<Button tone="primary" onClick={openHireDialog}><Icon name="plus" size={16} /> Hire</Button>
</TopbarActions>
<h1 className="page-h1">Team</h1>
<p className="page-sub">
@@ -266,7 +266,7 @@ function RosterRow({ row, last, onEdit }: { row: RosterEntry; last: boolean; onE
<Avatar name={row.name} size="sm" bot={!row.human} />
<div style={{ minWidth: 0 }}>
<div style={{ fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{row.name}</div>
<div style={{ fontSize: 11, color: "var(--text-3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{row.role}</div>
<div style={{ fontSize: 12, color: "var(--text-3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{row.role}</div>
</div>
</div>
<div style={{ color: "var(--text-2)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{row.dept}</div>
@@ -296,7 +296,7 @@ function RosterRow({ row, last, onEdit }: { row: RosterEntry; last: boolean; onE
}}
/>
</div>
<span className="num mono" style={{ fontSize: 11, color: "var(--text-3)" }}>{money(row.budgetCents)}</span>
<span className="num mono" style={{ fontSize: 12, color: "var(--text-3)" }}>{money(row.budgetCents)}</span>
</div>
)}
</div>
@@ -92,9 +92,9 @@ export function WorkPage({ snapshot, actions }: PageProps) {
onPriority={setPriorityFilter}
onAssignee={setAssigneeFilter}
/>
<Button tone="ghost" onClick={() => setNewGoalOpen(true)}><Icon name="plus" size={13} /> Goal</Button>
<Button tone="ghost" onClick={() => setNewProjectOpen(true)}><Icon name="plus" size={13} /> Project</Button>
<Button tone="primary" onClick={() => setNewTaskOpen(true)}><Icon name="plus" size={13} /> New task</Button>
<Button tone="ghost" onClick={() => setNewGoalOpen(true)}><Icon name="plus" size={16} /> Goal</Button>
<Button tone="ghost" onClick={() => setNewProjectOpen(true)}><Icon name="plus" size={16} /> Project</Button>
<Button tone="primary" onClick={() => setNewTaskOpen(true)}><Icon name="plus" size={16} /> New task</Button>
</TopbarActions>
<h1 className="page-h1">Work</h1>
<p className="page-sub">
@@ -178,7 +178,7 @@ function WorkFilter({
<Popover
trigger={({ toggle }) => (
<button type="button" className="button ghost" aria-label="Filter tasks" onClick={toggle}>
<Icon name="filter" size={13} color={active ? "var(--accent)" : "currentColor"} />
<Icon name="filter" size={16} color={active ? "var(--accent)" : "currentColor"} />
</button>
)}
>
@@ -188,19 +188,19 @@ function WorkFilter({
{priorities.map((option) => (
<MenuRow key={option.id} active={priority === option.id} onClick={() => onPriority(option.id)}>
{option.label}
{priority === option.id && <span className="menu-check"><Icon name="check" size={13} /></span>}
{priority === option.id && <span className="menu-check"><Icon name="check" size={16} /></span>}
</MenuRow>
))}
<MenuDivider />
<MenuLabel>Assignee</MenuLabel>
<MenuRow active={assignee === "all"} onClick={() => onAssignee("all")}>
All assignees
{assignee === "all" && <span className="menu-check"><Icon name="check" size={13} /></span>}
{assignee === "all" && <span className="menu-check"><Icon name="check" size={16} /></span>}
</MenuRow>
{agents.map((agent) => (
<MenuRow key={agent.id} active={assignee === agent.id} onClick={() => onAssignee(agent.id)}>
{agent.name}
{assignee === agent.id && <span className="menu-check"><Icon name="check" size={13} /></span>}
{assignee === agent.id && <span className="menu-check"><Icon name="check" size={16} /></span>}
</MenuRow>
))}
</>
@@ -242,7 +242,7 @@ function BoardView({
<div key={column.id} style={{ display: "flex", flexDirection: "column", gap: 8, minWidth: 0 }}>
<div className="row" style={{ padding: "4px 6px 8px" }}>
<span style={{ width: 8, height: 8, borderRadius: 2, background: column.tone, flexShrink: 0 }} />
<span style={{ fontSize: 12.5, fontWeight: 540 }}>{column.label}</span>
<span style={{ fontSize: 12, fontWeight: 540 }}>{column.label}</span>
<span className="num" style={{ fontSize: 12, color: "var(--text-3)" }}>{columnTasks.length}</span>
<IconButton icon="plus" label="Add task" onClick={onCreate} />
</div>
@@ -427,7 +427,7 @@ function TaskCard({
<div
style={{
flex: 1,
fontSize: 13,
fontSize: 14,
fontWeight: 480,
lineHeight: 1.35,
letterSpacing: "-0.005em",
@@ -61,7 +61,7 @@ export function ChatComposer({
<IconButton icon="sparkle" label="Commands" onClick={() => setSlashOpen((open) => !open)} />
{attachment && (
<span className="pill" style={{ maxWidth: 220 }}>
<Icon name="file" size={11} />
<Icon name="file" size={14} />
<span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{attachment.name}</span>
<button
type="button"
@@ -69,12 +69,12 @@ export function ChatComposer({
onClick={() => onAttachmentChange("")}
style={{ display: "inline-flex", border: 0, background: "transparent", padding: 0, color: "var(--text-3)", cursor: "pointer" }}
>
<Icon name="x" size={11} />
<Icon name="x" size={14} />
</button>
</span>
)}
<div style={{ marginLeft: "auto", display: "flex", alignItems: "center", gap: 6 }}>
<span className="mono" style={{ fontSize: 11, color: "var(--text-3)" }}>Ctrl+Enter</span>
<span className="mono" style={{ fontSize: 12, color: "var(--text-3)" }}>Ctrl+Enter</span>
<Button tone="primary" size="small" type="submit" disabled={disabled}><Icon name="send" size={12} /> Send</Button>
</div>
</div>
@@ -58,13 +58,13 @@ export function ChatMessageRow({
<Avatar name={name} size={compact ? "sm" : ""} bot={bot} />
<div style={{ flex: 1, minWidth: 0 }}>
<div className="row" style={{ alignItems: "baseline", gap: 8, marginBottom: 2 }}>
<span style={{ fontSize: 13, fontWeight: 540 }}>{name}</span>
<span className="mono" style={{ fontSize: 11, color: "var(--text-3)" }}>{formatTime(message.createdAt)}</span>
{message.editedAt && !deleted && <span style={{ fontSize: 11, color: "var(--text-3)" }}>(edited)</span>}
<span style={{ fontSize: 14, fontWeight: 540 }}>{name}</span>
<span className="mono" style={{ fontSize: 12, color: "var(--text-3)" }}>{formatTime(message.createdAt)}</span>
{message.editedAt && !deleted && <span style={{ fontSize: 12, color: "var(--text-3)" }}>(edited)</span>}
{canModify && !editing && (
<span style={{ marginLeft: "auto", display: "flex", gap: 2 }}>
<IconButton icon="edit" label="Edit message" size={13} onClick={() => setEditing(true)} />
<IconButton icon="x" label="Delete message" size={13} onClick={onDelete} />
<IconButton icon="edit" label="Edit message" size={16} onClick={() => setEditing(true)} />
<IconButton icon="x" label="Delete message" size={16} onClick={onDelete} />
</span>
)}
</div>
@@ -74,7 +74,7 @@ export function ChatMessageRow({
</div>
)}
{deleted ? (
<div style={{ fontSize: 13, color: "var(--text-3)", fontStyle: "italic" }}>Message deleted</div>
<div style={{ fontSize: 14, color: "var(--text-3)", fontStyle: "italic" }}>Message deleted</div>
) : editing ? (
<form onSubmit={submitEdit}>
<textarea
@@ -91,7 +91,7 @@ export function ChatMessageRow({
</div>
</form>
) : (
<div style={{ fontSize: 13, color: "var(--text-1)", lineHeight: 1.5, whiteSpace: "pre-wrap", wordBreak: "break-word" }}>
<div style={{ fontSize: 14, color: "var(--text-1)", lineHeight: 1.5, whiteSpace: "pre-wrap", wordBreak: "break-word" }}>
{renderBody(message.bodyMd, messageMentions, context)}
</div>
)}
@@ -123,7 +123,7 @@ export function ChatMessageRow({
border: 0,
}}
>
<Icon name="chat" size={11} /> {replyCount > 0 ? `${replyCount} ${replyCount === 1 ? "reply" : "replies"}` : "Thread"} →
<Icon name="chat" size={14} /> {replyCount > 0 ? `${replyCount} ${replyCount === 1 ? "reply" : "replies"}` : "Thread"} →
</button>
)}
</div>
@@ -205,14 +205,14 @@ function AttachmentCard({ file, handoff = false, onOpen }: { file: FileObjectRec
</div>
<div style={{ flex: 1, minWidth: 0 }}>
<div className="row" style={{ gap: 6, minWidth: 0 }}>
<span style={{ fontSize: 12.5, fontWeight: 540, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{file.name}</span>
<span style={{ fontSize: 12, fontWeight: 540, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{file.name}</span>
{handoff && (
<span className="pill violet" style={{ flexShrink: 0 }}>
<Icon name="bot" size={10} /> AI → AI
</span>
)}
</div>
<div style={{ fontSize: 11, color: "var(--text-3)" }}>{file.kind.toUpperCase()} · {file.sha256.slice(0, 8)}</div>
<div style={{ fontSize: 12, color: "var(--text-3)" }}>{file.kind.toUpperCase()} · {file.sha256.slice(0, 8)}</div>
</div>
{canOpen && <IconButton icon="arrowUpRight" label={`Open ${file.name}`} onClick={onOpen ?? undefined} />}
</div>
@@ -41,7 +41,7 @@ export function ChatSidebar({
return (
<aside className="secondary-pane">
<div className="row" style={{ padding: "4px 8px 12px" }}>
<div style={{ fontSize: 13, fontWeight: 600 }}>Messages</div>
<div style={{ fontSize: 14, fontWeight: 600 }}>Messages</div>
<IconButton icon="plus" label="New space" onClick={onCreateSpace} />
</div>
<div className="pane-scroll">
@@ -81,7 +81,7 @@ export function ChatSidebar({
function NavGroup({ label, children }: { label: string; children: ReactNode }) {
return (
<div style={{ marginTop: 10 }}>
<div style={{ fontSize: 11, color: "var(--text-3)", padding: "6px 8px", fontWeight: 540, letterSpacing: "0.02em" }}>{label}</div>
<div style={{ fontSize: 12, color: "var(--text-3)", padding: "6px 8px", fontWeight: 540, letterSpacing: "0.02em" }}>{label}</div>
<div style={{ display: "flex", flexDirection: "column", gap: 1 }}>{children}</div>
</div>
);
@@ -104,7 +104,7 @@ function ChannelItem({
}) {
return (
<button type="button" className={`nav-item ${active ? "active" : ""}`.trim()} onClick={onClick}>
<Icon name={space.visibility === "restricted" ? "lock" : "hash"} size={13} color={active ? "var(--text-1)" : "var(--text-3)"} />
<Icon name={space.visibility === "restricted" ? "lock" : "hash"} size={16} color={active ? "var(--text-1)" : "var(--text-3)"} />
<span>{space.name}</span>
{count > 0 && <span className="nav-badge">{count}</span>}
</button>
@@ -136,7 +136,7 @@ function DirectItem({
{dotColor && <span className="presence-dot" style={{ background: dotColor }} />}
</span>
) : (
<Icon name="user" size={13} />
<Icon name="user" size={16} />
)}
<span>{space.name}</span>
{count > 0 && <span className="nav-badge">{count}</span>}
@@ -68,7 +68,7 @@ export function ChatThreadPanel({
}}
>
<div className="row" style={{ padding: "14px 16px", borderBottom: "1px solid var(--border-soft)", flexShrink: 0 }}>
<div style={{ fontSize: 12.5, fontWeight: 600 }}>Thread</div>
<div style={{ fontSize: 12, fontWeight: 600 }}>Thread</div>
<Pill tone={boardStateTone(thread.boardState)}>{boardStateLabel(thread.boardState)}</Pill>
<div style={{ marginLeft: "auto" }}>
<IconButton icon="x" label="Close thread" onClick={onClose} />
@@ -134,7 +134,7 @@ export function ChatThreadPanel({
<IconButton icon="attach" label="Attach file" onClick={onAttach} />
{attachment && (
<span className="pill" style={{ maxWidth: 150 }}>
<Icon name="file" size={11} />
<Icon name="file" size={14} />
<span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{attachment.name}</span>
<button
type="button"
@@ -142,7 +142,7 @@ export function ChatThreadPanel({
onClick={() => onAttachmentChange("")}
style={{ display: "inline-flex", border: 0, background: "transparent", padding: 0, color: "var(--text-3)", cursor: "pointer" }}
>
<Icon name="x" size={11} />
<Icon name="x" size={14} />
</button>
</span>
)}
@@ -215,7 +215,7 @@ function BoardControl({
{interventions.map((intervention) => (
<div key={intervention.id} style={{ borderTop: "1px solid var(--border-soft)", paddingTop: 7 }}>
<div className="row" style={{ gap: 6, marginBottom: 3 }}>
<span className="mono" style={{ fontSize: 11, color: "var(--text-3)" }}>{formatTime(intervention.createdAt)}</span>
<span className="mono" style={{ fontSize: 12, color: "var(--text-3)" }}>{formatTime(intervention.createdAt)}</span>
<Pill tone={intervention.mode === "takeover" ? "violet" : intervention.action === "freeze" ? "red" : undefined}>
{formatBoardAction(intervention.action)}
</Pill>
@@ -264,7 +264,7 @@ function AuditReplay({ events }: { events: AuditEventRecord[] }) {
minWidth: 0,
}}
>
<span className="mono" style={{ fontSize: 11, color: "var(--text-3)", flexShrink: 0 }}>{formatTime(event.createdAt)}</span>
<span className="mono" style={{ fontSize: 12, color: "var(--text-3)", flexShrink: 0 }}>{formatTime(event.createdAt)}</span>
<span style={{ fontSize: 12, color: "var(--text-1)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
{auditEventLabel(event.entityType, event.action)}
</span>
@@ -94,7 +94,7 @@ function DayDivider({ label }: { label: string }) {
return (
<div className="row" style={{ gap: 12, margin: "8px 0 16px" }}>
<div style={{ flex: 1, height: 1, background: "var(--border-soft)" }} />
<div style={{ fontSize: 11, color: "var(--text-3)", fontWeight: 540 }}>{label}</div>
<div style={{ fontSize: 12, color: "var(--text-3)", fontWeight: 540 }}>{label}</div>
<div style={{ flex: 1, height: 1, background: "var(--border-soft)" }} />
</div>
);
@@ -126,7 +126,7 @@ function ApprovalInline({
<Pill tone={approval.risk === "high" ? "red" : approval.risk === "medium" ? "amber" : undefined}>{approval.risk}</Pill>
</div>
<div style={{ fontSize: 14, fontWeight: 540, marginBottom: 4 }}>{approval.title}</div>
<div style={{ fontSize: 12.5, color: "var(--text-3)", marginBottom: 12, lineHeight: 1.5 }}>{approval.details}</div>
<div style={{ fontSize: 12, color: "var(--text-3)", marginBottom: 12, lineHeight: 1.5 }}>{approval.details}</div>
<div className="row" style={{ gap: 6 }}>
<Button tone="primary" size="small" onClick={onApprove}>Approve</Button>
<Button size="small" onClick={onDecline}>Decline</Button>
@@ -133,7 +133,7 @@ export function MentionTextarea({
border: 0,
background: i === index ? "var(--accent-soft)" : "transparent",
cursor: "pointer",
fontSize: 13,
fontSize: 14,
color: "var(--text-1)",
textAlign: "left",
}}
@@ -155,7 +155,7 @@ export function MentionTextarea({
border: 0,
resize: "none",
outline: "none",
fontSize: 13,
fontSize: 14,
color: "var(--text-1)",
background: "transparent",
padding: 0,
@@ -84,7 +84,7 @@ export function PinnedCard({
<Icon name="pin" size={14} />
</button>
</div>
<div style={{ fontSize: 13, fontWeight: 540, letterSpacing: "-0.005em", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
<div style={{ fontSize: 14, fontWeight: 540, letterSpacing: "-0.005em", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
{file.name}
</div>
<div className="mono" style={{ color: "var(--text-3)", fontSize: 10, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
@@ -92,12 +92,12 @@ export function PinnedCard({
</div>
<div className="row" style={{ gap: 6 }}>
<Pill tone={file.scanState === "approved" ? "green" : "red"}>{file.scanState === "approved" ? "Clean" : "Blocked"}</Pill>
<span className="mono" style={{ color: "var(--text-3)", fontSize: 11 }}>{grantCount}</span>
<span className="mono" style={{ color: "var(--text-3)", fontSize: 12 }}>{grantCount}</span>
</div>
<ScanLabelStrip file={file} />
<div className="row" style={{ gap: 8, marginTop: "auto", minWidth: 0 }}>
<Avatar name={ownerName} size="sm" bot={isAgentOwner(file)} />
<span style={{ fontSize: 11, color: "var(--text-3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
<span style={{ fontSize: 12, color: "var(--text-3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
{formatRelative(file.updatedAt ?? file.createdAt)} · {ownerName.split(" ")[0]}
</span>
</div>
@@ -89,7 +89,7 @@ function FileRow({
</div>
<div className="row" style={{ gap: 6, minWidth: 0 }}>
<Pill tone={canOpen ? "green" : "red"}>{canOpen ? "Clean" : "Blocked"}</Pill>
<span className="mono" style={{ color: "var(--text-3)", fontSize: 11 }}>{grantCount}</span>
<span className="mono" style={{ color: "var(--text-3)", fontSize: 12 }}>{grantCount}</span>
</div>
<div style={{ color: "var(--text-3)", fontSize: 12 }}>{formatRelative(file.updatedAt ?? file.createdAt)}</div>
<div style={{ textAlign: "right" }} onClick={(event) => event.stopPropagation()}>
@@ -36,7 +36,7 @@ export function BillingPanel({
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 20 }}>
<div className="card" style={{ padding: 14 }}>
<div className="card-label" style={{ marginBottom: 8 }}>Token usage (30d)</div>
<div style={{ display: "grid", gridTemplateColumns: "100px 1fr", gap: "6px 14px", fontSize: 12.5 }}>
<div style={{ display: "grid", gridTemplateColumns: "100px 1fr", gap: "6px 14px", fontSize: 12 }}>
<span style={{ color: "var(--text-3)" }}>Input chars</span><span className="num">{totalInputChars.toLocaleString()}</span>
<span style={{ color: "var(--text-3)" }}>Output chars</span><span className="num">{totalOutputChars.toLocaleString()}</span>
<span style={{ color: "var(--text-3)" }}>Total</span><span className="num">{(totalInputChars + totalOutputChars).toLocaleString()}</span>
@@ -66,8 +66,8 @@ export function BillingPanel({
</div>
<div className="num mono">{money(row.agent.budgetCents)}</div>
<div className="num mono">{row.requestCount}</div>
<div className="num mono" style={{ fontSize: 11 }}>{row.inputChars.toLocaleString()}</div>
<div className="num mono" style={{ fontSize: 11 }}>{row.outputChars.toLocaleString()}</div>
<div className="num mono" style={{ fontSize: 12 }}>{row.inputChars.toLocaleString()}</div>
<div className="num mono" style={{ fontSize: 12 }}>{row.outputChars.toLocaleString()}</div>
</div>
))}
</div>
@@ -85,7 +85,7 @@ export function BillingPanel({
<div key={provider.id} className="table-row" style={{ gridTemplateColumns: "minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr)", borderBottom: index === providers.length - 1 ? "none" : "1px solid var(--border-soft)" }}>
<div style={{ minWidth: 0 }}>
<div style={{ fontWeight: 540 }}>{provider.label}</div>
{provider.model && <div style={{ fontSize: 11, color: "var(--text-3)" }}>{provider.model}</div>}
{provider.model && <div style={{ fontSize: 12, color: "var(--text-3)" }}>{provider.model}</div>}
</div>
<div className="num mono">{requests.length}</div>
<div>{errors > 0 ? <Pill tone="amber">{errors}</Pill> : <span className="num mono" style={{ color: "var(--text-3)" }}>0</span>}</div>
@@ -102,7 +102,7 @@ function StatTile({ label, value, tone }: { label: string; value: string; tone?:
return (
<div className="card" style={{ padding: 14 }}>
<div className="card-label" style={{ marginBottom: 6 }}>{label}</div>
<div className="num" style={{ fontSize: 22, fontWeight: 600, color: tone === "red" ? "var(--red)" : "var(--text-1)" }}>{value}</div>
<div className="num" style={{ fontSize: 18, fontWeight: 600, color: tone === "red" ? "var(--red)" : "var(--text-1)" }}>{value}</div>
</div>
);
}
@@ -47,7 +47,7 @@ export function MigrationPanel({
<p className="page-sub" style={{ marginBottom: 0 }}>{reports.length} migration {reports.length === 1 ? "report" : "reports"}.</p>
</div>
<div style={{ marginLeft: "auto" }}>
<Button tone="primary" onClick={() => setOpen(true)}><Icon name="plus" size={13} /> Report</Button>
<Button tone="primary" onClick={() => setOpen(true)}><Icon name="plus" size={16} /> Report</Button>
</div>
</div>
{reports.length > 0 && (
@@ -67,7 +67,7 @@ export function MigrationPanel({
<section className="card" style={{ marginTop: 16, padding: 0, overflow: "hidden" }}>
<div className="row" style={{ padding: "14px 16px", borderBottom: "1px solid var(--border-soft)" }}>
<Icon name="refresh" size={14} color="var(--text-3)" />
<div style={{ fontSize: 13, fontWeight: 600 }}>Rollback snapshots</div>
<div style={{ fontSize: 14, fontWeight: 600 }}>Rollback snapshots</div>
</div>
{rollbackSnapshots.length > 0 ? rollbackSnapshots.map((snapshot, index) => (
<RollbackRow
@@ -83,7 +83,7 @@ export function MigrationPanel({
<section className="card" style={{ marginTop: 16, padding: 0, overflow: "hidden" }}>
<div className="row" style={{ padding: "14px 16px", borderBottom: "1px solid var(--border-soft)" }}>
<Icon name="list" size={14} color="var(--text-3)" />
<div style={{ fontSize: 13, fontWeight: 600 }}>Reconciliation</div>
<div style={{ fontSize: 14, fontWeight: 600 }}>Reconciliation</div>
</div>
{reconciliationItems.length > 0 ? reconciliationItems.map((item, index) => (
<ReconciliationRow
@@ -125,7 +125,7 @@ function ReportRow({
>
<div style={{ minWidth: 0 }}>
<div style={{ fontWeight: 540, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }} title={report.sourceRef}>{report.sourceRef}</div>
<div style={{ fontSize: 11, color: "var(--text-3)" }}>{formatRelative(report.createdAt)}</div>
<div style={{ fontSize: 12, color: "var(--text-3)" }}>{formatRelative(report.createdAt)}</div>
</div>
<div className="row" style={{ flexWrap: "wrap", gap: 4 }}>
{Object.entries(body.tableCounts).map(([table, count]) => (
@@ -169,7 +169,7 @@ function RollbackRow({
>
<div style={{ minWidth: 0 }}>
<div style={{ fontWeight: 540, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }} title={snapshot.sourceDatabasePath}>{snapshot.sourceDatabasePath}</div>
<div style={{ fontSize: 11, color: "var(--text-3)" }}>{formatRelative(snapshot.createdAt)}</div>
<div style={{ fontSize: 12, color: "var(--text-3)" }}>{formatRelative(snapshot.createdAt)}</div>
</div>
<Pill>{snapshot.sourceDatabaseSha256.slice(0, 12)}</Pill>
<Pill>{manifest.workspaces.length} workspaces</Pill>
@@ -206,7 +206,7 @@ function ReconciliationRow({
>
<div style={{ minWidth: 0 }}>
<div style={{ fontWeight: 540, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{item.targetType} · {item.targetId}</div>
<div style={{ fontSize: 11, color: "var(--text-3)" }}>{formatRelative(item.createdAt)}</div>
<div style={{ fontSize: 12, color: "var(--text-3)" }}>{formatRelative(item.createdAt)}</div>
</div>
<div style={{ fontSize: 12, color: "var(--text-2)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{item.reason}</div>
<Pill tone={resolved ? "green" : "amber"}>{item.state}</Pill>
@@ -22,7 +22,7 @@ export function ProviderConnectFields({
if (entry.authType === "api_key") {
return (
<>
<p style={{ fontSize: 12.5, color: "var(--text-3)", lineHeight: 1.5, margin: 0 }}>{entry.credentialHelp}</p>
<p style={{ fontSize: 12, color: "var(--text-3)", lineHeight: 1.5, margin: 0 }}>{entry.credentialHelp}</p>
<Field label="API key"><input className="input" name="secret" type="password" required autoFocus /></Field>
<ModelPicker entry={entry} provider={provider} />
</>
@@ -50,7 +50,7 @@ export function ProviderOAuthFields({
const [model, setModel] = useState(provider.model ?? entry.defaultModel ?? entry.models[0]?.id ?? "");
return (
<>
<p style={{ fontSize: 12.5, color: "var(--text-3)", lineHeight: 1.5, margin: 0 }}>{entry.credentialHelp}</p>
<p style={{ fontSize: 12, color: "var(--text-3)", lineHeight: 1.5, margin: 0 }}>{entry.credentialHelp}</p>
<Field label="Default model">
{entry.models.length ? (
<select className="input" value={model} onChange={(event) => setModel(event.target.value)}>
@@ -77,7 +77,7 @@ function CompatFieldsForm({ entry, provider }: { entry: ProviderCatalogEntry; pr
const [baseUrl, setBaseUrl] = useState("");
return (
<>
<p style={{ fontSize: 12.5, color: "var(--text-3)", lineHeight: 1.5, margin: 0 }}>{entry.credentialHelp}</p>
<p style={{ fontSize: 12, color: "var(--text-3)", lineHeight: 1.5, margin: 0 }}>{entry.credentialHelp}</p>
<Field label="Base URL">
<input
className="input"
@@ -139,7 +139,7 @@ function CloudFieldsForm({ entry, provider }: { entry: ProviderCatalogEntry; pro
const update = (patch: Partial<CloudFields>) => setState((current) => ({ ...current, ...patch }));
return (
<>
<p style={{ fontSize: 12.5, color: "var(--text-3)", lineHeight: 1.5, margin: 0 }}>{entry.credentialHelp}</p>
<p style={{ fontSize: 12, color: "var(--text-3)", lineHeight: 1.5, margin: 0 }}>{entry.credentialHelp}</p>
<Field label="Base URL">
<input className="input" name="cloudBaseUrl" value={state.baseUrl} onChange={(event) => update({ baseUrl: event.target.value })} />
</Field>
@@ -105,7 +105,7 @@ export function ProviderRequestPanel({
</div>
<Button type="submit" tone="primary">
<span className="row" style={{ gap: 6 }}>
<Icon name="send" size={13} />
<Icon name="send" size={16} />
Run
</span>
</Button>
@@ -169,7 +169,7 @@ function ProviderRequestRow({
>
<div style={{ minWidth: 0 }}>
<div style={{ fontWeight: 540, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{provider.label}</div>
<div className="mono" style={{ fontSize: 11, color: "var(--text-3)" }}>{request.model}</div>
<div className="mono" style={{ fontSize: 12, color: "var(--text-3)" }}>{request.model}</div>
</div>
<div className="mono" style={{ color: "var(--text-2)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{workspace?.name ?? "Organization"}</div>
<div className="mono" style={{ color: "var(--text-2)" }}>{request.executionMode}</div>
@@ -302,8 +302,8 @@ function ProviderRow({
</div>
<ProviderHealth provider={provider} />
<div style={{ textAlign: "right", minWidth: 120 }}>
<div className="num mono" style={{ fontSize: 13, fontWeight: 540 }}>{boundCount} {boundCount === 1 ? "agent" : "agents"}</div>
<div className="mono" style={{ fontSize: 11, color: "var(--text-3)" }}>bound</div>
<div className="num mono" style={{ fontSize: 14, fontWeight: 540 }}>{boundCount} {boundCount === 1 ? "agent" : "agents"}</div>
<div className="mono" style={{ fontSize: 12, color: "var(--text-3)" }}>bound</div>
</div>
<Button onClick={onCheck}>Check</Button>
<Button onClick={onManage}>Manage</Button>
@@ -53,7 +53,7 @@ export function SkillsPanel({ orgId, skills, revisions, bindings, tests, agents,
</p>
</div>
<div style={{ marginLeft: "auto" }}>
<Button tone="primary" onClick={() => setImportOpen(true)}><Icon name="plus" size={13} /> Import</Button>
<Button tone="primary" onClick={() => setImportOpen(true)}><Icon name="plus" size={16} /> Import</Button>
</div>
</div>
@@ -77,7 +77,7 @@ export function SkillsPanel({ orgId, skills, revisions, bindings, tests, agents,
>
<div style={{ minWidth: 0 }}>
<div style={{ fontWeight: 540, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{skill.name}</div>
<div style={{ color: "var(--text-3)", fontSize: 11 }}>{skill.slug}</div>
<div style={{ color: "var(--text-3)", fontSize: 12 }}>{skill.slug}</div>
</div>
<Pill>{latest ? latest.versionSemver : "—"}</Pill>
<Pill>{testSummary(revisionTests)}</Pill>
@@ -71,7 +71,7 @@ export function WorkspacePanel({
<div className="card" style={{ padding: 18 }}>
<div className="row" style={{ marginBottom: 12 }}>
<div className="section-label">Workspaces</div>
<span style={{ marginLeft: "auto" }}><Button tone="ghost" onClick={() => setCreateOpen(true)}><Icon name="plus" size={13} /> Add</Button></span>
<span style={{ marginLeft: "auto" }}><Button tone="ghost" onClick={() => setCreateOpen(true)}><Icon name="plus" size={16} /> Add</Button></span>
</div>
{workspaces.map((workspace) => (
<div key={workspace.id} className="row" style={{ padding: "8px 0", borderBottom: "1px solid var(--border-soft)" }}>
@@ -84,7 +84,7 @@ export function WorkspacePanel({
</div>
</div>
))}
{workspaces.length === 0 && <div style={{ fontSize: 13, color: "var(--text-3)" }}>No workspaces configured</div>}
{workspaces.length === 0 && <div style={{ fontSize: 14, color: "var(--text-3)" }}>No workspaces configured</div>}
</div>
<Dialog title="Add workspace" open={createOpen} submitLabel="Create" onClose={() => setCreateOpen(false)} onSubmit={submit}>
@@ -96,7 +96,7 @@ export function WorkspacePanel({
const form = document.querySelector<HTMLFormElement>("form:has([name='localPath'])");
if (form) void chooseDirectory(form);
}}>
<Icon name="folder" size={13} /> Browse
<Icon name="folder" size={16} /> Browse
</Button>
</div>
</Field>
@@ -82,7 +82,7 @@ export function SocialActivity({
</span>
<span style={{ color: "var(--text-3)", fontSize: 12 }}>{accountHandle(grant.socialAccountId)}</span>
<Pill tone="violet">{humanize(grant.role)}</Pill>
<span style={{ marginLeft: "auto", fontSize: 11, color: "var(--text-3)" }}>{scopeSummary(grant.scopeJson)}</span>
<span style={{ marginLeft: "auto", fontSize: 12, color: "var(--text-3)" }}>{scopeSummary(grant.scopeJson)}</span>
</div>
))}
</div>
@@ -95,10 +95,10 @@ export function SocialActivity({
className="row"
style={{ gap: 10, padding: "10px 16px", borderBottom: index === entries.length - 1 ? "none" : "1px solid var(--border-soft)" }}
>
<span style={{ fontSize: 12.5, fontWeight: 500 }}>{entry.label}</span>
<span style={{ fontSize: 12, fontWeight: 500 }}>{entry.label}</span>
<span style={{ fontSize: 12, color: "var(--text-3)" }}>{accountHandle(entry.accountId)}</span>
<Pill tone={policyTone(entry.policyDecision)}>{humanize(entry.policyDecision)}</Pill>
<span style={{ marginLeft: "auto", fontSize: 11, color: "var(--text-3)" }}>
<span style={{ marginLeft: "auto", fontSize: 12, color: "var(--text-3)" }}>
{entry.actorType === "agent" ? "agent" : employeeName(entry.actorId)} · {formatRelative(entry.createdAt)}
</span>
</div>
@@ -55,7 +55,7 @@ export function SocialCalendar({
alignItems: "center",
justifyContent: "center",
gap: 3,
fontSize: 11,
fontSize: 12,
color: cell.inMonth ? "var(--text-2)" : "var(--text-4)",
fontWeight: isToday ? 600 : 480,
background: isToday ? "var(--text-1)" : "transparent",
@@ -82,7 +82,7 @@ export function SocialCalendar({
);
})}
</div>
<div className="row" style={{ marginTop: 16, fontSize: 11, color: "var(--text-3)", gap: 10 }}>
<div className="row" style={{ marginTop: 16, fontSize: 12, color: "var(--text-3)", gap: 10 }}>
<Legend label="X" color="var(--accent)" />
<Legend label="LinkedIn" color="var(--green)" />
<Legend label="YouTube" color="var(--amber)" />
@@ -54,12 +54,12 @@ export function HiringPipeline({ agents, approvals }: { agents: AgentRecord[]; a
<div className="row" style={{ gap: 8 }}>
<Avatar name={entry.agent.name} size="sm" bot />
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ fontSize: 12.5, fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{entry.agent.name}</div>
<div style={{ fontSize: 11, color: "var(--text-3)" }}>{entry.agent.role} · {entry.agent.department}</div>
<div style={{ fontSize: 12, fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{entry.agent.name}</div>
<div style={{ fontSize: 12, color: "var(--text-3)" }}>{entry.agent.role} · {entry.agent.department}</div>
</div>
</div>
{entry.approval && (
<div style={{ marginTop: 6, fontSize: 11, color: "var(--text-3)" }}>
<div style={{ marginTop: 6, fontSize: 12, color: "var(--text-3)" }}>
{formatRelative(entry.approval.createdAt)}
</div>
)}
@@ -121,9 +121,9 @@ export function TaskDetailDialog({
)}
<div className="modal-actions">
<Button tone="ghost" onClick={deleteTask}><Icon name="x" size={13} /> Delete</Button>
{assignee && <Button onClick={() => onRun(task)} disabled={!canRun(provider)}><Icon name="send" size={13} /> Run</Button>}
{advanceTo && <Button tone="primary" onClick={() => onAdvance(task)}><Icon name="check" size={13} /> {prettyStatus(advanceTo)}</Button>}
<Button tone="ghost" onClick={deleteTask}><Icon name="x" size={16} /> Delete</Button>
{assignee && <Button onClick={() => onRun(task)} disabled={!canRun(provider)}><Icon name="send" size={16} /> Run</Button>}
{advanceTo && <Button tone="primary" onClick={() => onAdvance(task)}><Icon name="check" size={16} /> {prettyStatus(advanceTo)}</Button>}
</div>
{editing && <EditOverlay task={task} agents={agents} allTasks={allTasks} onSubmit={submitEdit} onCancel={() => setEditing(false)} />}
@@ -140,9 +140,9 @@ function OverviewTab({ task, assignee, project, goal, workspace, provider, runs
return (
<>
{task.description && (
<p style={{ margin: "0 0 14px", color: "var(--text-2)", fontSize: 13, lineHeight: 1.55, whiteSpace: "pre-wrap" }}>{task.description}</p>
<p style={{ margin: "0 0 14px", color: "var(--text-2)", fontSize: 14, lineHeight: 1.55, whiteSpace: "pre-wrap" }}>{task.description}</p>
)}
<div style={{ display: "grid", gridTemplateColumns: "100px 1fr", gap: "8px 14px", fontSize: 12.5 }}>
<div style={{ display: "grid", gridTemplateColumns: "100px 1fr", gap: "8px 14px", fontSize: 12 }}>
<MetaLabel>Assignee</MetaLabel>
<div className="row" style={{ gap: 8 }}>
{assignee ? (<><Avatar name={assignee.name} size="sm" bot /><span>{assignee.name}</span>{provider && <span style={{ color: "var(--text-3)" }}>({provider.label})</span>}</>) : <span style={{ color: "var(--text-4)" }}>Unassigned</span>}
@@ -177,13 +177,13 @@ function OverviewTab({ task, assignee, project, goal, workspace, provider, runs
function SubtasksTab({ subtasks, agents }: { subtasks: TaskRecord[]; agents: AgentRecord[] }) {
return (
<div style={{ minHeight: 60 }}>
{subtasks.length === 0 && <div style={{ fontSize: 13, color: "var(--text-3)" }}>No subtasks</div>}
{subtasks.length === 0 && <div style={{ fontSize: 14, color: "var(--text-3)" }}>No subtasks</div>}
{subtasks.map((st) => {
const owner = agents.find((a) => a.id === st.assigneeAgentId);
return (
<div key={st.id} className="row" style={{ gap: 10, padding: "8px 0", borderBottom: "1px solid var(--border-soft)" }}>
<Icon name={st.status === TASK_STATUS.DONE ? "check" : "work"} size={13} color={st.status === TASK_STATUS.DONE ? "var(--green)" : "var(--text-3)"} />
<span style={{ flex: 1, fontSize: 13, fontWeight: 480, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{st.title}</span>
<Icon name={st.status === TASK_STATUS.DONE ? "check" : "work"} size={16} color={st.status === TASK_STATUS.DONE ? "var(--green)" : "var(--text-3)"} />
<span style={{ flex: 1, fontSize: 14, fontWeight: 480, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{st.title}</span>
<Pill>{prettyStatus(st.status)}</Pill>
{owner && <Avatar name={owner.name} size="sm" bot />}
</div>
@@ -202,18 +202,18 @@ function ActivityTab({ audit, approvals }: { audit: AuditEventRecord[]; approval
{approvals.map((a) => (
<div key={a.id} className="row" style={{ gap: 8, padding: "6px 0" }}>
<Pill tone={a.state === "approved" ? "green" : a.state === "pending" ? "amber" : "red"}>{a.state}</Pill>
<span style={{ fontSize: 12.5 }}>{a.title}</span>
<span className="mono" style={{ marginLeft: "auto", fontSize: 11, color: "var(--text-3)" }}>{formatRelative(a.createdAt)}</span>
<span style={{ fontSize: 12 }}>{a.title}</span>
<span className="mono" style={{ marginLeft: "auto", fontSize: 12, color: "var(--text-3)" }}>{formatRelative(a.createdAt)}</span>
</div>
))}
</div>
)}
<div className="section-label">Events</div>
{audit.length === 0 && <div style={{ fontSize: 13, color: "var(--text-3)" }}>No events</div>}
{audit.length === 0 && <div style={{ fontSize: 14, color: "var(--text-3)" }}>No events</div>}
{audit.map((e) => (
<div key={e.id} className="row" style={{ gap: 8, padding: "5px 0" }}>
<span className="mono" style={{ fontSize: 11, color: "var(--text-3)", flexShrink: 0 }}>{formatRelative(e.createdAt)}</span>
<span style={{ fontSize: 12.5, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{auditEventLabel(e.entityType, e.action)}</span>
<span className="mono" style={{ fontSize: 12, color: "var(--text-3)", flexShrink: 0 }}>{formatRelative(e.createdAt)}</span>
<span style={{ fontSize: 12, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{auditEventLabel(e.entityType, e.action)}</span>
</div>
))}
</div>
@@ -116,10 +116,10 @@ export function SearchDialog({
>
<Pill>{LABELS[result.entityType]}</Pill>
<div style={{ flex: 1, minWidth: 0 }}>
<div style={{ fontSize: 13, fontWeight: 540, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{result.title}</div>
<div style={{ fontSize: 14, fontWeight: 540, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{result.title}</div>
<div style={{ fontSize: 12, color: "var(--text-3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{result.preview}</div>
</div>
<span style={{ fontSize: 11, color: "var(--text-3)" }}>{result.facets.type}</span>
<span style={{ fontSize: 12, color: "var(--text-3)" }}>{result.facets.type}</span>
</button>
))}
</div>