| author | |
| committer | |
| log | f26ee083fe41720207fb10616359500dcecc19d3 |
| tree | c0668ed670d5c836eb9c1a00979e38a5d66a1435 |
| parent | 315fcca10a826d8aa1cbdffc3ef5b5eb5a1e2f9d |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>109 files changed, 464 insertions(+), 433 deletions(-)
apps/web/src/browser/BrowserDeviceToolbar.tsx+1-1| ... | @@ -175,7 +175,7 @@ export function BrowserDeviceToolbar({ | ... | @@ -175,7 +175,7 @@ export function BrowserDeviceToolbar({ |
| 175 | }} | 175 | }} |
| 176 | > | 176 | > |
| 177 | {width >= 560 ? ( | 177 | {width >= 560 ? ( |
| 178 | <span className="mr-0.5 shrink-0 text-[11px] font-medium text-muted-foreground"> | 178 | <span className="mr-0.5 shrink-0 text-2xs font-medium text-muted-foreground"> |
| 179 | Dimensions | 179 | Dimensions |
| 180 | </span> | 180 | </span> |
| 181 | ) : null} | 181 | ) : null} |
apps/web/src/browser/HostedBrowserWebview.tsx+1-1| ... | @@ -352,7 +352,7 @@ export function HostedBrowserWebview(props: { | ... | @@ -352,7 +352,7 @@ export function HostedBrowserWebview(props: { |
| 352 | /> | 352 | /> |
| 353 | {activeDrag ? ( | 353 | {activeDrag ? ( |
| 354 | <div | 354 | <div |
| 355 | className="pointer-events-none absolute z-40 -translate-x-1/2 rounded-md border border-border/80 bg-background/95 px-2 py-1 text-[11px] font-medium tabular-nums text-foreground shadow-md backdrop-blur-sm" | 355 | className="pointer-events-none absolute z-40 -translate-x-1/2 rounded-md border border-border/80 bg-background/95 px-2 py-1 text-2xs font-medium tabular-nums text-foreground shadow-md backdrop-blur-sm" |
| 356 | style={{ | 356 | style={{ |
| 357 | left: layout.viewportX + layout.viewportWidth / 2, | 357 | left: layout.viewportX + layout.viewportWidth / 2, |
| 358 | top: layout.viewportY + 10, | 358 | top: layout.viewportY + 10, |
apps/web/src/components/AgentsPanel.tsx+12-12| ... | @@ -162,12 +162,12 @@ function AgentRow({ agent }: { agent: RuntimeSubagent }) { | ... | @@ -162,12 +162,12 @@ function AgentRow({ agent }: { agent: RuntimeSubagent }) { |
| 162 | <span className="col-start-2 row-start-1 flex min-w-0 items-baseline gap-2"> | 162 | <span className="col-start-2 row-start-1 flex min-w-0 items-baseline gap-2"> |
| 163 | <span className="min-w-0 truncate text-sm font-medium">{agent.title}</span> | 163 | <span className="min-w-0 truncate text-sm font-medium">{agent.title}</span> |
| 164 | {role ? ( | 164 | {role ? ( |
| 165 | <span className="max-w-28 shrink-0 truncate rounded-sm border border-border/60 px-1 font-mono text-[.65rem] text-muted-foreground"> | 165 | <span className="max-w-28 shrink-0 truncate rounded-sm border border-border/60 px-1 font-mono text-3xs text-muted-foreground"> |
| 166 | {role} | 166 | {role} |
| 167 | </span> | 167 | </span> |
| 168 | ) : null} | 168 | ) : null} |
| 169 | </span> | 169 | </span> |
| 170 | <span className="col-start-3 row-start-1 min-w-14 text-right font-mono text-[.7rem] text-muted-foreground/80"> | 170 | <span className="col-start-3 row-start-1 min-w-14 text-right font-mono text-2xs text-muted-foreground/80"> |
| 171 | <span className="inline-flex items-center gap-1"> | 171 | <span className="inline-flex items-center gap-1"> |
| 172 | <AgentElapsed agent={agent} /> | 172 | <AgentElapsed agent={agent} /> |
| 173 | {agent.status === "completed" ? ( | 173 | {agent.status === "completed" ? ( |
| ... | @@ -183,7 +183,7 @@ function AgentRow({ agent }: { agent: RuntimeSubagent }) { | ... | @@ -183,7 +183,7 @@ function AgentRow({ agent }: { agent: RuntimeSubagent }) { |
| 183 | > | 183 | > |
| 184 | {activity ?? statusLabel} | 184 | {activity ?? statusLabel} |
| 185 | </span> | 185 | </span> |
| 186 | <span className="col-start-2 col-end-4 row-start-3 truncate font-mono text-[.7rem] tabular-nums text-muted-foreground/70"> | 186 | <span className="col-start-2 col-end-4 row-start-3 truncate font-mono text-2xs tabular-nums text-muted-foreground/70"> |
| 187 | {metadata.join(" · ")} | 187 | {metadata.join(" · ")} |
| 188 | </span> | 188 | </span> |
| 189 | <span className="sr-only">{statusLabel}</span> | 189 | <span className="sr-only">{statusLabel}</span> |
| ... | @@ -234,7 +234,7 @@ function PhaseRail({ group }: { group: AgentPanelWorkflowGroup }) { | ... | @@ -234,7 +234,7 @@ function PhaseRail({ group }: { group: AgentPanelWorkflowGroup }) { |
| 234 | > | 234 | > |
| 235 | <span | 235 | <span |
| 236 | className={cn( | 236 | className={cn( |
| 237 | "font-mono text-[.65rem]", | 237 | "font-mono text-3xs", |
| 238 | phase.state === "running" | 238 | phase.state === "running" |
| 239 | ? "text-info-foreground" | 239 | ? "text-info-foreground" |
| 240 | : phase.state === "done" | 240 | : phase.state === "done" |
| ... | @@ -247,7 +247,7 @@ function PhaseRail({ group }: { group: AgentPanelWorkflowGroup }) { | ... | @@ -247,7 +247,7 @@ function PhaseRail({ group }: { group: AgentPanelWorkflowGroup }) { |
| 247 | </span> | 247 | </span> |
| 248 | <span className="flex items-center gap-0.5"> | 248 | <span className="flex items-center gap-0.5"> |
| 249 | {phase.members.length === 0 ? ( | 249 | {phase.members.length === 0 ? ( |
| 250 | <span className="font-mono text-[.6rem] text-muted-foreground/50">–</span> | 250 | <span className="font-mono text-3xs text-muted-foreground/50">–</span> |
| 251 | ) : ( | 251 | ) : ( |
| 252 | phase.members.map((member) => <StatusDot key={member.id} status={member.status} />) | 252 | phase.members.map((member) => <StatusDot key={member.id} status={member.status} />) |
| 253 | )} | 253 | )} |
| ... | @@ -281,7 +281,7 @@ function WorkflowScriptView({ | ... | @@ -281,7 +281,7 @@ function WorkflowScriptView({ |
| 281 | <div className="mx-1.5 mb-1 rounded-md border border-border/60 bg-background/60"> | 281 | <div className="mx-1.5 mb-1 rounded-md border border-border/60 bg-background/60"> |
| 282 | <div className="flex items-center gap-2 border-b border-border/50 px-2 py-1"> | 282 | <div className="flex items-center gap-2 border-b border-border/50 px-2 py-1"> |
| 283 | <Braces aria-hidden className="size-3 text-muted-foreground" /> | 283 | <Braces aria-hidden className="size-3 text-muted-foreground" /> |
| 284 | <span className="truncate font-mono text-[.65rem] text-muted-foreground"> | 284 | <span className="truncate font-mono text-3xs text-muted-foreground"> |
| 285 | {scriptPath.split("/").at(-1)} | 285 | {scriptPath.split("/").at(-1)} |
| 286 | </span> | 286 | </span> |
| 287 | <Button | 287 | <Button |
| ... | @@ -296,7 +296,7 @@ function WorkflowScriptView({ | ... | @@ -296,7 +296,7 @@ function WorkflowScriptView({ |
| 296 | </div> | 296 | </div> |
| 297 | <div className="max-h-72 overflow-auto p-2"> | 297 | <div className="max-h-72 overflow-auto p-2"> |
| 298 | {result._tag === "Success" ? ( | 298 | {result._tag === "Success" ? ( |
| 299 | <pre className="whitespace-pre-wrap break-words font-mono text-[.7rem] leading-relaxed text-foreground/90"> | 299 | <pre className="whitespace-pre-wrap break-words font-mono text-2xs leading-relaxed text-foreground/90"> |
| 300 | {result.value.contents} | 300 | {result.value.contents} |
| 301 | {result.value.truncated ? "\n… (truncated)" : ""} | 301 | {result.value.truncated ? "\n… (truncated)" : ""} |
| 302 | </pre> | 302 | </pre> |
| ... | @@ -339,7 +339,7 @@ function PhaseSection({ | ... | @@ -339,7 +339,7 @@ function PhaseSection({ |
| 339 | onClick={() => setOpen((value) => !value)} | 339 | onClick={() => setOpen((value) => !value)} |
| 340 | aria-expanded={open} | 340 | aria-expanded={open} |
| 341 | className={cn( | 341 | className={cn( |
| 342 | "mt-2 flex w-full items-center gap-1.5 rounded-sm px-1.5 text-left text-[.65rem] font-medium uppercase tracking-wider hover:bg-accent/40", | 342 | "mt-2 flex w-full items-center gap-1.5 rounded-sm px-1.5 text-left text-3xs font-medium uppercase tracking-wider hover:bg-accent/40", |
| 343 | phase.state === "done" | 343 | phase.state === "done" |
| 344 | ? "text-success-foreground" | 344 | ? "text-success-foreground" |
| 345 | : phase.state === "running" | 345 | : phase.state === "running" |
| ... | @@ -399,7 +399,7 @@ function ExpandedWorkflowSection({ | ... | @@ -399,7 +399,7 @@ function ExpandedWorkflowSection({ |
| 399 | const canShowScript = scriptPath !== undefined && environmentId !== null && threadId !== null; | 399 | const canShowScript = scriptPath !== undefined && environmentId !== null && threadId !== null; |
| 400 | return ( | 400 | return ( |
| 401 | <section className="rounded-lg border border-border/50 bg-card/30 p-1.5"> | 401 | <section className="rounded-lg border border-border/50 bg-card/30 p-1.5"> |
| 402 | <div className="flex items-center gap-2 px-1.5 pt-0.5 text-[.65rem] font-medium uppercase tracking-wider text-muted-foreground"> | 402 | <div className="flex items-center gap-2 px-1.5 pt-0.5 text-3xs font-medium uppercase tracking-wider text-muted-foreground"> |
| 403 | <StatusDot status={group.workflow.status} /> | 403 | <StatusDot status={group.workflow.status} /> |
| 404 | <span className="min-w-0 truncate"> | 404 | <span className="min-w-0 truncate"> |
| 405 | {group.workflow.workflowName ?? group.workflow.title} | 405 | {group.workflow.workflowName ?? group.workflow.title} |
| ... | @@ -486,7 +486,7 @@ function CollapsedWorkflowSection({ | ... | @@ -486,7 +486,7 @@ function CollapsedWorkflowSection({ |
| 486 | <span className="truncate text-sm"> | 486 | <span className="truncate text-sm"> |
| 487 | {group.workflow.workflowName ?? group.workflow.title} | 487 | {group.workflow.workflowName ?? group.workflow.title} |
| 488 | </span> | 488 | </span> |
| 489 | <span className="ml-auto flex items-center gap-1.5 font-mono text-[.7rem] text-muted-foreground/80"> | 489 | <span className="ml-auto flex items-center gap-1.5 font-mono text-2xs text-muted-foreground/80"> |
| 490 | {failed > 0 ? <span className="text-destructive-foreground">{failed} failed</span> : null} | 490 | {failed > 0 ? <span className="text-destructive-foreground">{failed} failed</span> : null} |
| 491 | <span>{members.length} agents</span> | 491 | <span>{members.length} agents</span> |
| 492 | <span className="tabular-nums">· {formatSubagentTokenCount(totalTokens)} tok</span> | 492 | <span className="tabular-nums">· {formatSubagentTokenCount(totalTokens)} tok</span> |
| ... | @@ -557,7 +557,7 @@ export function AgentsPanel({ | ... | @@ -557,7 +557,7 @@ export function AgentsPanel({ |
| 557 | ))} | 557 | ))} |
| 558 | {model.directAgents.length > 0 ? ( | 558 | {model.directAgents.length > 0 ? ( |
| 559 | <section> | 559 | <section> |
| 560 | <div className="px-1.5 pt-1 text-[.65rem] font-medium uppercase tracking-wider text-muted-foreground"> | 560 | <div className="px-1.5 pt-1 text-3xs font-medium uppercase tracking-wider text-muted-foreground"> |
| 561 | Direct spawns | 561 | Direct spawns |
| 562 | </div> | 562 | </div> |
| 563 | {model.directAgents.map((agent) => ( | 563 | {model.directAgents.map((agent) => ( |
| ... | @@ -567,7 +567,7 @@ export function AgentsPanel({ | ... | @@ -567,7 +567,7 @@ export function AgentsPanel({ |
| 567 | ) : null} | 567 | ) : null} |
| 568 | </div> | 568 | </div> |
| 569 | </ScrollArea> | 569 | </ScrollArea> |
| 570 | <footer className="flex items-center justify-between border-t border-border/60 px-3 py-1.5 font-mono text-[.7rem] text-muted-foreground"> | 570 | <footer className="flex items-center justify-between border-t border-border/60 px-3 py-1.5 font-mono text-2xs text-muted-foreground"> |
| 571 | <span className="flex items-center gap-2"> | 571 | <span className="flex items-center gap-2"> |
| 572 | {model.runningCount + model.waitingCount > 0 ? ( | 572 | {model.runningCount + model.waitingCount > 0 ? ( |
| 573 | <span className="text-info-foreground"> | 573 | <span className="text-info-foreground"> |
apps/web/src/components/BranchToolbar.tsx+2-2| ... | @@ -185,7 +185,7 @@ const MobileRunContextSelector = memo(function MobileRunContextSelector({ | ... | @@ -185,7 +185,7 @@ const MobileRunContextSelector = memo(function MobileRunContextSelector({ |
| 185 | > | 185 | > |
| 186 | <span | 186 | <span |
| 187 | data-composer-label-motion | 187 | data-composer-label-motion |
| 188 | className="block w-full min-w-0 max-w-[240px] truncate transition-opacity duration-180 ease-[cubic-bezier(0.32,0.72,0,1)] group-data-[compact]/composer-context:opacity-0 motion-reduce:transition-none" | 188 | className="block w-full min-w-0 max-w-[240px] truncate transition-opacity duration-180 ease-drawer group-data-[compact]/composer-context:opacity-0 motion-reduce:transition-none" |
| 189 | > | 189 | > |
| 190 | {autoEnvironmentLabel ?? | 190 | {autoEnvironmentLabel ?? |
| 191 | (showEnvironmentIndicator ? (activeEnvironment?.label ?? "Run on") : workspaceLabel)} | 191 | (showEnvironmentIndicator ? (activeEnvironment?.label ?? "Run on") : workspaceLabel)} |
| ... | @@ -197,7 +197,7 @@ const MobileRunContextSelector = memo(function MobileRunContextSelector({ | ... | @@ -197,7 +197,7 @@ const MobileRunContextSelector = memo(function MobileRunContextSelector({ |
| 197 | if (isLocked) { | 197 | if (isLocked) { |
| 198 | return ( | 198 | return ( |
| 199 | <span | 199 | <span |
| 200 | className="inline-flex h-7 min-w-0 max-w-[48%] flex-initial items-center justify-start gap-1 rounded-md border border-transparent px-[calc(--spacing(2)-1px)] font-normal text-muted-foreground/70 text-xs sm:h-6" | 200 | className="inline-flex h-7 min-w-0 max-w-[48%] flex-initial items-center justify-start gap-1 rounded-md border border-transparent px-1.75 font-normal text-muted-foreground/70 text-xs sm:h-6" |
| 201 | data-composer-context-control | 201 | data-composer-context-control |
| 202 | > | 202 | > |
| 203 | {triggerContent} | 203 | {triggerContent} |
apps/web/src/components/BranchToolbarBranchSelector.tsx+2-2| ... | @@ -757,7 +757,7 @@ export function BranchToolbarBranchSelector({ | ... | @@ -757,7 +757,7 @@ export function BranchToolbarBranchSelector({ |
| 757 | > | 757 | > |
| 758 | <div className="flex w-full min-w-0 items-center justify-between gap-2"> | 758 | <div className="flex w-full min-w-0 items-center justify-between gap-2"> |
| 759 | <MiddleTruncate value={itemValue} className="flex-1" /> | 759 | <MiddleTruncate value={itemValue} className="flex-1" /> |
| 760 | {badge && <span className="shrink-0 text-[10px] text-muted-foreground/45">{badge}</span>} | 760 | {badge && <span className="shrink-0 text-3xs text-muted-foreground/45">{badge}</span>} |
| 761 | </div> | 761 | </div> |
| 762 | </ComboboxItem> | 762 | </ComboboxItem> |
| 763 | ); | 763 | ); |
| ... | @@ -819,7 +819,7 @@ export function BranchToolbarBranchSelector({ | ... | @@ -819,7 +819,7 @@ export function BranchToolbarBranchSelector({ |
| 819 | > | 819 | > |
| 820 | <span | 820 | <span |
| 821 | data-composer-label-motion | 821 | data-composer-label-motion |
| 822 | className="flex w-full max-w-[240px] transition-opacity duration-180 ease-[cubic-bezier(0.32,0.72,0,1)] group-data-[compact]/composer-context:opacity-0 motion-reduce:transition-none" | 822 | className="flex w-full max-w-[240px] transition-opacity duration-180 ease-drawer group-data-[compact]/composer-context:opacity-0 motion-reduce:transition-none" |
| 823 | > | 823 | > |
| 824 | <MiddleTruncate value={triggerLabel} /> | 824 | <MiddleTruncate value={triggerLabel} /> |
| 825 | </span> | 825 | </span> |
apps/web/src/components/BranchToolbarEnvModeSelector.tsx+3-3| ... | @@ -61,7 +61,7 @@ export const BranchToolbarEnvModeSelector = memo(function BranchToolbarEnvModeSe | ... | @@ -61,7 +61,7 @@ export const BranchToolbarEnvModeSelector = memo(function BranchToolbarEnvModeSe |
| 61 | <Tooltip> | 61 | <Tooltip> |
| 62 | <TooltipTrigger | 62 | <TooltipTrigger |
| 63 | render={<span />} | 63 | render={<span />} |
| 64 | className="inline-flex h-7 min-w-0 items-center gap-1 border border-transparent px-[calc(--spacing(2)-1px)] font-normal text-muted-foreground/70 text-xs sm:h-6" | 64 | className="inline-flex h-7 min-w-0 items-center gap-1 border border-transparent px-1.75 font-normal text-muted-foreground/70 text-xs sm:h-6" |
| 65 | data-composer-context-control | 65 | data-composer-context-control |
| 66 | > | 66 | > |
| 67 | {forceNewWorktree ? ( | 67 | {forceNewWorktree ? ( |
| ... | @@ -77,7 +77,7 @@ export const BranchToolbarEnvModeSelector = memo(function BranchToolbarEnvModeSe | ... | @@ -77,7 +77,7 @@ export const BranchToolbarEnvModeSelector = memo(function BranchToolbarEnvModeSe |
| 77 | > | 77 | > |
| 78 | <span | 78 | <span |
| 79 | data-composer-label-motion | 79 | data-composer-label-motion |
| 80 | className="block w-full min-w-0 max-w-[240px] truncate transition-opacity duration-180 ease-[cubic-bezier(0.32,0.72,0,1)] group-data-[compact]/composer-context:opacity-0 motion-reduce:transition-none" | 80 | className="block w-full min-w-0 max-w-[240px] truncate transition-opacity duration-180 ease-drawer group-data-[compact]/composer-context:opacity-0 motion-reduce:transition-none" |
| 81 | > | 81 | > |
| 82 | {forceNewWorktree | 82 | {forceNewWorktree |
| 83 | ? resolveEnvModeLabel("worktree") | 83 | ? resolveEnvModeLabel("worktree") |
| ... | @@ -133,7 +133,7 @@ export const BranchToolbarEnvModeSelector = memo(function BranchToolbarEnvModeSe | ... | @@ -133,7 +133,7 @@ export const BranchToolbarEnvModeSelector = memo(function BranchToolbarEnvModeSe |
| 133 | > | 133 | > |
| 134 | <span | 134 | <span |
| 135 | data-composer-label-motion | 135 | data-composer-label-motion |
| 136 | className="block w-full min-w-0 max-w-[240px] truncate transition-opacity duration-180 ease-[cubic-bezier(0.32,0.72,0,1)] group-data-[compact]/composer-context:opacity-0 motion-reduce:transition-none" | 136 | className="block w-full min-w-0 max-w-[240px] truncate transition-opacity duration-180 ease-drawer group-data-[compact]/composer-context:opacity-0 motion-reduce:transition-none" |
| 137 | > | 137 | > |
| 138 | <SelectValue /> | 138 | <SelectValue /> |
| 139 | </span> | 139 | </span> |
apps/web/src/components/BranchToolbarEnvironmentSelector.tsx+3-3| ... | @@ -63,7 +63,7 @@ export const BranchToolbarEnvironmentSelector = memo(function BranchToolbarEnvir | ... | @@ -63,7 +63,7 @@ export const BranchToolbarEnvironmentSelector = memo(function BranchToolbarEnvir |
| 63 | <Tooltip> | 63 | <Tooltip> |
| 64 | <TooltipTrigger | 64 | <TooltipTrigger |
| 65 | render={<span />} | 65 | render={<span />} |
| 66 | className="inline-flex h-7 min-w-0 max-w-full items-center gap-1 border border-transparent px-[calc(--spacing(2)-1px)] font-normal text-muted-foreground/70 text-xs sm:h-6" | 66 | className="inline-flex h-7 min-w-0 max-w-full items-center gap-1 border border-transparent px-1.75 font-normal text-muted-foreground/70 text-xs sm:h-6" |
| 67 | data-composer-context-control | 67 | data-composer-context-control |
| 68 | > | 68 | > |
| 69 | <EnvironmentMachineIcon | 69 | <EnvironmentMachineIcon |
| ... | @@ -76,7 +76,7 @@ export const BranchToolbarEnvironmentSelector = memo(function BranchToolbarEnvir | ... | @@ -76,7 +76,7 @@ export const BranchToolbarEnvironmentSelector = memo(function BranchToolbarEnvir |
| 76 | > | 76 | > |
| 77 | <span | 77 | <span |
| 78 | data-composer-label-motion | 78 | data-composer-label-motion |
| 79 | className="block w-full min-w-0 max-w-[240px] truncate transition-opacity duration-180 ease-[cubic-bezier(0.32,0.72,0,1)] group-data-[compact]/composer-context:opacity-0 motion-reduce:transition-none" | 79 | className="block w-full min-w-0 max-w-[240px] truncate transition-opacity duration-180 ease-drawer group-data-[compact]/composer-context:opacity-0 motion-reduce:transition-none" |
| 80 | > | 80 | > |
| 81 | {activeEnvironment?.label ?? "Run on"} | 81 | {activeEnvironment?.label ?? "Run on"} |
| 82 | </span> | 82 | </span> |
| ... | @@ -123,7 +123,7 @@ export const BranchToolbarEnvironmentSelector = memo(function BranchToolbarEnvir | ... | @@ -123,7 +123,7 @@ export const BranchToolbarEnvironmentSelector = memo(function BranchToolbarEnvir |
| 123 | > | 123 | > |
| 124 | <span | 124 | <span |
| 125 | data-composer-label-motion | 125 | data-composer-label-motion |
| 126 | className="block w-full min-w-0 max-w-[240px] truncate transition-opacity duration-180 ease-[cubic-bezier(0.32,0.72,0,1)] group-data-[compact]/composer-context:opacity-0 motion-reduce:transition-none" | 126 | className="block w-full min-w-0 max-w-[240px] truncate transition-opacity duration-180 ease-drawer group-data-[compact]/composer-context:opacity-0 motion-reduce:transition-none" |
| 127 | > | 127 | > |
| 128 | <SelectValue /> | 128 | <SelectValue /> |
| 129 | </span> | 129 | </span> |
apps/web/src/components/ChatMarkdown.tsx+3-3| ... | @@ -974,12 +974,12 @@ function MarkdownCodeBlock({ | ... | @@ -974,12 +974,12 @@ function MarkdownCodeBlock({ |
| 974 | 974 | ||
| 975 | return ( | 975 | return ( |
| 976 | <div | 976 | <div |
| 977 | className="chat-markdown-codeblock my-[0.65rem] overflow-hidden rounded-[var(--radius)] border border-border/70 bg-secondary leading-snug dark:border-transparent dark:bg-input/32" | 977 | className="chat-markdown-codeblock my-[0.65rem] overflow-hidden rounded-lg border border-border/70 bg-secondary leading-snug dark:border-transparent dark:bg-input/32" |
| 978 | data-language={language} | 978 | data-language={language} |
| 979 | data-wrap={wrapped ? "true" : "false"} | 979 | data-wrap={wrapped ? "true" : "false"} |
| 980 | > | 980 | > |
| 981 | <div className="chat-markdown-codeblock-header flex items-center justify-between gap-2 pt-1.5 pr-1.5 pb-0 pl-3 select-none"> | 981 | <div className="chat-markdown-codeblock-header flex items-center justify-between gap-2 pt-1.5 pr-1.5 pb-0 pl-3 select-none"> |
| 982 | <span className="inline-flex min-w-0 items-center gap-[0.4rem] [font-family:var(--font-mono,ui-monospace,SFMono-Regular,monospace)] [font-size:0.6875rem]"> | 982 | <span className="inline-flex min-w-0 items-center gap-1.5 font-mono text-2xs"> |
| 983 | <MarkdownCodeBlockTitleContent | 983 | <MarkdownCodeBlockTitleContent |
| 984 | fenceTitle={fenceTitle} | 984 | fenceTitle={fenceTitle} |
| 985 | language={language} | 985 | language={language} |
| ... | @@ -2201,7 +2201,7 @@ const MarkdownFileLink = memo(function MarkdownFileLink({ | ... | @@ -2201,7 +2201,7 @@ const MarkdownFileLink = memo(function MarkdownFileLink({ |
| 2201 | <TooltipPopup side="top" variant="code"> | 2201 | <TooltipPopup side="top" variant="code"> |
| 2202 | {/* The full path: the chip already shows the shortened form, and a link | 2202 | {/* The full path: the chip already shows the shortened form, and a link |
| 2203 | to the workspace root collapses to a bare label that repeats it. */} | 2203 | to the workspace root collapses to a bare label that repeats it. */} |
| 2204 | <div className="overflow-x-auto whitespace-nowrap [scrollbar-color:color-mix(in_srgb,var(--contrast-border)_78%,transparent)_transparent] [scrollbar-width:thin] [&::-webkit-scrollbar]:h-1.5 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-[color-mix(in_srgb,var(--contrast-border)_78%,transparent)] [&::-webkit-scrollbar-track]:bg-transparent"> | 2204 | <div className="overflow-x-auto whitespace-nowrap scrollbar-thumb-border/78 scrollbar-track-transparent [scrollbar-width:thin] [&::-webkit-scrollbar]:h-1.5 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-border/78 [&::-webkit-scrollbar-track]:bg-transparent"> |
| 2205 | {targetPath} | 2205 | {targetPath} |
| 2206 | </div> | 2206 | </div> |
| 2207 | </TooltipPopup> | 2207 | </TooltipPopup> |
apps/web/src/components/ChatView.tsx+3-3| ... | @@ -1220,7 +1220,7 @@ const PersistentThreadTerminalDrawer = memo(function PersistentThreadTerminalDra | ... | @@ -1220,7 +1220,7 @@ const PersistentThreadTerminalDrawer = memo(function PersistentThreadTerminalDra |
| 1220 | "grid shrink-0 overflow-clip", | 1220 | "grid shrink-0 overflow-clip", |
| 1221 | active ? (visible ? "grid-rows-[1fr]" : "grid-rows-[0fr]") : "hidden", | 1221 | active ? (visible ? "grid-rows-[1fr]" : "grid-rows-[0fr]") : "hidden", |
| 1222 | active && | 1222 | active && |
| 1223 | "[[data-panel-animations=true]_&]:transition-[grid-template-rows] [[data-panel-animations=true]_&]:[transition-duration:var(--panel-animation-duration)] [[data-panel-animations=true]_&]:ease-out", | 1223 | "[[data-panel-animations=true]_&]:transition-[grid-template-rows] [[data-panel-animations=true]_&]:duration-(--panel-animation-duration) [[data-panel-animations=true]_&]:ease-out", |
| 1224 | active && visible && "[[data-panel-animations=true]_&]:starting:grid-rows-[0fr]!", | 1224 | active && visible && "[[data-panel-animations=true]_&]:starting:grid-rows-[0fr]!", |
| 1225 | )} | 1225 | )} |
| 1226 | > | 1226 | > |
| ... | @@ -9588,7 +9588,7 @@ export default function ChatView(props: ChatViewProps) { | ... | @@ -9588,7 +9588,7 @@ export default function ChatView(props: ChatViewProps) { |
| 9588 | className={cn( | 9588 | className={cn( |
| 9589 | "flex shrink-0", | 9589 | "flex shrink-0", |
| 9590 | panelAnimationsActive && | 9590 | panelAnimationsActive && |
| 9591 | "motion-safe:transition-opacity motion-safe:[transition-duration:var(--panel-animation-duration)] motion-safe:ease-out", | 9591 | "motion-safe:transition-opacity motion-safe:duration-(--panel-animation-duration) motion-safe:ease-out", |
| 9592 | rightPanelOpen ? "pointer-events-auto opacity-100" : "pointer-events-none opacity-0", | 9592 | rightPanelOpen ? "pointer-events-auto opacity-100" : "pointer-events-none opacity-0", |
| 9593 | )} | 9593 | )} |
| 9594 | inert={!rightPanelOpen} | 9594 | inert={!rightPanelOpen} |
| ... | @@ -10015,7 +10015,7 @@ export default function ChatView(props: ChatViewProps) { | ... | @@ -10015,7 +10015,7 @@ export default function ChatView(props: ChatViewProps) { |
| 10015 | > | 10015 | > |
| 10016 | <div | 10016 | <div |
| 10017 | ref={attachDraftHeroTransitionGroupRef} | 10017 | ref={attachDraftHeroTransitionGroupRef} |
| 10018 | className="w-full ps-[calc(env(safe-area-inset-left)+0.75rem)] pe-[calc(env(safe-area-inset-right)+0.75rem)] sm:ps-[calc(env(safe-area-inset-left)+1.25rem)] sm:pe-[calc(env(safe-area-inset-right)+1.25rem)]" | 10018 | className="w-full ps-(--workspace-gutter-start) pe-(--workspace-gutter-end)" |
| 10019 | > | 10019 | > |
| 10020 | <div | 10020 | <div |
| 10021 | data-chat-composer-stack="true" | 10021 | data-chat-composer-stack="true" |
apps/web/src/components/ComposerPromptEditorTiptap.tsx+2-2| ... | @@ -190,7 +190,7 @@ function resolvedThemeFromDocument(): "light" | "dark" { | ... | @@ -190,7 +190,7 @@ function resolvedThemeFromDocument(): "light" | "dark" { |
| 190 | * paints the editor's node selection over it. | 190 | * paints the editor's node selection over it. |
| 191 | */ | 191 | */ |
| 192 | const CHIP_NODE_SELECTION_CLASS_NAME = | 192 | const CHIP_NODE_SELECTION_CLASS_NAME = |
| 193 | "relative inline-flex select-none items-center align-middle leading-none data-[composer-chip-selected]:after:pointer-events-none data-[composer-chip-selected]:after:absolute data-[composer-chip-selected]:after:inset-0 data-[composer-chip-selected]:after:rounded-[6px] data-[composer-chip-selected]:after:bg-[Highlight] data-[composer-chip-selected]:after:opacity-30 data-[composer-chip-selected]:after:content-['']"; | 193 | "relative inline-flex select-none items-center align-middle leading-none data-[composer-chip-selected]:after:pointer-events-none data-[composer-chip-selected]:after:absolute data-[composer-chip-selected]:after:inset-0 data-[composer-chip-selected]:after:rounded-sm data-[composer-chip-selected]:after:bg-[Highlight] data-[composer-chip-selected]:after:opacity-30 data-[composer-chip-selected]:after:content-['']"; |
| 194 | 194 | ||
| 195 | const ComposerMentionExtension = Node.create({ | 195 | const ComposerMentionExtension = Node.create({ |
| 196 | name: "composer-mention", | 196 | name: "composer-mention", |
| ... | @@ -1242,7 +1242,7 @@ function ComposerPromptEditorTiptapInner(props: ComposerPromptEditorProps) { | ... | @@ -1242,7 +1242,7 @@ function ComposerPromptEditorTiptapInner(props: ComposerPromptEditorProps) { |
| 1242 | <ComposerCitationCommentContext value={citationCommentActions}> | 1242 | <ComposerCitationCommentContext value={citationCommentActions}> |
| 1243 | <div | 1243 | <div |
| 1244 | className={cn( | 1244 | className={cn( |
| 1245 | "relative flow-root [font-family:var(--font-composer,var(--font-sans))] [font-size:var(--font-size-prompt,0.875rem)] [@media(max-width:39.999rem)_and_(pointer:coarse)]:[font-size:max(var(--font-size-prompt,1rem),16px)]", | 1245 | "relative flow-root font-(family-name:--font-composer,var(--font-sans)) text-(length:--font-size-prompt,var(--text-sm)) max-sm:pointer-coarse:text-(length:--font-size-prompt-touch)", |
| 1246 | containerClassName, | 1246 | containerClassName, |
| 1247 | )} | 1247 | )} |
| 1248 | > | 1248 | > |
apps/web/src/components/ContextChip.tsx+3-3| ... | @@ -23,7 +23,7 @@ import { cn } from "~/lib/utils"; | ... | @@ -23,7 +23,7 @@ import { cn } from "~/lib/utils"; |
| 23 | * span with tabIndex for a tooltip) gets the focus outline. | 23 | * span with tabIndex for a tooltip) gets the focus outline. |
| 24 | */ | 24 | */ |
| 25 | const contextChipVariants = cva( | 25 | const contextChipVariants = cva( |
| 26 | "inline-flex h-[1.41em] max-w-full items-center gap-[0.33em] rounded-[0.5em] border px-[0.5em] align-middle font-medium text-[0.86em] leading-none [&_svg]:block [&_svg]:size-[1.17em] [&_svg]:shrink-0 [&_svg]:self-center [button&,a&,[data-popup-open]&]:cursor-pointer [button&,a&]:transition-colors [button&,a&]:motion-reduce:transition-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--contrast-foreground)] disabled:cursor-default", | 26 | "inline-flex h-[1.41em] max-w-full items-center gap-[0.33em] rounded-[0.5em] border px-[0.5em] align-middle font-medium text-[0.86em] leading-none [&_svg]:block [&_svg]:size-[1.17em] [&_svg]:shrink-0 [&_svg]:self-center [button&,a&,[data-popup-open]&]:cursor-pointer [button&,a&]:transition-colors [button&,a&]:motion-reduce:transition-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-foreground disabled:cursor-default", |
| 27 | { | 27 | { |
| 28 | defaultVariants: { kind: "neutral" }, | 28 | defaultVariants: { kind: "neutral" }, |
| 29 | variants: { | 29 | variants: { |
| ... | @@ -71,7 +71,7 @@ const contextChipVariants = cva( | ... | @@ -71,7 +71,7 @@ const contextChipVariants = cva( |
| 71 | "citation", | 71 | "citation", |
| 72 | ], | 72 | ], |
| 73 | className: | 73 | className: |
| 74 | "border-[color-mix(in_oklab,var(--context-chip-accent)_34%,var(--contrast-border))] bg-[color-mix(in_oklab,var(--context-chip-accent)_11%,transparent)] text-[color-mix(in_oklab,var(--context-chip-accent)_22%,var(--contrast-foreground))] [button:enabled&,a&]:hover:border-[color-mix(in_oklab,var(--context-chip-accent)_48%,var(--contrast-border))] [button:enabled&,a&]:hover:bg-[color-mix(in_oklab,var(--context-chip-accent)_17%,transparent)]", | 74 | "[--context-chip-border:color-mix(in_oklab,var(--context-chip-accent)_34%,var(--contrast-border))] [--context-chip-border-hover:color-mix(in_oklab,var(--context-chip-accent)_48%,var(--contrast-border))] [--context-chip-foreground:color-mix(in_oklab,var(--context-chip-accent)_22%,var(--contrast-foreground))] border-(--context-chip-border) bg-(--context-chip-accent)/11 text-(--context-chip-foreground) [button:enabled&,a&]:hover:border-(--context-chip-border-hover) [button:enabled&,a&]:hover:bg-(--context-chip-accent)/17", |
| 75 | }, | 75 | }, |
| 76 | // State colors win over any kind. | 76 | // State colors win over any kind. |
| 77 | { state: "unresolved", className: "text-foreground" }, | 77 | { state: "unresolved", className: "text-foreground" }, |
| ... | @@ -115,7 +115,7 @@ function ContextChipLabel({ className, ...props }: React.ComponentProps<"span">) | ... | @@ -115,7 +115,7 @@ function ContextChipLabel({ className, ...props }: React.ComponentProps<"span">) |
| 115 | function ContextChipAction({ className, render, ...props }: useRender.ComponentProps<"button">) { | 115 | function ContextChipAction({ className, render, ...props }: useRender.ComponentProps<"button">) { |
| 116 | const defaultProps = { | 116 | const defaultProps = { |
| 117 | className: cn( | 117 | className: cn( |
| 118 | "ml-[0.17em] inline-flex size-[1.17em] shrink-0 cursor-pointer items-center justify-center rounded-sm text-current transition-colors hover:bg-[color-mix(in_oklab,var(--context-chip-accent,var(--color-foreground))_17%,transparent)] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring motion-reduce:transition-none [&_svg]:size-[0.85em]", | 118 | "ml-[0.17em] inline-flex size-[1.17em] shrink-0 cursor-pointer items-center justify-center rounded-sm text-current transition-colors hover:bg-(--context-chip-accent,var(--color-foreground))/17 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring motion-reduce:transition-none [&_svg]:size-[0.85em]", |
| 119 | className, | 119 | className, |
| 120 | ), | 120 | ), |
| 121 | "data-slot": "context-chip-action", | 121 | "data-slot": "context-chip-action", |
apps/web/src/components/DiffPanel.tsx+6-6| ... | @@ -765,7 +765,7 @@ export default function DiffPanel({ | ... | @@ -765,7 +765,7 @@ export default function DiffPanel({ |
| 765 | value={baseRefQuery} | 765 | value={baseRefQuery} |
| 766 | onChange={(event) => setBaseRefQuery(event.target.value)} | 766 | onChange={(event) => setBaseRefQuery(event.target.value)} |
| 767 | /> | 767 | /> |
| 768 | <div className="grid shrink-0 grid-cols-[1rem_minmax(0,1fr)] items-center gap-2 border-b border-border/70 ps-3 pe-6.5 pt-2 pb-1.5 font-medium text-[10px] text-muted-foreground uppercase tracking-wide"> | 768 | <div className="grid shrink-0 grid-cols-[1rem_minmax(0,1fr)] items-center gap-2 border-b border-border/70 ps-3 pe-6.5 pt-2 pb-1.5 font-medium text-3xs text-muted-foreground uppercase tracking-wide"> |
| 769 | <span aria-hidden="true" /> | 769 | <span aria-hidden="true" /> |
| 770 | <div className="grid min-w-0 grid-cols-[minmax(0,1fr)_2rem] items-center"> | 770 | <div className="grid min-w-0 grid-cols-[minmax(0,1fr)_2rem] items-center"> |
| 771 | <span>Branch</span> | 771 | <span>Branch</span> |
| ... | @@ -841,7 +841,7 @@ export default function DiffPanel({ | ... | @@ -841,7 +841,7 @@ export default function DiffPanel({ |
| 841 | <DiffStatLabel | 841 | <DiffStatLabel |
| 842 | additions={diffLineStat.additions} | 842 | additions={diffLineStat.additions} |
| 843 | deletions={diffLineStat.deletions} | 843 | deletions={diffLineStat.deletions} |
| 844 | className="mr-1 text-[11px]" | 844 | className="mr-1 text-2xs" |
| 845 | layout="inline" | 845 | layout="inline" |
| 846 | /> | 846 | /> |
| 847 | ) : null} | 847 | ) : null} |
| ... | @@ -992,14 +992,14 @@ export default function DiffPanel({ | ... | @@ -992,14 +992,14 @@ export default function DiffPanel({ |
| 992 | <> | 992 | <> |
| 993 | <div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden bg-background"> | 993 | <div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden bg-background"> |
| 994 | {isSelectedPatchTruncated && !lazySource && ( | 994 | {isSelectedPatchTruncated && !lazySource && ( |
| 995 | <p className="shrink-0 border-b border-border/70 bg-muted/40 px-3 py-1.5 text-[11px] text-muted-foreground"> | 995 | <p className="shrink-0 border-b border-border/70 bg-muted/40 px-3 py-1.5 text-2xs text-muted-foreground"> |
| 996 | This preview exceeds the size limit. Changes shown are incomplete. | 996 | This preview exceeds the size limit. Changes shown are incomplete. |
| 997 | {selectedGitSource?.files ? " Totals include all changes." : ""} | 997 | {selectedGitSource?.files ? " Totals include all changes." : ""} |
| 998 | </p> | 998 | </p> |
| 999 | )} | 999 | )} |
| 1000 | {selectedPatchError && !renderablePatch && ( | 1000 | {selectedPatchError && !renderablePatch && ( |
| 1001 | <div className="px-3"> | 1001 | <div className="px-3"> |
| 1002 | <p className="mb-2 text-[11px] text-error/80">{selectedPatchError}</p> | 1002 | <p className="mb-2 text-2xs text-error/80">{selectedPatchError}</p> |
| 1003 | </div> | 1003 | </div> |
| 1004 | )} | 1004 | )} |
| 1005 | {!renderablePatch && !lazySource ? ( | 1005 | {!renderablePatch && !lazySource ? ( |
| ... | @@ -1181,12 +1181,12 @@ export default function DiffPanel({ | ... | @@ -1181,12 +1181,12 @@ export default function DiffPanel({ |
| 1181 | ) : ( | 1181 | ) : ( |
| 1182 | <div className="min-h-0 flex-1 overflow-auto p-2"> | 1182 | <div className="min-h-0 flex-1 overflow-auto p-2"> |
| 1183 | <div className="space-y-2"> | 1183 | <div className="space-y-2"> |
| 1184 | <p className="text-[11px] text-muted-foreground/75"> | 1184 | <p className="text-2xs text-muted-foreground/75"> |
| 1185 | {renderablePatch?.kind === "raw" ? renderablePatch.reason : null} | 1185 | {renderablePatch?.kind === "raw" ? renderablePatch.reason : null} |
| 1186 | </p> | 1186 | </p> |
| 1187 | <pre | 1187 | <pre |
| 1188 | className={cn( | 1188 | className={cn( |
| 1189 | "max-h-[72vh] rounded-md border border-border/70 bg-background/70 p-3 font-mono text-[11px] leading-relaxed text-muted-foreground/90", | 1189 | "max-h-[72vh] rounded-md border border-border/70 bg-background/70 p-3 font-mono text-2xs leading-relaxed text-muted-foreground/90", |
| 1190 | wordWrap | 1190 | wordWrap |
| 1191 | ? "overflow-auto whitespace-pre-wrap wrap-break-word" | 1191 | ? "overflow-auto whitespace-pre-wrap wrap-break-word" |
| 1192 | : "overflow-auto", | 1192 | : "overflow-auto", |
apps/web/src/components/DiffPanelShell.tsx+1-1| ... | @@ -13,7 +13,7 @@ function getDiffPanelHeaderRowClassName(mode: DiffPanelMode) { | ... | @@ -13,7 +13,7 @@ function getDiffPanelHeaderRowClassName(mode: DiffPanelMode) { |
| 13 | "flex items-center justify-between gap-2", | 13 | "flex items-center justify-between gap-2", |
| 14 | mode === "embedded" ? "px-2" : "px-4", | 14 | mode === "embedded" ? "px-2" : "px-4", |
| 15 | shouldUseDragRegion | 15 | shouldUseDragRegion |
| 16 | ? "drag-region h-[var(--workspace-topbar-height)] border-b border-border wco:h-[env(titlebar-area-height)] wco:pr-[calc(100vw-env(titlebar-area-width)-env(titlebar-area-x)+1em)]" | 16 | ? "drag-region h-[var(--workspace-topbar-height)] border-b border-border wco:h-[env(titlebar-area-height)] wco:pr-(--workspace-native-controls-inset)" |
| 17 | : "flex h-10 min-h-10 shrink-0 items-center border-b border-border/60 bg-background in-data-[preview-panel-mode=inline]:mb-3 in-data-[preview-panel-mode=inline]:h-7 in-data-[preview-panel-mode=inline]:min-h-7 in-data-[preview-panel-mode=inline]:border-b-transparent", | 17 | : "flex h-10 min-h-10 shrink-0 items-center border-b border-border/60 bg-background in-data-[preview-panel-mode=inline]:mb-3 in-data-[preview-panel-mode=inline]:h-7 in-data-[preview-panel-mode=inline]:min-h-7 in-data-[preview-panel-mode=inline]:border-b-transparent", |
| 18 | ); | 18 | ); |
| 19 | } | 19 | } |
apps/web/src/components/LegacySidebar.tsx+5-5| ... | @@ -234,7 +234,7 @@ const PROJECT_GROUPING_MODE_LABELS: Record<SidebarProjectGroupingMode, string> = | ... | @@ -234,7 +234,7 @@ const PROJECT_GROUPING_MODE_LABELS: Record<SidebarProjectGroupingMode, string> = |
| 234 | separate: "Keep separate", | 234 | separate: "Keep separate", |
| 235 | }; | 235 | }; |
| 236 | const SIDEBAR_ICON_ACTION_BUTTON_CLASS = | 236 | const SIDEBAR_ICON_ACTION_BUTTON_CLASS = |
| 237 | "inline-flex h-6 min-w-6 cursor-pointer items-center justify-center rounded-md px-[calc(--spacing(1)-1px)] text-icon-muted hover:text-foreground focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring"; | 237 | "inline-flex h-6 min-w-6 cursor-pointer items-center justify-center rounded-md px-0.75 text-icon-muted hover:text-foreground focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring"; |
| 238 | 238 | ||
| 239 | function SidebarThreadDetailPrewarmer({ threadRef }: { readonly threadRef: ScopedThreadRef }) { | 239 | function SidebarThreadDetailPrewarmer({ threadRef }: { readonly threadRef: ScopedThreadRef }) { |
| 240 | useEnvironmentThread(threadRef.environmentId, threadRef.threadId); | 240 | useEnvironmentThread(threadRef.environmentId, threadRef.threadId); |
| ... | @@ -850,7 +850,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP | ... | @@ -850,7 +850,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP |
| 850 | data-thread-selection-safe | 850 | data-thread-selection-safe |
| 851 | data-testid={`thread-archive-confirm-${thread.id}`} | 851 | data-testid={`thread-archive-confirm-${thread.id}`} |
| 852 | aria-label={`Confirm archive ${thread.title}`} | 852 | aria-label={`Confirm archive ${thread.title}`} |
| 853 | className="absolute top-1/2 right-1 inline-flex h-5 -translate-y-1/2 cursor-pointer items-center rounded-md bg-destructive/12 px-2 text-[10px] font-medium text-destructive transition-colors hover:bg-destructive/18 focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-destructive/40" | 853 | className="absolute top-1/2 right-1 inline-flex h-5 -translate-y-1/2 cursor-pointer items-center rounded-md bg-destructive/12 px-2 text-3xs font-medium text-destructive transition-colors hover:bg-destructive/18 focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-destructive/40" |
| 854 | onPointerDown={stopPropagationOnPointerDown} | 854 | onPointerDown={stopPropagationOnPointerDown} |
| 855 | onClick={handleConfirmArchiveClick} | 855 | onClick={handleConfirmArchiveClick} |
| 856 | > | 856 | > |
| ... | @@ -920,7 +920,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP | ... | @@ -920,7 +920,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP |
| 920 | render={ | 920 | render={ |
| 921 | <span | 921 | <span |
| 922 | aria-label={jumpLabel} | 922 | aria-label={jumpLabel} |
| 923 | className="inline-flex h-5 items-center rounded-full border border-border/80 bg-background/90 px-1.5 font-mono text-[10px] font-medium tracking-tight text-foreground shadow-sm" | 923 | className="inline-flex h-5 items-center rounded-full border border-border/80 bg-background/90 px-1.5 font-mono text-3xs font-medium tracking-tight text-foreground shadow-sm" |
| 924 | /> | 924 | /> |
| 925 | } | 925 | } |
| 926 | > | 926 | > |
| ... | @@ -930,7 +930,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP | ... | @@ -930,7 +930,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP |
| 930 | </Tooltip> | 930 | </Tooltip> |
| 931 | ) : ( | 931 | ) : ( |
| 932 | <span | 932 | <span |
| 933 | className={`text-[10px] tabular-nums ${ | 933 | className={`text-3xs tabular-nums ${ |
| 934 | isHighlighted ? "text-foreground" : "text-secondary-label" | 934 | isHighlighted ? "text-foreground" : "text-secondary-label" |
| 935 | }`} | 935 | }`} |
| 936 | > | 936 | > |
| ... | @@ -2410,7 +2410,7 @@ const SidebarProjectItem = memo(function SidebarProjectItem(props: SidebarProjec | ... | @@ -2410,7 +2410,7 @@ const SidebarProjectItem = memo(function SidebarProjectItem(props: SidebarProjec |
| 2410 | {project.displayName} | 2410 | {project.displayName} |
| 2411 | </span> | 2411 | </span> |
| 2412 | {project.groupedProjectCount > 1 ? ( | 2412 | {project.groupedProjectCount > 1 ? ( |
| 2413 | <span className="shrink-0 text-secondary-label text-[10px]"> | 2413 | <span className="shrink-0 text-secondary-label text-3xs"> |
| 2414 | {project.groupedProjectCount} projects | 2414 | {project.groupedProjectCount} projects |
| 2415 | </span> | 2415 | </span> |
| 2416 | ) : null} | 2416 | ) : null} |
apps/web/src/components/ProjectFavicon.tsx+2-2| ... | @@ -19,7 +19,7 @@ const DynamicIcon = lazy(() => | ... | @@ -19,7 +19,7 @@ const DynamicIcon = lazy(() => |
| 19 | ); | 19 | ); |
| 20 | 20 | ||
| 21 | function DynamicProjectIconFallback() { | 21 | function DynamicProjectIconFallback() { |
| 22 | return <FolderCodeIcon className="size-full text-[inherit]" />; | 22 | return <FolderCodeIcon className="size-full text-inherit" />; |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | // The slice of a project that decides its icon. Every surface must pass the | 25 | // The slice of a project that decides its icon. Every surface must pass the |
| ... | @@ -176,7 +176,7 @@ function ProjectFaviconImage({ | ... | @@ -176,7 +176,7 @@ function ProjectFaviconImage({ |
| 176 | <img | 176 | <img |
| 177 | src={displayedSrc} | 177 | src={displayedSrc} |
| 178 | alt="" | 178 | alt="" |
| 179 | className={cn("size-3.5 shrink-0 rounded-[37.5%] object-contain", className)} | 179 | className={cn("size-3.5 shrink-0 rounded-[25%] object-contain", className)} |
| 180 | onError={() => handleLoadError(displayedSrc)} | 180 | onError={() => handleLoadError(displayedSrc)} |
| 181 | /> | 181 | /> |
| 182 | ) : null} | 182 | ) : null} |
apps/web/src/components/PullRequestContextDetails.tsx+1-1| ... | @@ -15,7 +15,7 @@ export function PullRequestContextDetails({ metadata }: { metadata: PullRequestC | ... | @@ -15,7 +15,7 @@ export function PullRequestContextDetails({ metadata }: { metadata: PullRequestC |
| 15 | <span className={state.toneClassName}>{state.label}</span> | 15 | <span className={state.toneClassName}>{state.label}</span> |
| 16 | </div> | 16 | </div> |
| 17 | <div className="wrap-break-word text-foreground">{metadata.title}</div> | 17 | <div className="wrap-break-word text-foreground">{metadata.title}</div> |
| 18 | <div className="flex min-w-0 items-center gap-1 text-secondary-label text-[10px]"> | 18 | <div className="flex min-w-0 items-center gap-1 text-secondary-label text-3xs"> |
| 19 | <code className="truncate">{metadata.headBranch}</code> | 19 | <code className="truncate">{metadata.headBranch}</code> |
| 20 | <ArrowRightIcon className="size-3 shrink-0" aria-hidden="true" /> | 20 | <ArrowRightIcon className="size-3 shrink-0" aria-hidden="true" /> |
| 21 | <code className="truncate">{metadata.baseBranch}</code> | 21 | <code className="truncate">{metadata.baseBranch}</code> |
apps/web/src/components/RightPanelTabs.tsx+11-10| ... | @@ -488,7 +488,7 @@ function RightPanelEmptyState(props: { | ... | @@ -488,7 +488,7 @@ function RightPanelEmptyState(props: { |
| 488 | {action.badgeCount > 0 ? ( | 488 | {action.badgeCount > 0 ? ( |
| 489 | <span | 489 | <span |
| 490 | aria-hidden | 490 | aria-hidden |
| 491 | className="absolute -top-1.5 -right-2 flex h-3.5 min-w-3.5 items-center justify-center rounded-full bg-info px-1 text-[9px] font-semibold tabular-nums text-white" | 491 | className="absolute -top-1.5 -right-2 flex h-3.5 min-w-3.5 items-center justify-center rounded-full bg-info px-1 text-3xs font-semibold tabular-nums text-white" |
| 492 | > | 492 | > |
| 493 | {action.badgeCount} | 493 | {action.badgeCount} |
| 494 | </span> | 494 | </span> |
| ... | @@ -505,13 +505,13 @@ function RightPanelEmptyState(props: { | ... | @@ -505,13 +505,13 @@ function RightPanelEmptyState(props: { |
| 505 | aria-label="Open a surface" | 505 | aria-label="Open a surface" |
| 506 | data-surface-launcher-keys={availableActions.map((action) => action.shortcut).join("")} | 506 | data-surface-launcher-keys={availableActions.map((action) => action.shortcut).join("")} |
| 507 | className={cn( | 507 | className={cn( |
| 508 | "flex min-h-0 flex-1 items-center justify-center overflow-y-auto px-6 pt-6 outline-none", | 508 | "flex min-h-0 flex-1 items-center justify-center overflow-y-auto px-6 outline-none", |
| 509 | // The panel topbar sits above this container; matching bottom padding | 509 | // The panel topbar sits above this container; matching bottom padding |
| 510 | // keeps the list centered against the full panel, not the leftover. | 510 | // keeps the list centered against the full panel, not the leftover. |
| 511 | "pb-[calc(var(--workspace-topbar-height)+--spacing(6))]", | 511 | "pb-(--workspace-topbar-height)", |
| 512 | )} | 512 | )} |
| 513 | > | 513 | > |
| 514 | <div className="w-full max-w-xs"> | 514 | <div className="w-full max-w-xs py-6"> |
| 515 | <h3 className="mb-3 text-center font-medium text-foreground text-sm">Open a surface</h3> | 515 | <h3 className="mb-3 text-center font-medium text-foreground text-sm">Open a surface</h3> |
| 516 | <div className="flex flex-col gap-0.5"> | 516 | <div className="flex flex-col gap-0.5"> |
| 517 | {actions.map((action) => | 517 | {actions.map((action) => |
| ... | @@ -534,7 +534,7 @@ function RightPanelEmptyState(props: { | ... | @@ -534,7 +534,7 @@ function RightPanelEmptyState(props: { |
| 534 | type="button" | 534 | type="button" |
| 535 | onClick={action.onClick} | 535 | onClick={action.onClick} |
| 536 | className={cn( | 536 | className={cn( |
| 537 | "flex h-8 w-full cursor-pointer items-center gap-2.5 rounded-[var(--control-radius)] px-2.5 text-left text-sm transition-colors group-hover:bg-accent/60", | 537 | "flex h-8 w-full cursor-pointer items-center gap-2.5 rounded-(--control-radius) px-2.5 text-left text-sm transition-colors group-hover:bg-accent/60", |
| 538 | isHighlighted(action) && "bg-accent/60", | 538 | isHighlighted(action) && "bg-accent/60", |
| 539 | )} | 539 | )} |
| 540 | > | 540 | > |
| ... | @@ -589,7 +589,7 @@ function RightPanelEmptyState(props: { | ... | @@ -589,7 +589,7 @@ function RightPanelEmptyState(props: { |
| 589 | <div | 589 | <div |
| 590 | tabIndex={0} | 590 | tabIndex={0} |
| 591 | aria-disabled="true" | 591 | aria-disabled="true" |
| 592 | className="flex h-8 w-full cursor-default items-center gap-2.5 rounded-[var(--control-radius)] px-2.5 text-left text-sm opacity-50" | 592 | className="flex h-8 w-full cursor-default items-center gap-2.5 rounded-(--control-radius) px-2.5 text-left text-sm opacity-50" |
| 593 | > | 593 | > |
| 594 | {actionIcon(action, "size-4")} | 594 | {actionIcon(action, "size-4")} |
| 595 | <span className="min-w-0 flex-1 truncate">{action.label}</span> | 595 | <span className="min-w-0 flex-1 truncate">{action.label}</span> |
| ... | @@ -1114,10 +1114,7 @@ export function RightPanelTabs(props: RightPanelTabsProps) { | ... | @@ -1114,10 +1114,7 @@ export function RightPanelTabs(props: RightPanelTabsProps) { |
| 1114 | // controls a few pixels higher and the cluster jumps on open. | 1114 | // controls a few pixels higher and the cluster jumps on open. |
| 1115 | props.mode === "inline" && !props.layoutControls ? "pr-28" : "pr-3", | 1115 | props.mode === "inline" && !props.layoutControls ? "pr-28" : "pr-3", |
| 1116 | ownsDesktopTitleBar && "drag-region", | 1116 | ownsDesktopTitleBar && "drag-region", |
| 1117 | ownsDesktopTitleBar && | 1117 | ownsDesktopTitleBar && "wco:pr-(--workspace-native-controls-inset)", |
| 1118 | (props.layoutControls | ||
| 1119 | ? "wco:pr-[var(--workspace-native-controls-inset)]" | ||
| 1120 | : "wco:pr-[calc(var(--workspace-native-controls-inset)+6rem)]"), | ||
| 1121 | props.mode === "inline" && props.maximized && COLLAPSED_SIDEBAR_TITLEBAR_INSET_CLASS, | 1118 | props.mode === "inline" && props.maximized && COLLAPSED_SIDEBAR_TITLEBAR_INSET_CLASS, |
| 1122 | )} | 1119 | )} |
| 1123 | data-right-panel-tabbar | 1120 | data-right-panel-tabbar |
| ... | @@ -1395,6 +1392,10 @@ export function RightPanelTabs(props: RightPanelTabsProps) { | ... | @@ -1395,6 +1392,10 @@ export function RightPanelTabs(props: RightPanelTabsProps) { |
| 1395 | </div> | 1392 | </div> |
| 1396 | ) : null} | 1393 | ) : null} |
| 1397 | {props.layoutControls} | 1394 | {props.layoutControls} |
| 1395 | {ownsDesktopTitleBar && !props.layoutControls ? ( | ||
| 1396 | // Keeps the tabs clear of the window controls when the layout toggles live elsewhere. | ||
| 1397 | <span aria-hidden className="hidden w-24 shrink-0 wco:block" /> | ||
| 1398 | ) : null} | ||
| 1398 | {ownsDesktopTitleBar ? ( | 1399 | {ownsDesktopTitleBar ? ( |
| 1399 | <span | 1400 | <span |
| 1400 | aria-hidden | 1401 | aria-hidden |
apps/web/src/components/Sidebar.tsx+8-8| ... | @@ -283,7 +283,7 @@ function JumpHintBadge(props: { label: string }) { | ... | @@ -283,7 +283,7 @@ function JumpHintBadge(props: { label: string }) { |
| 283 | return ( | 283 | return ( |
| 284 | <span | 284 | <span |
| 285 | aria-hidden | 285 | aria-hidden |
| 286 | className="pointer-events-none absolute right-1.5 top-1/2 z-10 inline-flex h-5 -translate-y-1/2 items-center rounded-full border border-border/80 bg-background/95 px-1.5 font-mono text-[10px] font-medium tracking-tight text-foreground shadow-sm" | 286 | className="pointer-events-none absolute right-1.5 top-1/2 z-10 inline-flex h-5 -translate-y-1/2 items-center rounded-full border border-border/80 bg-background/95 px-1.5 font-mono text-3xs font-medium tracking-tight text-foreground shadow-sm" |
| 287 | > | 287 | > |
| 288 | {props.label} | 288 | {props.label} |
| 289 | </span> | 289 | </span> |
| ... | @@ -760,7 +760,7 @@ const SidebarDraftRow = memo(function SidebarDraftRow(props: { | ... | @@ -760,7 +760,7 @@ const SidebarDraftRow = memo(function SidebarDraftRow(props: { |
| 760 | onClick={handleActivate} | 760 | onClick={handleActivate} |
| 761 | onKeyDown={handleKeyDown} | 761 | onKeyDown={handleKeyDown} |
| 762 | > | 762 | > |
| 763 | <div className="relative z-10 h-[4.875rem] px-[var(--sidebar-row-content-inset)] py-[var(--sidebar-content-inset)]"> | 763 | <div className="relative z-10 h-[4.875rem] px-(--sidebar-row-content-inset) py-(--sidebar-content-inset)"> |
| 764 | <div className="flex h-5 min-w-0 items-center gap-1.5"> | 764 | <div className="flex h-5 min-w-0 items-center gap-1.5"> |
| 765 | <SquarePenIcon aria-hidden className={draftPenClassName} /> | 765 | <SquarePenIcon aria-hidden className={draftPenClassName} /> |
| 766 | {props.project ? ( | 766 | {props.project ? ( |
| ... | @@ -1408,7 +1408,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { | ... | @@ -1408,7 +1408,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { |
| 1408 | // keeps the hover color applied, so both the tint and the solid sidebar | 1408 | // keeps the hover color applied, so both the tint and the solid sidebar |
| 1409 | // color are stacked as background images. | 1409 | // color are stacked as background images. |
| 1410 | props.sortable?.isDragging && | 1410 | props.sortable?.isDragging && |
| 1411 | "bg-[linear-gradient(var(--sidebar-row-active),var(--sidebar-row-active)),linear-gradient(var(--sidebar),var(--sidebar))] text-sidebar-foreground opacity-100 shadow-lg", | 1411 | "bg-sidebar bg-linear-to-b from-sidebar-row-active to-sidebar-row-active text-sidebar-foreground opacity-100 shadow-lg", |
| 1412 | ); | 1412 | ); |
| 1413 | // dnd-kit props for the row root. Same bag on both variants: every row in | 1413 | // dnd-kit props for the row root. Same bag on both variants: every row in |
| 1414 | // the list translates around the gap as the drag passes it. | 1414 | // the list translates around the gap as the drag passes it. |
| ... | @@ -1433,7 +1433,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { | ... | @@ -1433,7 +1433,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { |
| 1433 | sortable?.isDragging && props.dropVerb !== null ? ( | 1433 | sortable?.isDragging && props.dropVerb !== null ? ( |
| 1434 | <span | 1434 | <span |
| 1435 | role="status" | 1435 | role="status" |
| 1436 | className="pointer-events-none ml-auto inline-flex h-5 shrink-0 items-center gap-1 rounded-sm border border-primary/40 bg-primary/10 px-1.5 text-[11px] font-medium text-primary" | 1436 | className="pointer-events-none ml-auto inline-flex h-5 shrink-0 items-center gap-1 rounded-sm border border-primary/40 bg-primary/10 px-1.5 text-2xs font-medium text-primary" |
| 1437 | > | 1437 | > |
| 1438 | {dropVerbBadge[props.dropVerb]} | 1438 | {dropVerbBadge[props.dropVerb]} |
| 1439 | </span> | 1439 | </span> |
| ... | @@ -1478,7 +1478,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { | ... | @@ -1478,7 +1478,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { |
| 1478 | ? "text-muted-foreground" | 1478 | ? "text-muted-foreground" |
| 1479 | : "text-secondary-label/70", | 1479 | : "text-secondary-label/70", |
| 1480 | ), | 1480 | ), |
| 1481 | isRegeneratingTitle && "opacity-[0.55]", | 1481 | isRegeneratingTitle && "opacity-55", |
| 1482 | )} | 1482 | )} |
| 1483 | > | 1483 | > |
| 1484 | {thread.title} | 1484 | {thread.title} |
| ... | @@ -1745,7 +1745,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { | ... | @@ -1745,7 +1745,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { |
| 1745 | /> | 1745 | /> |
| 1746 | } | 1746 | } |
| 1747 | > | 1747 | > |
| 1748 | <div className="relative z-10 h-[4.875rem] px-[var(--sidebar-row-content-inset)] py-[var(--sidebar-content-inset)]"> | 1748 | <div className="relative z-10 h-[4.875rem] px-(--sidebar-row-content-inset) py-(--sidebar-content-inset)"> |
| 1749 | <div className="flex h-5 min-w-0 items-center gap-1.5"> | 1749 | <div className="flex h-5 min-w-0 items-center gap-1.5"> |
| 1750 | {draftIndicator} | 1750 | {draftIndicator} |
| 1751 | {props.project ? ( | 1751 | {props.project ? ( |
| ... | @@ -1956,7 +1956,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { | ... | @@ -1956,7 +1956,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { |
| 1956 | showBadge={showInstanceBadge} | 1956 | showBadge={showInstanceBadge} |
| 1957 | // Glyph dims, badge stays saturated; offset matches the composer trigger. | 1957 | // Glyph dims, badge stays saturated; offset matches the composer trigger. |
| 1958 | iconClassName="size-3.5 opacity-60" | 1958 | iconClassName="size-3.5 opacity-60" |
| 1959 | badgeClassName="right-[-0.1875rem] bottom-[-0.1875rem] h-3 min-w-3 px-0.5 text-[7px]" | 1959 | badgeClassName="right-[-0.1875rem] bottom-[-0.1875rem] h-3 min-w-3 px-0.5 text-3xs" |
| 1960 | /> | 1960 | /> |
| 1961 | </span> | 1961 | </span> |
| 1962 | ) : null} | 1962 | ) : null} |
| ... | @@ -4912,7 +4912,7 @@ export default function Sidebar() { | ... | @@ -4912,7 +4912,7 @@ export default function Sidebar() { |
| 4912 | <button | 4912 | <button |
| 4913 | type="button" | 4913 | type="button" |
| 4914 | onClick={openAddProjectCommandPalette} | 4914 | onClick={openAddProjectCommandPalette} |
| 4915 | className="inline-flex cursor-pointer items-center gap-1.5 rounded-md border border-sidebar-border px-2.5 py-1 text-[11px] font-medium text-sidebar-muted-foreground transition-colors hover:bg-sidebar-row-hover hover:text-sidebar-foreground" | 4915 | className="inline-flex cursor-pointer items-center gap-1.5 rounded-md border border-sidebar-border px-2.5 py-1 text-2xs font-medium text-sidebar-muted-foreground transition-colors hover:bg-sidebar-row-hover hover:text-sidebar-foreground" |
| 4916 | > | 4916 | > |
| 4917 | <PlusIcon className="-mx-0.5 size-3" /> | 4917 | <PlusIcon className="-mx-0.5 size-3" /> |
| 4918 | Add project | 4918 | Add project |
apps/web/src/components/SlowRpcRequestToastCoordinator.tsx+1-1| ... | @@ -22,7 +22,7 @@ function SlowRequestDetails({ requests }: { requests: ReadonlyArray<SlowRpcAckRe | ... | @@ -22,7 +22,7 @@ function SlowRequestDetails({ requests }: { requests: ReadonlyArray<SlowRpcAckRe |
| 22 | key={request.requestId} | 22 | key={request.requestId} |
| 23 | > | 23 | > |
| 24 | <div className="wrap-break-word font-medium text-foreground">{request.tag}</div> | 24 | <div className="wrap-break-word font-medium text-foreground">{request.tag}</div> |
| 25 | <div className="mt-0.5 text-[10px] opacity-75"> | 25 | <div className="mt-0.5 text-3xs opacity-75"> |
| 26 | Started {new Date(request.startedAt).toLocaleTimeString()} | 26 | Started {new Date(request.startedAt).toLocaleTimeString()} |
| 27 | </div> | 27 | </div> |
| 28 | </li> | 28 | </li> |
apps/web/src/components/ThreadStatusIndicators.tsx+2-2| ... | @@ -328,7 +328,7 @@ export function ThreadPullRequestsMiniList({ | ... | @@ -328,7 +328,7 @@ export function ThreadPullRequestsMiniList({ |
| 328 | {snapshot?.title ?? line.link.repository} | 328 | {snapshot?.title ?? line.link.repository} |
| 329 | </span> | 329 | </span> |
| 330 | {line.stack ? ( | 330 | {line.stack ? ( |
| 331 | <span className="ml-auto shrink-0 pl-1 text-[10px]"> | 331 | <span className="ml-auto shrink-0 pl-1 text-3xs"> |
| 332 | {line.stack.kind === "native" ? "stack" : "chain"} · {line.stack.size} | 332 | {line.stack.kind === "native" ? "stack" : "chain"} · {line.stack.size} |
| 333 | </span> | 333 | </span> |
| 334 | ) : null} | 334 | ) : null} |
| ... | @@ -463,7 +463,7 @@ export function ThreadStatusLabel({ | ... | @@ -463,7 +463,7 @@ export function ThreadStatusLabel({ |
| 463 | render={ | 463 | render={ |
| 464 | <span | 464 | <span |
| 465 | aria-label={status.label} | 465 | aria-label={status.label} |
| 466 | className={`inline-flex items-center gap-1 text-[10px] ${status.colorClass}`} | 466 | className={`inline-flex items-center gap-1 text-3xs ${status.colorClass}`} |
| 467 | /> | 467 | /> |
| 468 | } | 468 | } |
| 469 | > | 469 | > |
apps/web/src/components/ThreadTerminalDrawer.tsx+4-4| ... | @@ -981,7 +981,7 @@ export function TerminalViewport({ | ... | @@ -981,7 +981,7 @@ export function TerminalViewport({ |
| 981 | <div | 981 | <div |
| 982 | ref={containerRef} | 982 | ref={containerRef} |
| 983 | tabIndex={-1} | 983 | tabIndex={-1} |
| 984 | className="relative h-full w-full overflow-hidden bg-[var(--terminal-background)]" | 984 | className="relative h-full w-full overflow-hidden bg-(--terminal-background)" |
| 985 | /> | 985 | /> |
| 986 | ); | 986 | ); |
| 987 | } | 987 | } |
| ... | @@ -1490,7 +1490,7 @@ export default function ThreadTerminalDrawer({ | ... | @@ -1490,7 +1490,7 @@ export default function ThreadTerminalDrawer({ |
| 1490 | <div className="min-h-0 w-full flex-1"> | 1490 | <div className="min-h-0 w-full flex-1"> |
| 1491 | <div | 1491 | <div |
| 1492 | className={cn( | 1492 | className={cn( |
| 1493 | "flex h-full min-h-0 bg-[var(--terminal-background)]", | 1493 | "flex h-full min-h-0 bg-(--terminal-background)", |
| 1494 | hasTerminalSidebar && "gap-1.5", | 1494 | hasTerminalSidebar && "gap-1.5", |
| 1495 | )} | 1495 | )} |
| 1496 | > | 1496 | > |
| ... | @@ -1653,7 +1653,7 @@ export default function ThreadTerminalDrawer({ | ... | @@ -1653,7 +1653,7 @@ export default function ThreadTerminalDrawer({ |
| 1653 | {showGroupHeaders && ( | 1653 | {showGroupHeaders && ( |
| 1654 | <button | 1654 | <button |
| 1655 | type="button" | 1655 | type="button" |
| 1656 | className={`flex h-[22px] w-full cursor-pointer items-center gap-1 rounded px-1.5 text-[11px] ${ | 1656 | className={`flex h-[22px] w-full cursor-pointer items-center gap-1 rounded px-1.5 text-2xs ${ |
| 1657 | isGroupActive | 1657 | isGroupActive |
| 1658 | ? "bg-accent/50 text-foreground" | 1658 | ? "bg-accent/50 text-foreground" |
| 1659 | : "text-muted-foreground hover:bg-accent/40 hover:text-foreground" | 1659 | : "text-muted-foreground hover:bg-accent/40 hover:text-foreground" |
| ... | @@ -1662,7 +1662,7 @@ export default function ThreadTerminalDrawer({ | ... | @@ -1662,7 +1662,7 @@ export default function ThreadTerminalDrawer({ |
| 1662 | > | 1662 | > |
| 1663 | <GroupIcon className="size-3 shrink-0" /> | 1663 | <GroupIcon className="size-3 shrink-0" /> |
| 1664 | <span className="min-w-0 flex-1 truncate text-left">{groupLabel}</span> | 1664 | <span className="min-w-0 flex-1 truncate text-left">{groupLabel}</span> |
| 1665 | <span className="text-muted-foreground/70 text-[10px] tabular-nums"> | 1665 | <span className="text-muted-foreground/70 text-3xs tabular-nums"> |
| 1666 | {terminalCount} | 1666 | {terminalCount} |
| 1667 | </span> | 1667 | </span> |
| 1668 | </button> | 1668 | </button> |
apps/web/src/components/WorkspaceBreadcrumb.tsx+1-1| ... | @@ -33,7 +33,7 @@ export function WorkspaceBreadcrumbText({ children, className, ...props }: Compo | ... | @@ -33,7 +33,7 @@ export function WorkspaceBreadcrumbText({ children, className, ...props }: Compo |
| 33 | // Center the capital letters with adjacent icons, not the font's leading. | 33 | // Center the capital letters with adjacent icons, not the font's leading. |
| 34 | // Padding preserves accents and descenders when a label is truncated. | 34 | // Padding preserves accents and descenders when a label is truncated. |
| 35 | className={cn( | 35 | className={cn( |
| 36 | "block min-w-0 truncate [text-box:trim-both_cap_alphabetic] supports-[text-box:trim-both_cap_alphabetic]:py-[0.5em]", | 36 | "block min-w-0 truncate [text-box:trim-both_cap_alphabetic] supports-[text-box:trim-both_cap_alphabetic]:py-1.5", |
| 37 | className, | 37 | className, |
| 38 | )} | 38 | )} |
| 39 | {...props} | 39 | {...props} |
apps/web/src/components/WorkspacePageHeader.tsx+2-2| ... | @@ -16,9 +16,9 @@ export function WorkspacePageHeader({ | ... | @@ -16,9 +16,9 @@ export function WorkspacePageHeader({ |
| 16 | return ( | 16 | return ( |
| 17 | <header | 17 | <header |
| 18 | className={cn( | 18 | className={cn( |
| 19 | "flex h-[var(--workspace-topbar-height)] min-h-[var(--workspace-topbar-height)] shrink-0 items-center gap-3 pl-[calc(env(safe-area-inset-left)+0.75rem)] pr-[calc(env(safe-area-inset-right)+0.75rem)] [[data-panel-animations=true]_&]:motion-safe:transition-[padding-left,padding-right] [[data-panel-animations=true]_&]:motion-safe:[transition-duration:var(--panel-animation-duration)] [[data-panel-animations=true]_&]:motion-safe:ease-out sm:pl-[calc(env(safe-area-inset-left)+1.25rem)] sm:pr-[calc(env(safe-area-inset-right)+1.25rem)]", | 19 | "flex h-[var(--workspace-topbar-height)] min-h-[var(--workspace-topbar-height)] shrink-0 items-center gap-3 pl-(--workspace-gutter-start) pr-(--workspace-gutter-end) [[data-panel-animations=true]_&]:motion-safe:transition-[padding-left,padding-right] [[data-panel-animations=true]_&]:motion-safe:duration-(--panel-animation-duration) [[data-panel-animations=true]_&]:motion-safe:ease-out", |
| 20 | electron && "drag-region", | 20 | electron && "drag-region", |
| 21 | reserveNativeControls && "wco:pr-[var(--workspace-native-controls-inset)]", | 21 | reserveNativeControls && "wco:pr-(--workspace-native-controls-inset)", |
| 22 | COLLAPSED_SIDEBAR_TITLEBAR_INSET_CLASS, | 22 | COLLAPSED_SIDEBAR_TITLEBAR_INSET_CLASS, |
| 23 | className, | 23 | className, |
| 24 | )} | 24 | )} |
apps/web/src/components/auth/AuthSurfaceShell.tsx+1-1| ... | @@ -27,7 +27,7 @@ export function AuthSurfaceShell({ children }: { readonly children: ReactNode }) | ... | @@ -27,7 +27,7 @@ export function AuthSurfaceShell({ children }: { readonly children: ReactNode }) |
| 27 | )} | 27 | )} |
| 28 | <div className="absolute inset-0 bg-[linear-gradient(to_bottom,transparent_20%,rgba(7,18,55,0.46)_100%)]" /> | 28 | <div className="absolute inset-0 bg-[linear-gradient(to_bottom,transparent_20%,rgba(7,18,55,0.46)_100%)]" /> |
| 29 | <div className="relative h-full p-5 sm:p-6"> | 29 | <div className="relative h-full p-5 sm:p-6"> |
| 30 | <p className="text-[10px] font-semibold tracking-[0.2em] text-white/80 uppercase"> | 30 | <p className="text-3xs font-semibold tracking-widest text-white/80 uppercase"> |
| 31 | {APP_DISPLAY_NAME} | 31 | {APP_DISPLAY_NAME} |
| 32 | </p> | 32 | </p> |
| 33 | </div> | 33 | </div> |
apps/web/src/components/chat/AssistantCitationChip.tsx+2-2| ... | @@ -110,7 +110,7 @@ export function AssistantCitationChip({ | ... | @@ -110,7 +110,7 @@ export function AssistantCitationChip({ |
| 110 | const composerSourceLink = ( | 110 | const composerSourceLink = ( |
| 111 | <Link | 111 | <Link |
| 112 | {...sourceLinkProps} | 112 | {...sourceLinkProps} |
| 113 | className="inline-flex h-full min-w-0 items-center gap-[0.33em] rounded-sm text-inherit no-underline focus-visible:outline-2 focus-visible:outline-[var(--contrast-foreground)]" | 113 | className="inline-flex h-full min-w-0 items-center gap-[0.33em] rounded-sm text-inherit no-underline focus-visible:outline-2 focus-visible:outline-foreground" |
| 114 | aria-label={`View cited assistant text: ${label}`} | 114 | aria-label={`View cited assistant text: ${label}`} |
| 115 | > | 115 | > |
| 116 | <QuoteIcon aria-hidden="true" /> | 116 | <QuoteIcon aria-hidden="true" /> |
| ... | @@ -120,7 +120,7 @@ export function AssistantCitationChip({ | ... | @@ -120,7 +120,7 @@ export function AssistantCitationChip({ |
| 120 | const chatSourceLink = ( | 120 | const chatSourceLink = ( |
| 121 | <Link | 121 | <Link |
| 122 | {...sourceLinkProps} | 122 | {...sourceLinkProps} |
| 123 | className="inline-flex h-full min-w-0 items-center gap-[0.33em] rounded-sm text-inherit no-underline hover:bg-[color-mix(in_oklab,var(--context-chip-accent)_17%,transparent)] focus-visible:outline-2 focus-visible:outline-[var(--contrast-foreground)]" | 123 | className="inline-flex h-full min-w-0 items-center gap-[0.33em] rounded-sm text-inherit no-underline hover:bg-(--context-chip-accent)/17 focus-visible:outline-2 focus-visible:outline-foreground" |
| 124 | aria-label={`View cited assistant text: ${label}`} | 124 | aria-label={`View cited assistant text: ${label}`} |
| 125 | > | 125 | > |
| 126 | <QuoteIcon aria-hidden="true" /> | 126 | <QuoteIcon aria-hidden="true" /> |
apps/web/src/components/chat/ChangedFilesTree.tsx+4-4| ... | @@ -54,7 +54,7 @@ export const ChangedFilesCard = memo(function ChangedFilesCard(props: { | ... | @@ -54,7 +54,7 @@ export const ChangedFilesCard = memo(function ChangedFilesCard(props: { |
| 54 | > | 54 | > |
| 55 | <div | 55 | <div |
| 56 | data-changed-files-header="" | 56 | data-changed-files-header="" |
| 57 | className="sticky top-2 z-10 flex items-center justify-between gap-2 rounded-t-lg bg-secondary px-3 py-2 dark:bg-[color-mix(in_srgb,var(--input)_20%,var(--background))]" | 57 | className="sticky top-2 z-10 flex items-center justify-between gap-2 rounded-t-lg bg-secondary px-3 py-2 dark:bg-background dark:bg-linear-to-b dark:from-input/20 dark:to-input/20" |
| 58 | > | 58 | > |
| 59 | <div className="flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1 text-xs font-medium text-foreground"> | 59 | <div className="flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1 text-xs font-medium text-foreground"> |
| 60 | <span> | 60 | <span> |
| ... | @@ -206,11 +206,11 @@ export const ChangedFilesTree = memo(function ChangedFilesTree(props: { | ... | @@ -206,11 +206,11 @@ export const ChangedFilesTree = memo(function ChangedFilesTree(props: { |
| 206 | ) : ( | 206 | ) : ( |
| 207 | <FolderClosedIcon className="size-3.5 shrink-0 text-muted-foreground/75" /> | 207 | <FolderClosedIcon className="size-3.5 shrink-0 text-muted-foreground/75" /> |
| 208 | )} | 208 | )} |
| 209 | <span className="truncate font-mono text-[11px] text-muted-foreground/90 group-hover:text-foreground/90"> | 209 | <span className="truncate font-mono text-2xs text-muted-foreground/90 group-hover:text-foreground/90"> |
| 210 | {node.name} | 210 | {node.name} |
| 211 | </span> | 211 | </span> |
| 212 | {hasNonZeroStat(node.stat) && ( | 212 | {hasNonZeroStat(node.stat) && ( |
| 213 | <span className="ml-auto shrink-0 font-mono text-[10px] tabular-nums"> | 213 | <span className="ml-auto shrink-0 font-mono text-3xs tabular-nums"> |
| 214 | <DiffStatLabel additions={node.stat.additions} deletions={node.stat.deletions} /> | 214 | <DiffStatLabel additions={node.stat.additions} deletions={node.stat.deletions} /> |
| 215 | </span> | 215 | </span> |
| 216 | )} | 216 | )} |
| ... | @@ -251,7 +251,7 @@ export const ChangedFilesTree = memo(function ChangedFilesTree(props: { | ... | @@ -251,7 +251,7 @@ export const ChangedFilesTree = memo(function ChangedFilesTree(props: { |
| 251 | <MiddleTruncate value={node.name} /> | 251 | <MiddleTruncate value={node.name} /> |
| 252 | </span> | 252 | </span> |
| 253 | {node.stat && ( | 253 | {node.stat && ( |
| 254 | <span className="ml-auto shrink-0 font-mono text-[10px] tabular-nums"> | 254 | <span className="ml-auto shrink-0 font-mono text-3xs tabular-nums"> |
| 255 | <DiffStatLabel additions={node.stat.additions} deletions={node.stat.deletions} /> | 255 | <DiffStatLabel additions={node.stat.additions} deletions={node.stat.deletions} /> |
| 256 | </span> | 256 | </span> |
| 257 | )} | 257 | )} |
apps/web/src/components/chat/ChatComposer.tsx+8-8| ... | @@ -381,7 +381,7 @@ function SnapShotAttachmentFrame({ | ... | @@ -381,7 +381,7 @@ function SnapShotAttachmentFrame({ |
| 381 | className={cn( | 381 | className={cn( |
| 382 | animateArrival && | 382 | animateArrival && |
| 383 | !animationId && | 383 | !animationId && |
| 384 | "origin-center transition-[opacity,scale] duration-300 ease-[cubic-bezier(.2,.8,.2,1)] starting:scale-95 starting:opacity-0 motion-reduce:transition-none motion-reduce:starting:scale-100 motion-reduce:starting:opacity-100", | 384 | "origin-center transition-[opacity,scale] duration-300 ease-drawer starting:scale-95 starting:opacity-0 motion-reduce:transition-none motion-reduce:starting:scale-100 motion-reduce:starting:opacity-100", |
| 385 | className, | 385 | className, |
| 386 | )} | 386 | )} |
| 387 | {...props} | 387 | {...props} |
| ... | @@ -6365,7 +6365,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) | ... | @@ -6365,7 +6365,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) |
| 6365 | data-chat-composer-surface="true" | 6365 | data-chat-composer-surface="true" |
| 6366 | data-chat-composer-mobile-collapsed={isComposerCollapsedMobile ? "true" : "false"} | 6366 | data-chat-composer-mobile-collapsed={isComposerCollapsedMobile ? "true" : "false"} |
| 6367 | className={cn( | 6367 | className={cn( |
| 6368 | "rounded-[20px] transition-[background-color] duration-200", | 6368 | "rounded-3xl transition-[background-color] duration-200", |
| 6369 | isDragOverComposer ? "bg-accent/45 ring-1 ring-primary/70" : null, | 6369 | isDragOverComposer ? "bg-accent/45 ring-1 ring-primary/70" : null, |
| 6370 | projectSelectionRequired ? "opacity-75" : null, | 6370 | projectSelectionRequired ? "opacity-75" : null, |
| 6371 | composerProviderState.composerSurfaceClassName, | 6371 | composerProviderState.composerSurfaceClassName, |
| ... | @@ -6377,7 +6377,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) | ... | @@ -6377,7 +6377,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) |
| 6377 | type="button" | 6377 | type="button" |
| 6378 | data-chat-composer-transition-prompt="true" | 6378 | data-chat-composer-transition-prompt="true" |
| 6379 | className={cn( | 6379 | className={cn( |
| 6380 | "min-w-0 flex-1 truncate bg-transparent p-0 text-left text-[14px] focus:outline-none", | 6380 | "min-w-0 flex-1 truncate bg-transparent p-0 text-left text-sm focus:outline-none", |
| 6381 | (activePendingProgress ? activePendingProgress.customAnswer : prompt.trim()) | 6381 | (activePendingProgress ? activePendingProgress.customAnswer : prompt.trim()) |
| 6382 | ? "text-foreground" | 6382 | ? "text-foreground" |
| 6383 | : "text-placeholder", | 6383 | : "text-placeholder", |
| ... | @@ -6477,7 +6477,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) | ... | @@ -6477,7 +6477,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) |
| 6477 | "mb-3 flex max-w-full gap-2", | 6477 | "mb-3 flex max-w-full gap-2", |
| 6478 | pendingSnapShotIds.length > 0 || | 6478 | pendingSnapShotIds.length > 0 || |
| 6479 | expandedComposerImages.some((image) => image.source?.kind === "snap-shot") | 6479 | expandedComposerImages.some((image) => image.source?.kind === "snap-shot") |
| 6480 | ? "snap-x snap-proximity overflow-x-auto overscroll-x-contain pb-1 [scrollbar-color:color-mix(in_srgb,var(--contrast-foreground)_18%,transparent)_transparent] [scrollbar-width:thin] [&::-webkit-scrollbar]:h-2.5 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:border-3 [&::-webkit-scrollbar-thumb]:border-transparent [&::-webkit-scrollbar-thumb]:bg-[color-mix(in_srgb,var(--contrast-foreground)_18%,transparent)] [&::-webkit-scrollbar-thumb]:bg-clip-content [&::-webkit-scrollbar-thumb:hover]:bg-[color-mix(in_srgb,var(--contrast-foreground)_28%,transparent)] [&::-webkit-scrollbar-track]:mx-1 [&::-webkit-scrollbar-track]:bg-transparent" | 6480 | ? "snap-x snap-proximity overflow-x-auto overscroll-x-contain pb-1 scrollbar-thumb-foreground/18 scrollbar-track-transparent [scrollbar-width:thin] [&::-webkit-scrollbar]:h-2.5 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:border-3 [&::-webkit-scrollbar-thumb]:border-transparent [&::-webkit-scrollbar-thumb]:bg-foreground/18 [&::-webkit-scrollbar-thumb]:bg-clip-content [&::-webkit-scrollbar-thumb:hover]:bg-foreground/28 [&::-webkit-scrollbar-track]:mx-1 [&::-webkit-scrollbar-track]:bg-transparent" |
| 6481 | : "flex-wrap", | 6481 | : "flex-wrap", |
| 6482 | )} | 6482 | )} |
| 6483 | > | 6483 | > |
| ... | @@ -6532,14 +6532,14 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) | ... | @@ -6532,14 +6532,14 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) |
| 6532 | alt={image.name} | 6532 | alt={image.name} |
| 6533 | className="h-full w-full object-cover" | 6533 | className="h-full w-full object-cover" |
| 6534 | fallback={ | 6534 | fallback={ |
| 6535 | <span className="flex h-full items-center justify-center px-1 text-[10px] text-secondary-label"> | 6535 | <span className="flex h-full items-center justify-center px-1 text-3xs text-secondary-label"> |
| 6536 | {image.name} | 6536 | {image.name} |
| 6537 | </span> | 6537 | </span> |
| 6538 | } | 6538 | } |
| 6539 | /> | 6539 | /> |
| 6540 | </button> | 6540 | </button> |
| 6541 | ) : ( | 6541 | ) : ( |
| 6542 | <div className="flex h-full w-full items-center justify-center px-1 text-center text-[10px] text-secondary-label"> | 6542 | <div className="flex h-full w-full items-center justify-center px-1 text-center text-3xs text-secondary-label"> |
| 6543 | {image.name} | 6543 | {image.name} |
| 6544 | </div> | 6544 | </div> |
| 6545 | )} | 6545 | )} |
| ... | @@ -6572,7 +6572,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) | ... | @@ -6572,7 +6572,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) |
| 6572 | </Tooltip> | 6572 | </Tooltip> |
| 6573 | )} | 6573 | )} |
| 6574 | {upload?.status === "uploading" && ( | 6574 | {upload?.status === "uploading" && ( |
| 6575 | <span className="pointer-events-none absolute inset-x-0 bottom-0 bg-background/85 px-1 text-center text-[10px] text-foreground"> | 6575 | <span className="pointer-events-none absolute inset-x-0 bottom-0 bg-background/85 px-1 text-center text-3xs text-foreground"> |
| 6576 | {formatAttachmentUploadProgress(upload.progress)} | 6576 | {formatAttachmentUploadProgress(upload.progress)} |
| 6577 | </span> | 6577 | </span> |
| 6578 | )} | 6578 | )} |
| ... | @@ -6671,7 +6671,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) | ... | @@ -6671,7 +6671,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) |
| 6671 | <PlayIcon className="relative z-10 size-4 fill-current drop-shadow-md" /> | 6671 | <PlayIcon className="relative z-10 size-4 fill-current drop-shadow-md" /> |
| 6672 | </button> | 6672 | </button> |
| 6673 | {upload?.status === "uploading" && ( | 6673 | {upload?.status === "uploading" && ( |
| 6674 | <span className="pointer-events-none absolute inset-x-0 bottom-0 bg-background/85 px-1 text-center text-[10px] text-foreground"> | 6674 | <span className="pointer-events-none absolute inset-x-0 bottom-0 bg-background/85 px-1 text-center text-3xs text-foreground"> |
| 6675 | {formatAttachmentUploadProgress(upload.progress)} | 6675 | {formatAttachmentUploadProgress(upload.progress)} |
| 6676 | </span> | 6676 | </span> |
| 6677 | )} | 6677 | )} |
apps/web/src/components/chat/ChatHeader.tsx+2-2| ... | @@ -494,8 +494,8 @@ export const ChatHeader = memo(function ChatHeader({ | ... | @@ -494,8 +494,8 @@ export const ChatHeader = memo(function ChatHeader({ |
| 494 | "flex shrink-0 items-center justify-end gap-2 @3xl/header-actions:gap-3", | 494 | "flex shrink-0 items-center justify-end gap-2 @3xl/header-actions:gap-3", |
| 495 | // Reserve two panel toggles plus their 4px gaps and 1px edge inset. | 495 | // Reserve two panel toggles plus their 4px gaps and 1px edge inset. |
| 496 | // The page header adds 8px more right padding at sm. | 496 | // The page header adds 8px more right padding at sm. |
| 497 | rightPanelOpen ? "pr-0" : "pr-[calc(--spacing(18)+1px)] sm:pr-[calc(--spacing(14)+1px)]", | 497 | rightPanelOpen ? "pr-0" : "pr-18.25 sm:pr-14.25", |
| 498 | "[[data-panel-animations=true]_&]:motion-safe:transition-[padding-right] [[data-panel-animations=true]_&]:motion-safe:[transition-duration:var(--panel-animation-duration)] [[data-panel-animations=true]_&]:motion-safe:ease-out", | 498 | "[[data-panel-animations=true]_&]:motion-safe:transition-[padding-right] [[data-panel-animations=true]_&]:motion-safe:duration-(--panel-animation-duration) [[data-panel-animations=true]_&]:motion-safe:ease-out", |
| 499 | )} | 499 | )} |
| 500 | > | 500 | > |
| 501 | <Menu open={actionsCollapsed && actionsOpen} onOpenChange={setActionsOpen}> | 501 | <Menu open={actionsCollapsed && actionsOpen} onOpenChange={setActionsOpen}> |
apps/web/src/components/chat/ComposerBanner.tsx+14-22| ... | @@ -51,17 +51,17 @@ function Surface({ | ... | @@ -51,17 +51,17 @@ function Surface({ |
| 51 | surfaceColors, | 51 | surfaceColors, |
| 52 | "relative isolate border-0 bg-transparent shadow-none [--chat-composer-attached-tint:transparent]", | 52 | "relative isolate border-0 bg-transparent shadow-none [--chat-composer-attached-tint:transparent]", |
| 53 | variantColors[variant], | 53 | variantColors[variant], |
| 54 | // The mask cut-off (1rem) bleeds one pixel past the seam (1rem + 1px): Chromium | ||
| 55 | // drops the last device-pixel row of a filtered backdrop when the cut-off lands | ||
| 56 | // off the device-pixel grid, and the composer's surface starts exactly there. | ||
| 57 | // The composer's own glass covers the extra row, so the overlap never shows. | ||
| 54 | placement === "attached" | 58 | placement === "attached" |
| 55 | ? "[--chat-composer-attachment-overlap:calc(1rem+1px)] before:rounded-t-[16px]" | 59 | ? "[--chat-composer-attachment-overlap:calc(1rem+1px)] before:rounded-t-2xl before:mask-t-from-transparent before:mask-t-from-4 before:mask-t-to-black before:mask-t-to-4" |
| 56 | : "[--chat-composer-attachment-overlap:0px] before:rounded-[1rem]", | 60 | : "[--chat-composer-attachment-overlap:0px] before:rounded-2xl", |
| 57 | "before:pointer-events-none before:absolute before:inset-0 before:-z-1 before:border before:border-(--chat-composer-attached-outline)", | 61 | "before:pointer-events-none before:absolute before:inset-0 before:-z-1 before:border before:border-(--chat-composer-attached-outline)", |
| 58 | "before:bg-[color-mix(in_srgb,var(--chat-composer-attached-surface)_var(--glass-opacity),transparent)] before:bg-[linear-gradient(var(--chat-composer-attached-tint),var(--chat-composer-attached-tint))] before:backdrop-blur-(--glass-blur) before:backdrop-saturate-(--glass-saturation)", | 62 | "before:bg-(--chat-composer-attached-surface)/(--glass-opacity) before:bg-linear-to-b before:from-(--chat-composer-attached-tint) before:to-(--chat-composer-attached-tint) before:backdrop-blur-(--glass-blur) before:backdrop-saturate-(--glass-saturation)", |
| 59 | // The mask cut-off bleeds one pixel past the seam: Chromium drops the last | 63 | "before:shadow-composer dark:before:shadow-composer-dark", |
| 60 | // device-pixel row of a filtered backdrop when the cut-off lands off the | 64 | "dark:supports-[(backdrop-filter:blur(1px))_or_(-webkit-backdrop-filter:blur(1px))]:before:bg-composer-seam-above", |
| 61 | // device-pixel grid, and the composer's surface starts exactly there. The | ||
| 62 | // composer's own glass covers the extra row, so the overlap never shows. | ||
| 63 | "before:mask-[linear-gradient(to_top,transparent_0_calc(var(--chat-composer-attachment-overlap)-1px),black_calc(var(--chat-composer-attachment-overlap)-1px))] before:shadow-[0_12px_28px_-18px_rgb(0_0_0/40%)] dark:before:shadow-[0_14px_32px_-18px_rgb(0_0_0/75%)]", | ||
| 64 | "dark:supports-[(backdrop-filter:blur(1px))_or_(-webkit-backdrop-filter:blur(1px))]:before:bg-[linear-gradient(var(--chat-composer-attached-tint),var(--chat-composer-attached-tint)),linear-gradient(to_top,transparent_0_var(--chat-composer-attachment-overlap),rgb(0_0_0/18%)_var(--chat-composer-attachment-overlap),transparent_calc(var(--chat-composer-attachment-overlap)+10px))]", | ||
| 65 | "not-supports-[((backdrop-filter:blur(1px))_or_(-webkit-backdrop-filter:blur(1px)))]:before:bg-(--chat-composer-attached-surface)", | 65 | "not-supports-[((backdrop-filter:blur(1px))_or_(-webkit-backdrop-filter:blur(1px)))]:before:bg-(--chat-composer-attached-surface)", |
| 66 | className, | 66 | className, |
| 67 | )} | 67 | )} |
| ... | @@ -91,8 +91,8 @@ function Peek({ | ... | @@ -91,8 +91,8 @@ function Peek({ |
| 91 | className={cn( | 91 | className={cn( |
| 92 | surfaceColors, | 92 | surfaceColors, |
| 93 | neutralOutline, | 93 | neutralOutline, |
| 94 | "absolute inset-x-0 bottom-0 z-0 mx-auto h-3 w-[96%] cursor-pointer rounded-t-2xl border border-b-0 shadow-[0_6px_18px_rgb(0_0_0/6%)]", | 94 | "absolute inset-x-0 bottom-0 z-0 mx-auto h-3 w-[96%] cursor-pointer rounded-t-2xl border border-b-0 shadow-md", |
| 95 | "bg-[color-mix(in_srgb,var(--chat-composer-attached-surface)_var(--glass-opacity),transparent)] backdrop-blur-(--glass-blur) backdrop-saturate-(--glass-saturation)", | 95 | "bg-(--chat-composer-attached-surface)/(--glass-opacity) backdrop-blur-(--glass-blur) backdrop-saturate-(--glass-saturation)", |
| 96 | "not-supports-[((backdrop-filter:blur(1px))_or_(-webkit-backdrop-filter:blur(1px)))]:bg-(--chat-composer-attached-surface)", | 96 | "not-supports-[((backdrop-filter:blur(1px))_or_(-webkit-backdrop-filter:blur(1px)))]:bg-(--chat-composer-attached-surface)", |
| 97 | "transition-opacity duration-150 ease-out focus-visible:outline-2 focus-visible:outline-ring", | 97 | "transition-opacity duration-150 ease-out focus-visible:outline-2 focus-visible:outline-ring", |
| 98 | peekBorder[variant], | 98 | peekBorder[variant], |
| ... | @@ -161,7 +161,7 @@ function Root({ | ... | @@ -161,7 +161,7 @@ function Root({ |
| 161 | return ( | 161 | return ( |
| 162 | <Surface | 162 | <Surface |
| 163 | className={cn( | 163 | className={cn( |
| 164 | "min-w-0 px-1 pt-(--composer-banner-padding-block) pb-[calc(var(--chat-composer-attachment-overlap)+var(--composer-banner-padding-block))] text-xs/4 [--composer-banner-icon-column:--spacing(7)] [--composer-banner-padding-block:--spacing(1)] sm:[--composer-banner-icon-column:--spacing(6)]", | 164 | "min-w-0 px-1 py-(--composer-banner-padding-block) after:block after:h-(--chat-composer-attachment-overlap) text-xs/4 [--composer-banner-icon-column:--spacing(7)] [--composer-banner-padding-block:--spacing(1)] sm:[--composer-banner-icon-column:--spacing(6)]", |
| 165 | density === "comfortable" && "[--composer-banner-padding-block:--spacing(1.25)]", | 165 | density === "comfortable" && "[--composer-banner-padding-block:--spacing(1.25)]", |
| 166 | density === "spacious" && "px-3 [--composer-banner-padding-block:--spacing(3)]", | 166 | density === "spacious" && "px-3 [--composer-banner-padding-block:--spacing(3)]", |
| 167 | width === "content" ? "w-fit max-w-full flex-none" : "@container", | 167 | width === "content" ? "w-fit max-w-full flex-none" : "@container", |
| ... | @@ -189,7 +189,7 @@ function Row({ | ... | @@ -189,7 +189,7 @@ function Row({ |
| 189 | className: cn( | 189 | className: cn( |
| 190 | "group/banner-row grid min-h-(--composer-banner-icon-column) w-full min-w-0 grid-cols-[var(--composer-banner-icon-column)_minmax(0,1fr)_auto] items-center gap-x-1 text-start", | 190 | "group/banner-row grid min-h-(--composer-banner-icon-column) w-full min-w-0 grid-cols-[var(--composer-banner-icon-column)_minmax(0,1fr)_auto] items-center gap-x-1 text-start", |
| 191 | "not-has-[>[data-slot=composer-banner-actions]]:grid-cols-[var(--composer-banner-icon-column)_minmax(0,1fr)]", | 191 | "not-has-[>[data-slot=composer-banner-actions]]:grid-cols-[var(--composer-banner-icon-column)_minmax(0,1fr)]", |
| 192 | "[&:is(button)]:cursor-pointer [&:is(button)]:rounded-[0.5rem] [&:is(button)]:focus-visible:outline-2 [&:is(button)]:focus-visible:-outline-offset-2 [&:is(button)]:focus-visible:outline-ring", | 192 | "[&:is(button)]:cursor-pointer [&:is(button)]:rounded-md [&:is(button)]:focus-visible:outline-2 [&:is(button)]:focus-visible:-outline-offset-2 [&:is(button)]:focus-visible:outline-ring", |
| 193 | layout === "wrap-actions" && | 193 | layout === "wrap-actions" && |
| 194 | "@max-[400px]:*:data-[slot=composer-banner-content]:min-h-(--composer-banner-icon-column)", | 194 | "@max-[400px]:*:data-[slot=composer-banner-content]:min-h-(--composer-banner-icon-column)", |
| 195 | layout === "wrap-actions-narrow" && | 195 | layout === "wrap-actions-narrow" && |
| ... | @@ -306,15 +306,7 @@ function Count({ className, ...props }: ComponentProps<"span">) { | ... | @@ -306,15 +306,7 @@ function Count({ className, ...props }: ComponentProps<"span">) { |
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | function Body({ className, ...props }: ComponentProps<"div">) { | 308 | function Body({ className, ...props }: ComponentProps<"div">) { |
| 309 | return ( | 309 | return <div className={cn("min-w-0 ps-8 sm:ps-7", className)} {...props} />; |
| 310 | <div | ||
| 311 | className={cn( | ||
| 312 | "min-w-0 ps-[calc(var(--composer-banner-icon-column)+(--spacing(1)))]", | ||
| 313 | className, | ||
| 314 | )} | ||
| 315 | {...props} | ||
| 316 | /> | ||
| 317 | ); | ||
| 318 | } | 310 | } |
| 319 | 311 | ||
| 320 | function Dot({ className, ...props }: ComponentProps<"span">) { | 312 | function Dot({ className, ...props }: ComponentProps<"span">) { |
apps/web/src/components/chat/ComposerBannerStack.tsx+2-2| ... | @@ -123,7 +123,7 @@ export function ComposerBannerStack({ className, items }: ComposerBannerStackPro | ... | @@ -123,7 +123,7 @@ export function ComposerBannerStack({ className, items }: ComposerBannerStackPro |
| 123 | <div | 123 | <div |
| 124 | key={frontItem.id} | 124 | key={frontItem.id} |
| 125 | className={cn( | 125 | className={cn( |
| 126 | "relative z-10 transition-[translate,opacity] duration-220 ease-in", | 126 | "relative z-10 transition-[opacity,translate] duration-220 ease-in", |
| 127 | exitingItemId === frontItem.id | 127 | exitingItemId === frontItem.id |
| 128 | ? "pointer-events-none translate-y-16 opacity-0" | 128 | ? "pointer-events-none translate-y-16 opacity-0" |
| 129 | : "opacity-100", | 129 | : "opacity-100", |
| ... | @@ -218,7 +218,7 @@ export function ComposerBannerStack({ className, items }: ComposerBannerStackPro | ... | @@ -218,7 +218,7 @@ export function ComposerBannerStack({ className, items }: ComposerBannerStackPro |
| 218 | <div | 218 | <div |
| 219 | key={item.id} | 219 | key={item.id} |
| 220 | className={cn( | 220 | className={cn( |
| 221 | "transition-[translate,opacity] duration-220 ease-in", | 221 | "transition-[opacity,translate] duration-220 ease-in", |
| 222 | exitingItemId === item.id | 222 | exitingItemId === item.id |
| 223 | ? "pointer-events-none translate-y-28 opacity-0" | 223 | ? "pointer-events-none translate-y-28 opacity-0" |
| 224 | : "opacity-100", | 224 | : "opacity-100", |
apps/web/src/components/chat/ComposerControl.tsx+3-3| ... | @@ -16,10 +16,10 @@ export type ComposerControlSize = "sm" | "xs"; | ... | @@ -16,10 +16,10 @@ export type ComposerControlSize = "sm" | "xs"; |
| 16 | */ | 16 | */ |
| 17 | function composerControlClassName(size: ComposerControlSize, className?: string) { | 17 | function composerControlClassName(size: ComposerControlSize, className?: string) { |
| 18 | return cn( | 18 | return cn( |
| 19 | "relative inline-flex shrink-0 cursor-pointer items-center justify-center whitespace-nowrap rounded-[var(--control-radius)] border border-transparent text-base outline-none hover:bg-accent data-pressed:bg-accent focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 [&:active:not([aria-haspopup])]:scale-[0.97] [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:-mx-0.5 [&_svg[data-composer-control-icon]]:mx-0 [&_svg:not([class*='text-'])]:text-[var(--control-icon-color)]", | 19 | "relative inline-flex shrink-0 cursor-pointer items-center justify-center whitespace-nowrap rounded-(--control-radius) border border-transparent text-base outline-none hover:bg-accent data-pressed:bg-accent focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-64 data-disabled:pointer-events-none data-disabled:opacity-64 pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 [&:active:not([aria-haspopup])]:scale-[0.97] [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:-mx-0.5 [&_svg[data-composer-control-icon]]:mx-0", |
| 20 | size === "xs" | 20 | size === "xs" |
| 21 | ? "h-7 gap-1 px-[calc(--spacing(2)-1px)] font-normal text-muted-foreground/70 text-sm [--control-icon-color:currentColor] hover:text-foreground/80 sm:h-6 sm:text-xs [&_svg:not([class*='size-'])]:size-4 sm:[&_svg:not([class*='size-'])]:size-3.5 [&_svg[data-composer-control-chevron]]:ms-0 [&_svg[data-composer-control-chevron]]:-me-1" | 21 | ? "h-7 gap-1 px-1.75 font-normal text-muted-foreground/70 text-sm hover:text-foreground/80 sm:h-6 sm:text-xs [&_svg:not([class*='size-'])]:size-4 sm:[&_svg:not([class*='size-'])]:size-3.5 [&_svg[data-composer-control-chevron]]:ms-0 [&_svg[data-composer-control-chevron]]:-me-1" |
| 22 | : "h-7 gap-1.5 px-2.5 font-medium text-secondary-label [--control-icon-color:var(--contrast-muted-foreground)] hover:text-foreground sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4", | 22 | : "h-7 gap-1.5 px-2.5 font-medium text-secondary-label [&_svg:not([class*='text-'])]:text-muted-foreground hover:text-foreground sm:text-sm [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4", |
| 23 | "aria-pressed:bg-accent aria-pressed:text-accent-foreground aria-pressed:hover:bg-accent/80", | 23 | "aria-pressed:bg-accent aria-pressed:text-accent-foreground aria-pressed:hover:bg-accent/80", |
| 24 | className, | 24 | className, |
| 25 | ); | 25 | ); |
apps/web/src/components/chat/ComposerPendingApprovalPanel.tsx+1-1| ... | @@ -41,7 +41,7 @@ export const ComposerPendingApprovalPanel = memo(function ComposerPendingApprova | ... | @@ -41,7 +41,7 @@ export const ComposerPendingApprovalPanel = memo(function ComposerPendingApprova |
| 41 | className={cn("flex min-w-0 flex-1 flex-col items-start gap-1", className)} | 41 | className={cn("flex min-w-0 flex-1 flex-col items-start gap-1", className)} |
| 42 | role="group" | 42 | role="group" |
| 43 | > | 43 | > |
| 44 | <span className="flex w-full min-w-0 items-center gap-2 text-[11px] text-muted-foreground"> | 44 | <span className="flex w-full min-w-0 items-center gap-2 text-2xs text-muted-foreground"> |
| 45 | <span className="shrink-0 font-medium text-warning">{fallbackLabel}</span> | 45 | <span className="shrink-0 font-medium text-warning">{fallbackLabel}</span> |
| 46 | {approval.appName ? <span className="min-w-0 truncate">{approval.appName}</span> : null} | 46 | {approval.appName ? <span className="min-w-0 truncate">{approval.appName}</span> : null} |
| 47 | {pendingCount > 1 ? ( | 47 | {pendingCount > 1 ? ( |
apps/web/src/components/chat/ComposerPendingUserInputPanel.tsx+3-5| ... | @@ -198,7 +198,7 @@ const ComposerPendingUserInputCard = memo(function ComposerPendingUserInputCard( | ... | @@ -198,7 +198,7 @@ const ComposerPendingUserInputCard = memo(function ComposerPendingUserInputCard( |
| 198 | </ComposerBanner.Content> | 198 | </ComposerBanner.Content> |
| 199 | <ComposerBanner.Actions> | 199 | <ComposerBanner.Actions> |
| 200 | {prompt.questions.length > 1 ? ( | 200 | {prompt.questions.length > 1 ? ( |
| 201 | <span className="text-[10px] font-medium text-muted-foreground tabular-nums"> | 201 | <span className="text-3xs font-medium text-muted-foreground tabular-nums"> |
| 202 | {questionIndex + 1}/{prompt.questions.length} | 202 | {questionIndex + 1}/{prompt.questions.length} |
| 203 | </span> | 203 | </span> |
| 204 | ) : null} | 204 | ) : null} |
| ... | @@ -257,9 +257,7 @@ const ComposerPendingUserInputCard = memo(function ComposerPendingUserInputCard( | ... | @@ -257,9 +257,7 @@ const ComposerPendingUserInputCard = memo(function ComposerPendingUserInputCard( |
| 257 | <div className="min-w-0 flex-1 flex flex-col gap-0.5"> | 257 | <div className="min-w-0 flex-1 flex flex-col gap-0.5"> |
| 258 | <span className="text-sm font-medium">{option.label}</span> | 258 | <span className="text-sm font-medium">{option.label}</span> |
| 259 | {option.description && option.description !== option.label ? ( | 259 | {option.description && option.description !== option.label ? ( |
| 260 | <span className="text-secondary-label text-[11px]"> | 260 | <span className="text-secondary-label text-2xs">{option.description}</span> |
| 261 | {option.description} | ||
| 262 | </span> | ||
| 263 | ) : null} | 261 | ) : null} |
| 264 | </div> | 262 | </div> |
| 265 | {isSelected ? ( | 263 | {isSelected ? ( |
| ... | @@ -267,7 +265,7 @@ const ComposerPendingUserInputCard = memo(function ComposerPendingUserInputCard( | ... | @@ -267,7 +265,7 @@ const ComposerPendingUserInputCard = memo(function ComposerPendingUserInputCard( |
| 267 | ) : shortcutKey !== null ? ( | 265 | ) : shortcutKey !== null ? ( |
| 268 | <kbd | 266 | <kbd |
| 269 | className={cn( | 267 | className={cn( |
| 270 | "flex size-5 shrink-0 items-center justify-center text-[10px] font-medium text-muted-foreground tabular-nums", | 268 | "flex size-5 shrink-0 items-center justify-center text-3xs font-medium text-muted-foreground tabular-nums", |
| 271 | )} | 269 | )} |
| 272 | > | 270 | > |
| 273 | {shortcutKey} | 271 | {shortcutKey} |
apps/web/src/components/chat/ComposerPrimaryActions.tsx+2-2| ... | @@ -91,7 +91,7 @@ export const ComposerPrimaryActions = memo(function ComposerPrimaryActions({ | ... | @@ -91,7 +91,7 @@ export const ComposerPrimaryActions = memo(function ComposerPrimaryActions({ |
| 91 | <button | 91 | <button |
| 92 | type="button" | 92 | type="button" |
| 93 | className={cn( | 93 | className={cn( |
| 94 | "flex cursor-pointer items-center justify-center rounded-full bg-destructive/90 text-white shadow-xs shadow-destructive/24 inset-shadow-[0_1px_--theme(--color-white/16%)] transition-all duration-150 hover:bg-destructive hover:scale-105 active:inset-shadow-[0_1px_--theme(--color-black/8%)] active:shadow-none", | 94 | "flex cursor-pointer items-center justify-center rounded-full bg-destructive/90 text-white shadow-xs shadow-destructive/24 inset-shadow-2xs inset-shadow-white/16 transition-all duration-150 hover:bg-destructive hover:scale-105 active:inset-shadow-black/8 active:shadow-none", |
| 95 | insidePendingAction | 95 | insidePendingAction |
| 96 | ? "size-8 sm:size-7" | 96 | ? "size-8 sm:size-7" |
| 97 | : hasSendableContent | 97 | : hasSendableContent |
| ... | @@ -215,7 +215,7 @@ export const ComposerPrimaryActions = memo(function ComposerPrimaryActions({ | ... | @@ -215,7 +215,7 @@ export const ComposerPrimaryActions = memo(function ComposerPrimaryActions({ |
| 215 | <button | 215 | <button |
| 216 | type="submit" | 216 | type="submit" |
| 217 | className={cn( | 217 | className={cn( |
| 218 | "relative isolate flex h-9 w-9 items-center justify-center overflow-hidden rounded-full shadow-xs transition-all duration-150 enabled:cursor-pointer enabled:inset-shadow-[0_1px_--theme(--color-white/16%)] hover:scale-105 active:inset-shadow-[0_1px_--theme(--color-black/8%)] active:shadow-none disabled:pointer-events-none disabled:opacity-30 disabled:shadow-none disabled:hover:scale-100 sm:h-8 sm:w-8", | 218 | "relative isolate flex h-9 w-9 items-center justify-center overflow-hidden rounded-full shadow-xs transition-all duration-150 enabled:cursor-pointer enabled:inset-shadow-2xs enabled:inset-shadow-white/16 hover:scale-105 active:inset-shadow-black/8 active:shadow-none disabled:pointer-events-none disabled:opacity-30 disabled:shadow-none disabled:hover:scale-100 sm:h-8 sm:w-8", |
| 219 | stageBackdropVariant | 219 | stageBackdropVariant |
| 220 | ? "bg-transparent text-white enabled:shadow-black/24 enabled:hover:brightness-110" | 220 | ? "bg-transparent text-white enabled:shadow-black/24 enabled:hover:brightness-110" |
| 221 | : "bg-message-action text-message-action-foreground enabled:shadow-message-action/24 hover:bg-message-action-hover", | 221 | : "bg-message-action text-message-action-foreground enabled:shadow-message-action/24 hover:bg-message-action-hover", |
apps/web/src/components/chat/ComposerStashBadge.tsx+1-1| ... | @@ -25,7 +25,7 @@ export const ComposerStashBadge = memo(function ComposerStashBadge(props: { | ... | @@ -25,7 +25,7 @@ export const ComposerStashBadge = memo(function ComposerStashBadge(props: { |
| 25 | key={props.pulseKey} | 25 | key={props.pulseKey} |
| 26 | className={cn( | 26 | className={cn( |
| 27 | props.pulsing | 27 | props.pulsing |
| 28 | ? "animate-[prompt-stash-count-enter_180ms_ease-out_both] text-primary motion-reduce:animate-none" | 28 | ? "text-primary transition-[opacity,translate] duration-180 ease-out starting:translate-y-0.5 starting:opacity-0 motion-reduce:transition-none" |
| 29 | : "text-muted-foreground", | 29 | : "text-muted-foreground", |
| 30 | )} | 30 | )} |
| 31 | > | 31 | > |
apps/web/src/components/chat/ComposerSurface.tsx+10-10| ... | @@ -19,7 +19,7 @@ function Shell({ | ... | @@ -19,7 +19,7 @@ function Shell({ |
| 19 | "[html[data-theme-id]_&]:[--chat-composer-glass-surface:var(--app-theme-surface-raised)] [html[data-theme-id]_&]:[--chat-composer-outline:var(--app-theme-toolbar-border)]", | 19 | "[html[data-theme-id]_&]:[--chat-composer-glass-surface:var(--app-theme-surface-raised)] [html[data-theme-id]_&]:[--chat-composer-outline:var(--app-theme-toolbar-border)]", |
| 20 | "dark:[html[data-theme-id]:not([data-theme-id=t3-chat])_&]:[--chat-composer-highlight:color-mix(in_srgb,var(--app-theme-input)_12%,transparent)] dark:[html[data-theme-id]:not([data-theme-id=t3-chat])_&]:[--chat-composer-outline:color-mix(in_srgb,var(--app-theme-input)_30%,var(--background))]", | 20 | "dark:[html[data-theme-id]:not([data-theme-id=t3-chat])_&]:[--chat-composer-highlight:color-mix(in_srgb,var(--app-theme-input)_12%,transparent)] dark:[html[data-theme-id]:not([data-theme-id=t3-chat])_&]:[--chat-composer-outline:color-mix(in_srgb,var(--app-theme-input)_30%,var(--background))]", |
| 21 | "dark:[html[data-theme-id=t3-chat]_&]:[--chat-composer-highlight:color-mix(in_srgb,#432d48_12%,transparent)] dark:[html[data-theme-id=t3-chat]_&]:[--chat-composer-outline:#241e28]", | 21 | "dark:[html[data-theme-id=t3-chat]_&]:[--chat-composer-highlight:color-mix(in_srgb,#432d48_12%,transparent)] dark:[html[data-theme-id=t3-chat]_&]:[--chat-composer-outline:#241e28]", |
| 22 | "before:pointer-events-none before:absolute before:inset-0 before:z-0 before:rounded-[22px] before:bg-[color-mix(in_srgb,var(--chat-composer-glass-surface)_var(--glass-opacity),transparent)] before:backdrop-blur-(--glass-blur) before:backdrop-saturate-(--glass-saturation)", | 22 | "before:pointer-events-none before:absolute before:inset-0 before:z-0 before:rounded-3xl before:bg-(--chat-composer-glass-surface)/(--glass-opacity) before:backdrop-blur-(--glass-blur) before:backdrop-saturate-(--glass-saturation)", |
| 23 | "not-supports-[((backdrop-filter:blur(1px))_or_(-webkit-backdrop-filter:blur(1px)))]:before:bg-(--chat-composer-glass-surface)", | 23 | "not-supports-[((backdrop-filter:blur(1px))_or_(-webkit-backdrop-filter:blur(1px)))]:before:bg-(--chat-composer-glass-surface)", |
| 24 | "has-data-[composer-banner-surface=attached]:before:hidden", | 24 | "has-data-[composer-banner-surface=attached]:before:hidden", |
| 25 | contextStrip && [ | 25 | contextStrip && [ |
| ... | @@ -37,7 +37,7 @@ function Shell({ | ... | @@ -37,7 +37,7 @@ function Shell({ |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | const outlineClasses = | 39 | const outlineClasses = |
| 40 | "after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit] after:border after:border-(--chat-composer-outline) dark:after:shadow-[inset_0_1px_var(--chat-composer-highlight)]"; | 40 | "after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit] after:border after:border-(--chat-composer-outline) dark:after:inset-shadow-2xs dark:after:inset-shadow-(color:--chat-composer-highlight)"; |
| 41 | 41 | ||
| 42 | // The bottom strip continues the outline, so leave the seam between its corners open. | 42 | // The bottom strip continues the outline, so leave the seam between its corners open. |
| 43 | const contextSeamClasses = | 43 | const contextSeamClasses = |
| ... | @@ -48,7 +48,7 @@ function Host({ className, ...props }: ComponentProps<"div">) { | ... | @@ -48,7 +48,7 @@ function Host({ className, ...props }: ComponentProps<"div">) { |
| 48 | <div | 48 | <div |
| 49 | data-slot="composer-host" | 49 | data-slot="composer-host" |
| 50 | className={cn( | 50 | className={cn( |
| 51 | "relative z-10 w-full rounded-[22px] shadow-[0_12px_28px_-18px_rgb(0_0_0/40%)] after:z-1 dark:shadow-none", | 51 | "relative z-10 w-full rounded-3xl shadow-composer after:z-1 dark:shadow-none", |
| 52 | outlineClasses, | 52 | outlineClasses, |
| 53 | contextSeamClasses, | 53 | contextSeamClasses, |
| 54 | "group-has-data-[composer-banner-surface=attached]/composer-surface:shadow-none group-has-data-[composer-banner-surface=attached]/composer-surface:after:hidden", | 54 | "group-has-data-[composer-banner-surface=attached]/composer-surface:shadow-none group-has-data-[composer-banner-surface=attached]/composer-surface:after:hidden", |
| ... | @@ -64,12 +64,12 @@ function Main({ className, ...props }: ComponentProps<"div">) { | ... | @@ -64,12 +64,12 @@ function Main({ className, ...props }: ComponentProps<"div">) { |
| 64 | <div | 64 | <div |
| 65 | data-chat-composer-main-surface="true" | 65 | data-chat-composer-main-surface="true" |
| 66 | className={cn( | 66 | className={cn( |
| 67 | "group relative z-10 rounded-[22px] p-px transition-colors duration-200", | 67 | "group relative z-10 rounded-3xl p-px transition-colors duration-200", |
| 68 | outlineClasses, | 68 | outlineClasses, |
| 69 | contextSeamClasses, | 69 | contextSeamClasses, |
| 70 | "after:z-20 after:hidden group-has-data-[composer-banner-surface=attached]/composer-surface:after:block", | 70 | "after:z-20 after:hidden group-has-data-[composer-banner-surface=attached]/composer-surface:after:block", |
| 71 | "group-has-data-[composer-banner-surface=attached]/composer-surface:bg-[color-mix(in_srgb,var(--chat-composer-glass-surface)_var(--glass-opacity),transparent)] group-has-data-[composer-banner-surface=attached]/composer-surface:backdrop-blur-(--glass-blur) group-has-data-[composer-banner-surface=attached]/composer-surface:backdrop-saturate-(--glass-saturation)", | 71 | "group-has-data-[composer-banner-surface=attached]/composer-surface:bg-(--chat-composer-glass-surface)/(--glass-opacity) group-has-data-[composer-banner-surface=attached]/composer-surface:backdrop-blur-(--glass-blur) group-has-data-[composer-banner-surface=attached]/composer-surface:backdrop-saturate-(--glass-saturation)", |
| 72 | "group-has-data-[composer-banner-surface=attached]/composer-surface:shadow-[0_12px_28px_-18px_rgb(0_0_0/40%)] dark:group-has-data-[composer-banner-surface=attached]/composer-surface:shadow-none", | 72 | "group-has-data-[composer-banner-surface=attached]/composer-surface:shadow-composer dark:group-has-data-[composer-banner-surface=attached]/composer-surface:shadow-none", |
| 73 | "not-supports-[((backdrop-filter:blur(1px))_or_(-webkit-backdrop-filter:blur(1px)))]:group-has-data-[composer-banner-surface=attached]/composer-surface:bg-(--chat-composer-glass-surface)", | 73 | "not-supports-[((backdrop-filter:blur(1px))_or_(-webkit-backdrop-filter:blur(1px)))]:group-has-data-[composer-banner-surface=attached]/composer-surface:bg-(--chat-composer-glass-surface)", |
| 74 | "group-has-data-[composer-banner-surface=attached]/composer-surface:**:data-[chat-composer-mobile-collapsed=true]:min-h-[calc(1rem+1px)]", | 74 | "group-has-data-[composer-banner-surface=attached]/composer-surface:**:data-[chat-composer-mobile-collapsed=true]:min-h-[calc(1rem+1px)]", |
| 75 | className, | 75 | className, |
| ... | @@ -85,10 +85,10 @@ function ContextStrip({ className, ...props }: ComponentProps<"div">) { | ... | @@ -85,10 +85,10 @@ function ContextStrip({ className, ...props }: ComponentProps<"div">) { |
| 85 | data-slot="composer-context-strip" | 85 | data-slot="composer-context-strip" |
| 86 | className={cn( | 86 | className={cn( |
| 87 | "group/composer-context relative isolate mx-auto -mt-4 flex w-[calc(100%-2*var(--chat-composer-drawer-inset))] items-center gap-2 overflow-x-clip overflow-y-visible ps-1 pe-2 pt-5 pb-1", | 87 | "group/composer-context relative isolate mx-auto -mt-4 flex w-[calc(100%-2*var(--chat-composer-drawer-inset))] items-center gap-2 overflow-x-clip overflow-y-visible ps-1 pe-2 pt-5 pb-1", |
| 88 | "before:absolute before:inset-0 before:-z-1 before:rounded-b-[16px] before:border before:border-(--chat-composer-outline) before:mask-[linear-gradient(to_bottom,transparent_0_1rem,black_1rem)] before:shadow-[0_12px_28px_-18px_rgb(0_0_0/40%)]", | 88 | "before:absolute before:inset-0 before:-z-1 before:rounded-b-2xl before:border before:border-(--chat-composer-outline) before:mask-b-from-transparent before:mask-b-from-4 before:mask-b-to-black before:mask-b-to-4 before:shadow-composer", |
| 89 | "dark:before:border-white/7 dark:before:bg-[linear-gradient(to_bottom,transparent_0_1rem,rgb(0_0_0/18%)_1rem,transparent_calc(1rem+10px)),linear-gradient(rgb(255_255_255/1%),rgb(255_255_255/1%))] dark:before:shadow-[0_14px_32px_-18px_rgb(0_0_0/75%)]", | 89 | "dark:before:border-white/7 dark:before:bg-composer-seam-below dark:before:shadow-composer-dark", |
| 90 | "group-has-data-[composer-banner-surface=attached]/composer-surface:before:bg-[color-mix(in_srgb,var(--chat-composer-glass-surface)_var(--glass-opacity),transparent)] group-has-data-[composer-banner-surface=attached]/composer-surface:before:backdrop-blur-(--glass-blur) group-has-data-[composer-banner-surface=attached]/composer-surface:before:backdrop-saturate-(--glass-saturation)", | 90 | "group-has-data-[composer-banner-surface=attached]/composer-surface:before:bg-(--chat-composer-glass-surface)/(--glass-opacity) group-has-data-[composer-banner-surface=attached]/composer-surface:before:backdrop-blur-(--glass-blur) group-has-data-[composer-banner-surface=attached]/composer-surface:before:backdrop-saturate-(--glass-saturation)", |
| 91 | "not-supports-[clip-path:shape(from_0_0,line_to_1px_1px)]:before:bg-[color-mix(in_srgb,var(--chat-composer-glass-surface)_var(--glass-opacity),transparent)] not-supports-[clip-path:shape(from_0_0,line_to_1px_1px)]:before:backdrop-blur-(--glass-blur) not-supports-[clip-path:shape(from_0_0,line_to_1px_1px)]:before:backdrop-saturate-(--glass-saturation)", | 91 | "not-supports-[clip-path:shape(from_0_0,line_to_1px_1px)]:before:bg-(--chat-composer-glass-surface)/(--glass-opacity) not-supports-[clip-path:shape(from_0_0,line_to_1px_1px)]:before:backdrop-blur-(--glass-blur) not-supports-[clip-path:shape(from_0_0,line_to_1px_1px)]:before:backdrop-saturate-(--glass-saturation)", |
| 92 | className, | 92 | className, |
| 93 | )} | 93 | )} |
| 94 | {...props} | 94 | {...props} |
apps/web/src/components/chat/ComposerTasksBadge.tsx+1-1| ... | @@ -200,7 +200,7 @@ export const ComposerTasksContent = memo(function ComposerTasksContent({ | ... | @@ -200,7 +200,7 @@ export const ComposerTasksContent = memo(function ComposerTasksContent({ |
| 200 | </ComposerBanner.Content> | 200 | </ComposerBanner.Content> |
| 201 | <ComposerBanner.Actions> | 201 | <ComposerBanner.Actions> |
| 202 | <span | 202 | <span |
| 203 | className="w-12 text-right text-[10px]/4 text-muted-foreground/45 tabular-nums" | 203 | className="w-12 text-right text-3xs/4 text-muted-foreground/45 tabular-nums" |
| 204 | data-composer-task-duration="true" | 204 | data-composer-task-duration="true" |
| 205 | > | 205 | > |
| 206 | {step.durationMs !== undefined | 206 | {step.durationMs !== undefined |
apps/web/src/components/chat/ContextWindowMeter.tsx+6-6| ... | @@ -92,11 +92,11 @@ export function ContextWindowMeter(props: { | ... | @@ -92,11 +92,11 @@ export function ContextWindowMeter(props: { |
| 92 | width="sm" | 92 | width="sm" |
| 93 | className="text-left whitespace-normal" | 93 | className="text-left whitespace-normal" |
| 94 | > | 94 | > |
| 95 | <div className="flex flex-col gap-2 p-[var(--floating-content-inset)]"> | 95 | <div className="flex flex-col gap-2 p-(--floating-content-inset)"> |
| 96 | <div className="flex items-center justify-between gap-3"> | 96 | <div className="flex items-center justify-between gap-3"> |
| 97 | <div className="font-medium text-muted-foreground text-xs">Context Window</div> | 97 | <div className="font-medium text-muted-foreground text-xs">Context Window</div> |
| 98 | {usage.maxTokens !== null && usedPercentage ? ( | 98 | {usage.maxTokens !== null && usedPercentage ? ( |
| 99 | <div className="text-secondary-label text-[11px] tabular-nums"> | 99 | <div className="text-secondary-label text-2xs tabular-nums"> |
| 100 | <span>{usedPercentage}</span> | 100 | <span>{usedPercentage}</span> |
| 101 | <span className="mx-1">·</span> | 101 | <span className="mx-1">·</span> |
| 102 | <span> | 102 | <span> |
| ... | @@ -105,7 +105,7 @@ export function ContextWindowMeter(props: { | ... | @@ -105,7 +105,7 @@ export function ContextWindowMeter(props: { |
| 105 | </span> | 105 | </span> |
| 106 | </div> | 106 | </div> |
| 107 | ) : ( | 107 | ) : ( |
| 108 | <div className="text-secondary-label text-[11px] tabular-nums"> | 108 | <div className="text-secondary-label text-2xs tabular-nums"> |
| 109 | {formatContextWindowTokens(usage.usedTokens)} | 109 | {formatContextWindowTokens(usage.usedTokens)} |
| 110 | </div> | 110 | </div> |
| 111 | )} | 111 | )} |
| ... | @@ -126,7 +126,7 @@ export function ContextWindowMeter(props: { | ... | @@ -126,7 +126,7 @@ export function ContextWindowMeter(props: { |
| 126 | </div> | 126 | </div> |
| 127 | ) : null} | 127 | ) : null} |
| 128 | {showTotalProcessed ? ( | 128 | {showTotalProcessed ? ( |
| 129 | <div className="flex items-center justify-between gap-3 text-[11px] leading-4"> | 129 | <div className="flex items-center justify-between gap-3 text-2xs leading-4"> |
| 130 | <span className="text-secondary-label">Total processed</span> | 130 | <span className="text-secondary-label">Total processed</span> |
| 131 | <span className="font-medium tabular-nums text-secondary-label"> | 131 | <span className="font-medium tabular-nums text-secondary-label"> |
| 132 | {formatContextWindowTokens(totalProcessedTokens)} | 132 | {formatContextWindowTokens(totalProcessedTokens)} |
| ... | @@ -134,7 +134,7 @@ export function ContextWindowMeter(props: { | ... | @@ -134,7 +134,7 @@ export function ContextWindowMeter(props: { |
| 134 | </div> | 134 | </div> |
| 135 | ) : null} | 135 | ) : null} |
| 136 | {usage.compactsAutomatically ? ( | 136 | {usage.compactsAutomatically ? ( |
| 137 | <div className="mt-1 text-pretty text-secondary-label text-[11px] font-medium"> | 137 | <div className="mt-1 text-pretty text-secondary-label text-2xs font-medium"> |
| 138 | {formatContextWindowCompactionMessage(modelDisplayName, usage.autoCompactThreshold)} | 138 | {formatContextWindowCompactionMessage(modelDisplayName, usage.autoCompactThreshold)} |
| 139 | </div> | 139 | </div> |
| 140 | ) : null} | 140 | ) : null} |
| ... | @@ -151,7 +151,7 @@ export function ContextWindowMeter(props: { | ... | @@ -151,7 +151,7 @@ export function ContextWindowMeter(props: { |
| 151 | Compact context | 151 | Compact context |
| 152 | </Button> | 152 | </Button> |
| 153 | {compactDisabled && compactDisabledReason ? ( | 153 | {compactDisabled && compactDisabledReason ? ( |
| 154 | <div className="text-pretty text-secondary-label text-[11px]"> | 154 | <div className="text-pretty text-secondary-label text-2xs"> |
| 155 | {compactDisabledReason} | 155 | {compactDisabledReason} |
| 156 | </div> | 156 | </div> |
| 157 | ) : null} | 157 | ) : null} |
apps/web/src/components/chat/ExpandedImageDialog.tsx+1-1| ... | @@ -219,7 +219,7 @@ export const ExpandedImageDialog = memo(function ExpandedImageDialog({ | ... | @@ -219,7 +219,7 @@ export const ExpandedImageDialog = memo(function ExpandedImageDialog({ |
| 219 | accessibilityDetails ? ( | 219 | accessibilityDetails ? ( |
| 220 | <SnapShotAccessibilityData | 220 | <SnapShotAccessibilityData |
| 221 | details={accessibilityDetails} | 221 | details={accessibilityDetails} |
| 222 | className="h-[min(var(--media-height),40rem)] w-[min(var(--media-width),42rem)] animate-[snap-shot-contents-enter_140ms_ease-out] rounded-lg border border-border/70 bg-background p-4 text-xs leading-5 shadow-2xl motion-reduce:animate-none" | 222 | className="h-[min(var(--media-height),40rem)] w-[min(var(--media-width),42rem)] transition-opacity duration-140 ease-out starting:opacity-0 rounded-lg border border-border/70 bg-background p-4 text-xs leading-5 shadow-2xl motion-reduce:transition-none" |
| 223 | /> | 223 | /> |
| 224 | ) : null | 224 | ) : null |
| 225 | ) : item.src === null || failedImageSrc === item.src ? ( | 225 | ) : item.src === null || failedImageSrc === item.src ? ( |
apps/web/src/components/chat/MessagesTimeline.tsx+22-22| ... | @@ -344,7 +344,7 @@ function TimelineLoadEarlierHeader({ | ... | @@ -344,7 +344,7 @@ function TimelineLoadEarlierHeader({ |
| 344 | fade: boolean; | 344 | fade: boolean; |
| 345 | }) { | 345 | }) { |
| 346 | return ( | 346 | return ( |
| 347 | <div className={fade ? "pt-[var(--workspace-titlebar-scroll-fade-height)]" : "pt-3 sm:pt-4"}> | 347 | <div className={fade ? "pt-(--workspace-titlebar-scroll-fade-height)" : "pt-3 sm:pt-4"}> |
| 348 | <div className="mx-auto w-full max-w-3xl pb-2"> | 348 | <div className="mx-auto w-full max-w-3xl pb-2"> |
| 349 | <button | 349 | <button |
| 350 | type="button" | 350 | type="button" |
| ... | @@ -1539,7 +1539,7 @@ function TimelineMinimap({ | ... | @@ -1539,7 +1539,7 @@ function TimelineMinimap({ |
| 1539 | <span | 1539 | <span |
| 1540 | aria-hidden="true" | 1540 | aria-hidden="true" |
| 1541 | className={cn( | 1541 | className={cn( |
| 1542 | "pointer-events-none absolute left-0 h-0.5 -translate-y-1/2 rounded-full bg-muted-foreground/35 transition-[background-color,width] duration-150 data-[in-view=true]:bg-foreground/90", | 1542 | "pointer-events-none absolute left-0 h-0.5 -translate-y-1/2 rounded-full bg-muted-foreground/35 transition-[width,background-color] duration-150 data-[in-view=true]:bg-foreground/90", |
| 1543 | activeDistance === 0 | 1543 | activeDistance === 0 |
| 1544 | ? "w-6 bg-muted-foreground/75" | 1544 | ? "w-6 bg-muted-foreground/75" |
| 1545 | : activeDistance === 1 | 1545 | : activeDistance === 1 |
| ... | @@ -1885,7 +1885,7 @@ function UserVideoAttachment({ file }: { readonly file: ChatFileAttachment }) { | ... | @@ -1885,7 +1885,7 @@ function UserVideoAttachment({ file }: { readonly file: ChatFileAttachment }) { |
| 1885 | 1885 | ||
| 1886 | if (asset === null && src === null) { | 1886 | if (asset === null && src === null) { |
| 1887 | return ( | 1887 | return ( |
| 1888 | <div className="flex aspect-[4/3] w-full items-center justify-center rounded-lg border border-border/80 bg-black px-2 py-3 text-center text-[11px] text-white/70"> | 1888 | <div className="flex aspect-[4/3] w-full items-center justify-center rounded-lg border border-border/80 bg-black px-2 py-3 text-center text-2xs text-white/70"> |
| 1889 | {file.name} | 1889 | {file.name} |
| 1890 | </div> | 1890 | </div> |
| 1891 | ); | 1891 | ); |
| ... | @@ -2112,7 +2112,7 @@ function UserTimelineRow({ row }: { row: Extract<TimelineRow, { kind: "message" | ... | @@ -2112,7 +2112,7 @@ function UserTimelineRow({ row }: { row: Extract<TimelineRow, { kind: "message" |
| 2112 | /> | 2112 | /> |
| 2113 | </button> | 2113 | </button> |
| 2114 | ) : ( | 2114 | ) : ( |
| 2115 | <div className="flex min-h-[72px] items-center justify-center px-2 py-3 text-center text-secondary-label text-[11px]"> | 2115 | <div className="flex min-h-[72px] items-center justify-center px-2 py-3 text-center text-secondary-label text-2xs"> |
| 2116 | {image.name} | 2116 | {image.name} |
| 2117 | </div> | 2117 | </div> |
| 2118 | )} | 2118 | )} |
| ... | @@ -2756,7 +2756,7 @@ function ReasoningTraceBlock({ | ... | @@ -2756,7 +2756,7 @@ function ReasoningTraceBlock({ |
| 2756 | className="flex min-h-6 cursor-pointer select-none items-center gap-1.5 rounded-md px-0.5 text-start text-sm leading-relaxed transition-colors hover:bg-accent/20 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring/70" | 2756 | className="flex min-h-6 cursor-pointer select-none items-center gap-1.5 rounded-md px-0.5 text-start text-sm leading-relaxed transition-colors hover:bg-accent/20 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring/70" |
| 2757 | > | 2757 | > |
| 2758 | <span className="flex size-6 shrink-0 items-center justify-center text-icon-muted"> | 2758 | <span className="flex size-6 shrink-0 items-center justify-center text-icon-muted"> |
| 2759 | <BrainIcon aria-hidden className="block size-4 shrink-0 stroke-[1.8] opacity-70" /> | 2759 | <BrainIcon aria-hidden className="block size-4 shrink-0 stroke-2 opacity-70" /> |
| 2760 | </span> | 2760 | </span> |
| 2761 | <span | 2761 | <span |
| 2762 | ref={streaming ? observeVisibleAnimation : undefined} | 2762 | ref={streaming ? observeVisibleAnimation : undefined} |
| ... | @@ -2829,7 +2829,7 @@ const ReasoningTimelineRow = memo(function ReasoningTimelineRow({ | ... | @@ -2829,7 +2829,7 @@ const ReasoningTimelineRow = memo(function ReasoningTimelineRow({ |
| 2829 | className="flex cursor-pointer select-none items-center gap-1.5 rounded-md px-0.5 py-0.5 text-start transition-colors hover:bg-accent/20 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring/70" | 2829 | className="flex cursor-pointer select-none items-center gap-1.5 rounded-md px-0.5 py-0.5 text-start transition-colors hover:bg-accent/20 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring/70" |
| 2830 | > | 2830 | > |
| 2831 | <span className="flex size-6 shrink-0 items-center justify-center text-icon-muted"> | 2831 | <span className="flex size-6 shrink-0 items-center justify-center text-icon-muted"> |
| 2832 | <BrainIcon aria-hidden className="block size-4 shrink-0 stroke-[1.8] opacity-70" /> | 2832 | <BrainIcon aria-hidden className="block size-4 shrink-0 stroke-2 opacity-70" /> |
| 2833 | </span> | 2833 | </span> |
| 2834 | <span className="flex min-w-0 flex-1 items-center gap-1.5"> | 2834 | <span className="flex min-w-0 flex-1 items-center gap-1.5"> |
| 2835 | <span className="relative min-w-0 flex-1 truncate text-secondary-label text-sm leading-relaxed"> | 2835 | <span className="relative min-w-0 flex-1 truncate text-secondary-label text-sm leading-relaxed"> |
| ... | @@ -3208,7 +3208,7 @@ function LiveActivityContent({ | ... | @@ -3208,7 +3208,7 @@ function LiveActivityContent({ |
| 3208 | <ToolActivityIconView | 3208 | <ToolActivityIconView |
| 3209 | icon={toolIcon} | 3209 | icon={toolIcon} |
| 3210 | fallbackName={iconName} | 3210 | fallbackName={iconName} |
| 3211 | className="block size-4 shrink-0 stroke-[1.8]" | 3211 | className="block size-4 shrink-0 stroke-2" |
| 3212 | muted={!highlighted} | 3212 | muted={!highlighted} |
| 3213 | /> | 3213 | /> |
| 3214 | </span> | 3214 | </span> |
| ... | @@ -3329,7 +3329,7 @@ function WorkGroupToggleTimelineRow({ | ... | @@ -3329,7 +3329,7 @@ function WorkGroupToggleTimelineRow({ |
| 3329 | fallbackName={ | 3329 | fallbackName={ |
| 3330 | row.summaryToolIcon ?? row.toolSurface ?? toolGroupSummaryIconName(row.summaryKind) | 3330 | row.summaryToolIcon ?? row.toolSurface ?? toolGroupSummaryIconName(row.summaryKind) |
| 3331 | } | 3331 | } |
| 3332 | className="size-4 shrink-0 stroke-[1.8]" | 3332 | className="size-4 shrink-0 stroke-2" |
| 3333 | muted | 3333 | muted |
| 3334 | /> | 3334 | /> |
| 3335 | </span> | 3335 | </span> |
| ... | @@ -3545,7 +3545,7 @@ function UserMessagePreviewAnnotationDetails(props: { | ... | @@ -3545,7 +3545,7 @@ function UserMessagePreviewAnnotationDetails(props: { |
| 3545 | {props.record.comment} | 3545 | {props.record.comment} |
| 3546 | </div> | 3546 | </div> |
| 3547 | ) : null} | 3547 | ) : null} |
| 3548 | <div className="mt-1 flex items-center gap-2 text-secondary-label text-[10px]"> | 3548 | <div className="mt-1 flex items-center gap-2 text-secondary-label text-3xs"> |
| 3549 | {props.record.targetSummary ? ( | 3549 | {props.record.targetSummary ? ( |
| 3550 | <span className="truncate">{props.record.targetSummary}</span> | 3550 | <span className="truncate">{props.record.targetSummary}</span> |
| 3551 | ) : null} | 3551 | ) : null} |
| ... | @@ -3577,7 +3577,7 @@ function UserMessagePreviewAnnotationDetails(props: { | ... | @@ -3577,7 +3577,7 @@ function UserMessagePreviewAnnotationDetails(props: { |
| 3577 | ) : null} | 3577 | ) : null} |
| 3578 | </div> | 3578 | </div> |
| 3579 | {element.htmlPreview?.trim() ? ( | 3579 | {element.htmlPreview?.trim() ? ( |
| 3580 | <pre className="mt-1 max-h-24 overflow-auto whitespace-pre-wrap rounded bg-muted/60 px-2 py-1.5 text-[10px] leading-relaxed"> | 3580 | <pre className="mt-1 max-h-24 overflow-auto whitespace-pre-wrap rounded bg-muted/60 px-2 py-1.5 text-3xs leading-relaxed"> |
| 3581 | {element.htmlPreview.trim()} | 3581 | {element.htmlPreview.trim()} |
| 3582 | </pre> | 3582 | </pre> |
| 3583 | ) : null} | 3583 | ) : null} |
| ... | @@ -3585,7 +3585,7 @@ function UserMessagePreviewAnnotationDetails(props: { | ... | @@ -3585,7 +3585,7 @@ function UserMessagePreviewAnnotationDetails(props: { |
| 3585 | ); | 3585 | ); |
| 3586 | })} | 3586 | })} |
| 3587 | {(props.record.elements?.length ?? 0) > visibleElements.length ? ( | 3587 | {(props.record.elements?.length ?? 0) > visibleElements.length ? ( |
| 3588 | <div className="text-secondary-label text-[10px]"> | 3588 | <div className="text-secondary-label text-3xs"> |
| 3589 | {(props.record.elements?.length ?? 0) - visibleElements.length} more selected | 3589 | {(props.record.elements?.length ?? 0) - visibleElements.length} more selected |
| 3590 | elements | 3590 | elements |
| 3591 | </div> | 3591 | </div> |
| ... | @@ -3611,7 +3611,7 @@ function UserMessageElementDetails({ | ... | @@ -3611,7 +3611,7 @@ function UserMessageElementDetails({ |
| 3611 | <div className="truncate text-message-foreground text-xs font-medium"> | 3611 | <div className="truncate text-message-foreground text-xs font-medium"> |
| 3612 | {record.pageTitle?.trim() || record.pageUrl} | 3612 | {record.pageTitle?.trim() || record.pageUrl} |
| 3613 | </div> | 3613 | </div> |
| 3614 | <div className="mt-0.5 truncate text-secondary-label text-[10px]">{record.pageUrl}</div> | 3614 | <div className="mt-0.5 truncate text-secondary-label text-3xs">{record.pageUrl}</div> |
| 3615 | </div> | 3615 | </div> |
| 3616 | <div className="space-y-2 px-3 py-2.5"> | 3616 | <div className="space-y-2 px-3 py-2.5"> |
| 3617 | <div className="flex min-w-0 items-center gap-2 text-xs"> | 3617 | <div className="flex min-w-0 items-center gap-2 text-xs"> |
| ... | @@ -4013,7 +4013,7 @@ function UserMessageReviewCommentCard({ comment }: { comment: ReviewCommentConte | ... | @@ -4013,7 +4013,7 @@ function UserMessageReviewCommentCard({ comment }: { comment: ReviewCommentConte |
| 4013 | <div className="text-message-foreground text-xs font-medium"> | 4013 | <div className="text-message-foreground text-xs font-medium"> |
| 4014 | {formatWorkspaceRelativePath(comment.filePath, ctx.workspaceRoot)} | 4014 | {formatWorkspaceRelativePath(comment.filePath, ctx.workspaceRoot)} |
| 4015 | </div> | 4015 | </div> |
| 4016 | <div className="text-secondary-label text-[11px]"> | 4016 | <div className="text-secondary-label text-2xs"> |
| 4017 | {comment.sectionTitle} · {comment.rangeLabel} | 4017 | {comment.sectionTitle} · {comment.rangeLabel} |
| 4018 | </div> | 4018 | </div> |
| 4019 | </div> | 4019 | </div> |
| ... | @@ -4153,7 +4153,7 @@ function ToolActivityIconView(props: { | ... | @@ -4153,7 +4153,7 @@ function ToolActivityIconView(props: { |
| 4153 | muted: boolean; | 4153 | muted: boolean; |
| 4154 | }) { | 4154 | }) { |
| 4155 | const { resolvedTheme } = use(TimelineRowCtx); | 4155 | const { resolvedTheme } = use(TimelineRowCtx); |
| 4156 | const fallbackClassName = cn(props.className, props.muted && "opacity-70 light:brightness-[.6]"); | 4156 | const fallbackClassName = cn(props.className, props.muted && "opacity-70 light:brightness-60"); |
| 4157 | if (!props.icon) { | 4157 | if (!props.icon) { |
| 4158 | return <WorkEntryIcon name={props.fallbackName} className={fallbackClassName} />; | 4158 | return <WorkEntryIcon name={props.fallbackName} className={fallbackClassName} />; |
| 4159 | } | 4159 | } |
| ... | @@ -4213,7 +4213,7 @@ function NativeAppToolActivityIcon(props: { | ... | @@ -4213,7 +4213,7 @@ function NativeAppToolActivityIcon(props: { |
| 4213 | return ( | 4213 | return ( |
| 4214 | <WorkEntryIcon | 4214 | <WorkEntryIcon |
| 4215 | name={props.fallbackName} | 4215 | name={props.fallbackName} |
| 4216 | className={cn(props.className, props.muted && "opacity-70 light:brightness-[.6]")} | 4216 | className={cn(props.className, props.muted && "opacity-70 light:brightness-60")} |
| 4217 | /> | 4217 | /> |
| 4218 | ); | 4218 | ); |
| 4219 | } | 4219 | } |
| ... | @@ -4258,14 +4258,14 @@ function ToolActivityImageIcon(props: { | ... | @@ -4258,14 +4258,14 @@ function ToolActivityImageIcon(props: { |
| 4258 | {displayedSrc === null ? ( | 4258 | {displayedSrc === null ? ( |
| 4259 | <WorkEntryIcon | 4259 | <WorkEntryIcon |
| 4260 | name={props.fallbackName} | 4260 | name={props.fallbackName} |
| 4261 | className={cn(props.className, props.muted && "opacity-70 light:brightness-[.6]")} | 4261 | className={cn(props.className, props.muted && "opacity-70 light:brightness-60")} |
| 4262 | /> | 4262 | /> |
| 4263 | ) : null} | 4263 | ) : null} |
| 4264 | {displayedSrc ? ( | 4264 | {displayedSrc ? ( |
| 4265 | <span | 4265 | <span |
| 4266 | className={cn( | 4266 | className={cn( |
| 4267 | props.className, | 4267 | props.className, |
| 4268 | "inline-block overflow-hidden rounded-[3px] bg-background", | 4268 | "inline-block overflow-hidden rounded-xs bg-background", |
| 4269 | props.muted && "opacity-70", | 4269 | props.muted && "opacity-70", |
| 4270 | )} | 4270 | )} |
| 4271 | > | 4271 | > |
| ... | @@ -4275,7 +4275,7 @@ function ToolActivityImageIcon(props: { | ... | @@ -4275,7 +4275,7 @@ function ToolActivityImageIcon(props: { |
| 4275 | aria-hidden | 4275 | aria-hidden |
| 4276 | decoding="async" | 4276 | decoding="async" |
| 4277 | referrerPolicy="no-referrer" | 4277 | referrerPolicy="no-referrer" |
| 4278 | className={cn("block size-full object-contain", props.muted && "light:brightness-[.6]")} | 4278 | className={cn("block size-full object-contain", props.muted && "light:brightness-60")} |
| 4279 | onError={() => handleLoadError(displayedSrc)} | 4279 | onError={() => handleLoadError(displayedSrc)} |
| 4280 | /> | 4280 | /> |
| 4281 | </span> | 4281 | </span> |
| ... | @@ -4429,7 +4429,7 @@ function buildToolCallExpandedBody( | ... | @@ -4429,7 +4429,7 @@ function buildToolCallExpandedBody( |
| 4429 | } | 4429 | } |
| 4430 | 4430 | ||
| 4431 | const toolCallExpandedBodyClassName = | 4431 | const toolCallExpandedBodyClassName = |
| 4432 | "max-h-64 cursor-text overflow-auto whitespace-pre-wrap break-words font-mono text-secondary-label text-[length:var(--font-size-code,0.6875rem)] leading-relaxed select-text"; | 4432 | "max-h-64 cursor-text overflow-auto whitespace-pre-wrap break-words font-mono text-secondary-label text-(length:--font-size-code,var(--text-2xs)) leading-relaxed select-text"; |
| 4433 | 4433 | ||
| 4434 | function workEntryIconName(workEntry: TimelineWorkEntry): WorkEntryIconName { | 4434 | function workEntryIconName(workEntry: TimelineWorkEntry): WorkEntryIconName { |
| 4435 | if ( | 4435 | if ( |
| ... | @@ -4640,12 +4640,12 @@ function AgentSpawnMemberRow({ | ... | @@ -4640,12 +4640,12 @@ function AgentSpawnMemberRow({ |
| 4640 | {agent.title} | 4640 | {agent.title} |
| 4641 | </span> | 4641 | </span> |
| 4642 | {role ? ( | 4642 | {role ? ( |
| 4643 | <span className="max-w-28 shrink-0 truncate rounded-sm border border-border/60 px-1 font-mono text-[.65rem] text-muted-foreground"> | 4643 | <span className="max-w-28 shrink-0 truncate rounded-sm border border-border/60 px-1 font-mono text-3xs text-muted-foreground"> |
| 4644 | {role} | 4644 | {role} |
| 4645 | </span> | 4645 | </span> |
| 4646 | ) : null} | 4646 | ) : null} |
| 4647 | </p> | 4647 | </p> |
| 4648 | <span className="shrink-0 font-mono text-[.7rem] tabular-nums text-muted-foreground"> | 4648 | <span className="shrink-0 font-mono text-2xs tabular-nums text-muted-foreground"> |
| 4649 | {statusLabel} | 4649 | {statusLabel} |
| 4650 | </span> | 4650 | </span> |
| 4651 | </div> | 4651 | </div> |
| ... | @@ -4821,7 +4821,7 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { | ... | @@ -4821,7 +4821,7 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: { |
| 4821 | <ToolActivityIconView | 4821 | <ToolActivityIconView |
| 4822 | icon={entryToolIcon} | 4822 | icon={entryToolIcon} |
| 4823 | fallbackName={entryIconName} | 4823 | fallbackName={entryIconName} |
| 4824 | className="block size-4 shrink-0 stroke-[1.8]" | 4824 | className="block size-4 shrink-0 stroke-2" |
| 4825 | muted | 4825 | muted |
| 4826 | /> | 4826 | /> |
| 4827 | </span> | 4827 | </span> |
apps/web/src/components/chat/ModelListRow.tsx+1-1| ... | @@ -70,7 +70,7 @@ export const ModelListRow = memo(function ModelListRow(props: { | ... | @@ -70,7 +70,7 @@ export const ModelListRow = memo(function ModelListRow(props: { |
| 70 | </div> | 70 | </div> |
| 71 | {props.showNewBadge ? ( | 71 | {props.showNewBadge ? ( |
| 72 | <span | 72 | <span |
| 73 | className="shrink-0 rounded border border-update/35 bg-update/15 px-0.5 py-px text-[10px] font-bold uppercase leading-none tracking-wide text-update-foreground" | 73 | className="shrink-0 rounded border border-update/35 bg-update/15 px-0.5 py-px text-3xs font-bold uppercase leading-none tracking-wide text-update-foreground" |
| 74 | aria-label="New model" | 74 | aria-label="New model" |
| 75 | > | 75 | > |
| 76 | New | 76 | New |
apps/web/src/components/chat/ModelPickerSidebar.tsx+3-5| ... | @@ -123,7 +123,7 @@ export const ModelPickerSidebar = memo(function ModelPickerSidebar(props: { | ... | @@ -123,7 +123,7 @@ export const ModelPickerSidebar = memo(function ModelPickerSidebar(props: { |
| 123 | render={ | 123 | render={ |
| 124 | <Toolbar.Button | 124 | <Toolbar.Button |
| 125 | className={cn( | 125 | className={cn( |
| 126 | "relative isolate flex w-full cursor-pointer aspect-square items-center justify-center rounded-md transition-colors hover:bg-[color-mix(in_srgb,var(--popover)_90%,var(--contrast-foreground))] focus-visible:bg-[color-mix(in_srgb,var(--popover)_90%,var(--contrast-foreground))] focus-visible:outline-none", | 126 | "relative isolate flex w-full cursor-pointer aspect-square items-center justify-center rounded-md transition-colors hover:bg-foreground/10 focus-visible:bg-foreground/10 focus-visible:outline-none", |
| 127 | )} | 127 | )} |
| 128 | onClick={() => handleSelect("favorites")} | 128 | onClick={() => handleSelect("favorites")} |
| 129 | type="button" | 129 | type="button" |
| ... | @@ -171,7 +171,7 @@ export const ModelPickerSidebar = memo(function ModelPickerSidebar(props: { | ... | @@ -171,7 +171,7 @@ export const ModelPickerSidebar = memo(function ModelPickerSidebar(props: { |
| 171 | const button = ( | 171 | const button = ( |
| 172 | <Toolbar.Button | 172 | <Toolbar.Button |
| 173 | className={cn( | 173 | className={cn( |
| 174 | "relative isolate flex w-full cursor-pointer aspect-square items-center justify-center rounded-md transition-colors hover:bg-[color-mix(in_srgb,var(--popover)_90%,var(--contrast-foreground))] focus-visible:bg-[color-mix(in_srgb,var(--popover)_90%,var(--contrast-foreground))] focus-visible:outline-none", | 174 | "relative isolate flex w-full cursor-pointer aspect-square items-center justify-center rounded-md transition-colors hover:bg-foreground/10 focus-visible:bg-foreground/10 focus-visible:outline-none", |
| 175 | isDisabled && "opacity-50 cursor-not-allowed hover:bg-transparent", | 175 | isDisabled && "opacity-50 cursor-not-allowed hover:bg-transparent", |
| 176 | )} | 176 | )} |
| 177 | data-provider-accent-color={entry.accentColor} | 177 | data-provider-accent-color={entry.accentColor} |
| ... | @@ -210,9 +210,7 @@ export const ModelPickerSidebar = memo(function ModelPickerSidebar(props: { | ... | @@ -210,9 +210,7 @@ export const ModelPickerSidebar = memo(function ModelPickerSidebar(props: { |
| 210 | ? "var(--background)" | 210 | ? "var(--background)" |
| 211 | : "color-mix(in oklab, var(--muted) 30%, transparent)" | 211 | : "color-mix(in oklab, var(--muted) 30%, transparent)" |
| 212 | } | 212 | } |
| 213 | {...(entry.accentColor | 213 | {...(entry.accentColor ? { badgeClassName: "h-3 min-w-3 px-0.5 text-3xs" } : {})} |
| 214 | ? { badgeClassName: "h-3 min-w-3 px-0.5 text-[7px]" } | ||
| 215 | : {})} | ||
| 216 | /> | 214 | /> |
| 217 | {showNewBadge ? ( | 215 | {showNewBadge ? ( |
| 218 | <span className={NEW_BADGE_CLASS} aria-hidden> | 216 | <span className={NEW_BADGE_CLASS} aria-hidden> |
apps/web/src/components/chat/PanelLayoutControls.tsx+1-1| ... | @@ -78,7 +78,7 @@ export const PanelLayoutControls = memo(function PanelLayoutControls({ | ... | @@ -78,7 +78,7 @@ export const PanelLayoutControls = memo(function PanelLayoutControls({ |
| 78 | {liveAgentCount > 0 ? ( | 78 | {liveAgentCount > 0 ? ( |
| 79 | <span | 79 | <span |
| 80 | aria-hidden | 80 | aria-hidden |
| 81 | className="absolute -top-1 -right-1 flex h-3.5 min-w-3.5 items-center justify-center rounded-full bg-info px-1 text-[9px] font-semibold tabular-nums text-white" | 81 | className="absolute -top-1 -right-1 flex h-3.5 min-w-3.5 items-center justify-center rounded-full bg-info px-1 text-3xs font-semibold tabular-nums text-white" |
| 82 | > | 82 | > |
| 83 | {liveAgentCount} | 83 | {liveAgentCount} |
| 84 | </span> | 84 | </span> |
apps/web/src/components/chat/ProposedPlanCard.tsx+1-1| ... | @@ -146,7 +146,7 @@ export const ProposedPlanCard = memo(function ProposedPlanCard({ | ... | @@ -146,7 +146,7 @@ export const ProposedPlanCard = memo(function ProposedPlanCard({ |
| 146 | }; | 146 | }; |
| 147 | 147 | ||
| 148 | return ( | 148 | return ( |
| 149 | <div className="rounded-[24px] border border-border/80 bg-card/70 p-4 sm:p-5"> | 149 | <div className="rounded-3xl border border-border/80 bg-card/70 p-4 sm:p-5"> |
| 150 | <div className="flex flex-wrap items-center justify-between gap-3"> | 150 | <div className="flex flex-wrap items-center justify-between gap-3"> |
| 151 | <div className="flex min-w-0 items-center gap-2"> | 151 | <div className="flex min-w-0 items-center gap-2"> |
| 152 | <Badge variant="secondary">Plan</Badge> | 152 | <Badge variant="secondary">Plan</Badge> |
apps/web/src/components/chat/ProviderInstanceIcon.tsx+3-3| ... | @@ -38,7 +38,7 @@ export const ProviderInstanceIcon = memo(function ProviderInstanceIcon(props: { | ... | @@ -38,7 +38,7 @@ export const ProviderInstanceIcon = memo(function ProviderInstanceIcon(props: { |
| 38 | {Icon ? ( | 38 | {Icon ? ( |
| 39 | <Icon className={cn("size-5 shrink-0", props.iconClassName)} aria-hidden /> | 39 | <Icon className={cn("size-5 shrink-0", props.iconClassName)} aria-hidden /> |
| 40 | ) : ( | 40 | ) : ( |
| 41 | <span className={cn("text-[10px] font-semibold leading-none", props.iconClassName)}> | 41 | <span className={cn("text-3xs font-semibold leading-none", props.iconClassName)}> |
| 42 | {providerInstanceInitials(props.displayName)} | 42 | {providerInstanceInitials(props.displayName)} |
| 43 | </span> | 43 | </span> |
| 44 | )} | 44 | )} |
| ... | @@ -55,9 +55,9 @@ export const ProviderInstanceIcon = memo(function ProviderInstanceIcon(props: { | ... | @@ -55,9 +55,9 @@ export const ProviderInstanceIcon = memo(function ProviderInstanceIcon(props: { |
| 55 | {props.showBadge ? ( | 55 | {props.showBadge ? ( |
| 56 | <span | 56 | <span |
| 57 | className={cn( | 57 | className={cn( |
| 58 | "pointer-events-none absolute right-0 bottom-0 z-10 flex h-3.5 min-w-3.5 items-center justify-center rounded-full border px-0.5 text-[8px] font-semibold leading-none shadow-sm", | 58 | "pointer-events-none absolute right-0 bottom-0 z-10 flex h-3.5 min-w-3.5 items-center justify-center rounded-full border px-0.5 text-3xs font-semibold leading-none shadow-sm", |
| 59 | props.accentColor | 59 | props.accentColor |
| 60 | ? "bg-[var(--provider-accent)] text-white" | 60 | ? "bg-(--provider-accent) text-white" |
| 61 | : "bg-card text-muted-foreground", | 61 | : "bg-card text-muted-foreground", |
| 62 | props.badgeClassName, | 62 | props.badgeClassName, |
| 63 | )} | 63 | )} |
apps/web/src/components/chat/ProviderModelPicker.test.tsx+1-1| ... | @@ -174,6 +174,6 @@ describe("ProviderModelPicker", () => { | ... | @@ -174,6 +174,6 @@ describe("ProviderModelPicker", () => { |
| 174 | expect(markup).toContain(">CP</span>"); | 174 | expect(markup).toContain(">CP</span>"); |
| 175 | expect(markup).toContain("size-4"); | 175 | expect(markup).toContain("size-4"); |
| 176 | expect(markup).toContain("h-3"); | 176 | expect(markup).toContain("h-3"); |
| 177 | expect(markup).toContain("text-[7px]"); | 177 | expect(markup).toContain("text-3xs"); |
| 178 | }); | 178 | }); |
| 179 | }); | 179 | }); |
apps/web/src/components/chat/ProviderModelPicker.tsx+3-3| ... | @@ -229,13 +229,13 @@ export const ProviderModelPicker = memo(function ProviderModelPicker(props: { | ... | @@ -229,13 +229,13 @@ export const ProviderModelPicker = memo(function ProviderModelPicker(props: { |
| 229 | driverKind={selection.entry.driverKind} | 229 | driverKind={selection.entry.driverKind} |
| 230 | displayName={selection.entry.displayName} | 230 | displayName={selection.entry.displayName} |
| 231 | accentColor={selection.entry.accentColor} | 231 | accentColor={selection.entry.accentColor} |
| 232 | className="size-4 rounded-full bg-[var(--chat-composer-glass-surface,var(--background))] ring-2 ring-[var(--chat-composer-glass-surface,var(--background))]" | 232 | className="size-4 rounded-full bg-(--chat-composer-glass-surface,var(--background)) ring-2 ring-(--chat-composer-glass-surface,var(--background))" |
| 233 | iconClassName="size-4" | 233 | iconClassName="size-4" |
| 234 | /> | 234 | /> |
| 235 | ) : null, | 235 | ) : null, |
| 236 | )} | 236 | )} |
| 237 | {selectedEntries.length > 3 ? ( | 237 | {selectedEntries.length > 3 ? ( |
| 238 | <span className="relative z-30 flex size-4 items-center justify-center rounded-full bg-[var(--chat-composer-glass-surface,var(--background))] text-[9px] ring-2 ring-[var(--chat-composer-glass-surface,var(--background))]"> | 238 | <span className="relative z-30 flex size-4 items-center justify-center rounded-full bg-(--chat-composer-glass-surface,var(--background)) text-3xs ring-2 ring-(--chat-composer-glass-surface,var(--background))"> |
| 239 | +{selectedEntries.length - 3} | 239 | +{selectedEntries.length - 3} |
| 240 | </span> | 240 | </span> |
| 241 | ) : null} | 241 | ) : null} |
| ... | @@ -250,7 +250,7 @@ export const ProviderModelPicker = memo(function ProviderModelPicker(props: { | ... | @@ -250,7 +250,7 @@ export const ProviderModelPicker = memo(function ProviderModelPicker(props: { |
| 250 | iconClassName={cn("size-4", props.activeProviderIconClassName)} | 250 | iconClassName={cn("size-4", props.activeProviderIconClassName)} |
| 251 | indicatorBackground={props.instanceIndicatorBackground ?? "var(--contrast-input)"} | 251 | indicatorBackground={props.instanceIndicatorBackground ?? "var(--contrast-input)"} |
| 252 | badgeClassName={cn( | 252 | badgeClassName={cn( |
| 253 | "right-[-0.125rem] bottom-[-0.125rem] h-3 min-w-3 px-0.5 text-[7px]", | 253 | "right-[-0.125rem] bottom-[-0.125rem] h-3 min-w-3 px-0.5 text-3xs", |
| 254 | size === "xs" && "shadow-none", | 254 | size === "xs" && "shadow-none", |
| 255 | )} | 255 | )} |
| 256 | /> | 256 | /> |
apps/web/src/components/chat/SnapShotAttachmentDetails.tsx+4-4| ... | @@ -169,7 +169,7 @@ export function SnapShotContentsButton({ | ... | @@ -169,7 +169,7 @@ export function SnapShotContentsButton({ |
| 169 | {accessibilityDetails ? ( | 169 | {accessibilityDetails ? ( |
| 170 | <SnapShotAccessibilityData | 170 | <SnapShotAccessibilityData |
| 171 | details={accessibilityDetails} | 171 | details={accessibilityDetails} |
| 172 | className="max-h-64 rounded-md border border-border/70 bg-muted/45 p-2.5 text-[11px] leading-4" | 172 | className="max-h-64 rounded-md border border-border/70 bg-muted/45 p-2.5 text-2xs leading-4" |
| 173 | /> | 173 | /> |
| 174 | ) : includesAccessibility ? ( | 174 | ) : includesAccessibility ? ( |
| 175 | <div className="rounded-md border border-border/70 bg-muted/45 p-2.5 text-muted-foreground text-xs leading-4"> | 175 | <div className="rounded-md border border-border/70 bg-muted/45 p-2.5 text-muted-foreground text-xs leading-4"> |
| ... | @@ -204,16 +204,16 @@ export function SnapShotAttachmentDetails({ | ... | @@ -204,16 +204,16 @@ export function SnapShotAttachmentDetails({ |
| 204 | {source.appIconDataUrl ? ( | 204 | {source.appIconDataUrl ? ( |
| 205 | <img src={source.appIconDataUrl} alt="" className="size-7 shrink-0 rounded-md" /> | 205 | <img src={source.appIconDataUrl} alt="" className="size-7 shrink-0 rounded-md" /> |
| 206 | ) : ( | 206 | ) : ( |
| 207 | <div className="flex size-7 shrink-0 items-center justify-center rounded-md bg-white/20 text-[10px] font-medium text-white uppercase"> | 207 | <div className="flex size-7 shrink-0 items-center justify-center rounded-md bg-white/20 text-3xs font-medium text-white uppercase"> |
| 208 | {source.appName.slice(0, 1)} | 208 | {source.appName.slice(0, 1)} |
| 209 | </div> | 209 | </div> |
| 210 | )} | 210 | )} |
| 211 | <div className="min-w-0 flex-1"> | 211 | <div className="min-w-0 flex-1"> |
| 212 | <div className="flex min-w-0 items-center gap-1.5 text-[11px] font-medium leading-3.5 text-white"> | 212 | <div className="flex min-w-0 items-center gap-1.5 text-2xs font-medium leading-3.5 text-white"> |
| 213 | <span className="truncate">{source.appName}</span> | 213 | <span className="truncate">{source.appName}</span> |
| 214 | <SnapShotContentsButton source={source} className="pointer-events-auto" /> | 214 | <SnapShotContentsButton source={source} className="pointer-events-auto" /> |
| 215 | </div> | 215 | </div> |
| 216 | <div className="truncate text-[9px] leading-3.5 text-white/70"> | 216 | <div className="truncate text-3xs leading-3.5 text-white/70"> |
| 217 | {source.windowTitle || "Captured window"} | 217 | {source.windowTitle || "Captured window"} |
| 218 | </div> | 218 | </div> |
| 219 | </div> | 219 | </div> |
apps/web/src/components/chat/WorktreeSetupCard.tsx+2-2| ... | @@ -56,7 +56,7 @@ function useNowWhile(active: boolean): number { | ... | @@ -56,7 +56,7 @@ function useNowWhile(active: boolean): number { |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | function StageIcon({ status }: { status: WorktreeSetupStage["status"] }) { | 58 | function StageIcon({ status }: { status: WorktreeSetupStage["status"] }) { |
| 59 | const className = "size-4 shrink-0 stroke-[1.8]"; | 59 | const className = "size-4 shrink-0 stroke-2"; |
| 60 | switch (status) { | 60 | switch (status) { |
| 61 | case "done": | 61 | case "done": |
| 62 | return <CheckIcon aria-hidden className={className} />; | 62 | return <CheckIcon aria-hidden className={className} />; |
| ... | @@ -240,7 +240,7 @@ function OutputTail({ lines, failed }: { lines: ReadonlyArray<string>; failed: b | ... | @@ -240,7 +240,7 @@ function OutputTail({ lines, failed }: { lines: ReadonlyArray<string>; failed: b |
| 240 | return ( | 240 | return ( |
| 241 | <pre | 241 | <pre |
| 242 | className={cn( | 242 | className={cn( |
| 243 | "mb-1 ml-8 overflow-hidden rounded-md border px-2.5 py-1.5 font-mono text-[11px] leading-relaxed select-text", | 243 | "mb-1 ml-8 overflow-hidden rounded-md border px-2.5 py-1.5 font-mono text-2xs leading-relaxed select-text", |
| 244 | failed | 244 | failed |
| 245 | ? "border-destructive/20 bg-error-surface text-destructive-foreground" | 245 | ? "border-destructive/20 bg-error-surface text-destructive-foreground" |
| 246 | : "border-border bg-code text-muted-foreground", | 246 | : "border-border bg-code text-muted-foreground", |
apps/web/src/components/clerk/ClerkUserProfilePage.tsx+2-2| ... | @@ -22,9 +22,9 @@ export function ClerkUserProfilePage({ | ... | @@ -22,9 +22,9 @@ export function ClerkUserProfilePage({ |
| 22 | <div className={cn("w-full min-w-0 text-foreground", className)}> | 22 | <div className={cn("w-full min-w-0 text-foreground", className)}> |
| 23 | <header className="flex flex-col gap-3 pb-4 sm:flex-row sm:items-start sm:justify-between sm:gap-4 sm:pr-8"> | 23 | <header className="flex flex-col gap-3 pb-4 sm:flex-row sm:items-start sm:justify-between sm:gap-4 sm:pr-8"> |
| 24 | <div className="min-w-0"> | 24 | <div className="min-w-0"> |
| 25 | <h2 className="text-[1.0625rem] leading-6 font-semibold">{title}</h2> | 25 | <h2 className="text-base leading-6 font-semibold">{title}</h2> |
| 26 | {description ? ( | 26 | {description ? ( |
| 27 | <p className="mt-1 max-w-[34rem] text-[0.8125rem] leading-[1.125rem] text-muted-foreground sm:min-h-9"> | 27 | <p className="mt-1 max-w-[34rem] text-xs leading-4.5 text-muted-foreground sm:min-h-9"> |
| 28 | {description} | 28 | {description} |
| 29 | </p> | 29 | </p> |
| 30 | ) : null} | 30 | ) : null} |
apps/web/src/components/clerk/MobileClientsUserProfilePage.tsx+5-5| ... | @@ -38,14 +38,14 @@ function MobileClientRow({ device }: { readonly device: RelayClientDeviceRecord | ... | @@ -38,14 +38,14 @@ function MobileClientRow({ device }: { readonly device: RelayClientDeviceRecord |
| 38 | <ClerkUserProfileRow icon={<SmartphoneIcon className="size-4" />}> | 38 | <ClerkUserProfileRow icon={<SmartphoneIcon className="size-4" />}> |
| 39 | <div className="flex flex-col gap-0.5 sm:flex-row sm:items-start sm:justify-between sm:gap-3"> | 39 | <div className="flex flex-col gap-0.5 sm:flex-row sm:items-start sm:justify-between sm:gap-3"> |
| 40 | <div className="min-w-0"> | 40 | <div className="min-w-0"> |
| 41 | <h3 className="truncate text-[0.8125rem] leading-[1.125rem] font-medium text-foreground"> | 41 | <h3 className="truncate text-sm leading-4.5 font-medium text-foreground"> |
| 42 | {device.label} | 42 | {device.label} |
| 43 | </h3> | 43 | </h3> |
| 44 | <p className="text-xs leading-[1.125rem] text-muted-foreground"> | 44 | <p className="text-xs leading-4.5 text-muted-foreground"> |
| 45 | {mobileClientPlatformLabel(device)} | 45 | {mobileClientPlatformLabel(device)} |
| 46 | </p> | 46 | </p> |
| 47 | </div> | 47 | </div> |
| 48 | <p className="shrink-0 text-[0.6875rem] leading-4 text-muted-foreground/75"> | 48 | <p className="shrink-0 text-2xs leading-4 text-muted-foreground/75"> |
| 49 | {mobileClientUpdatedAtLabel(device.updatedAt)} | 49 | {mobileClientUpdatedAtLabel(device.updatedAt)} |
| 50 | </p> | 50 | </p> |
| 51 | </div> | 51 | </div> |
| ... | @@ -56,7 +56,7 @@ function MobileClientRow({ device }: { readonly device: RelayClientDeviceRecord | ... | @@ -56,7 +56,7 @@ function MobileClientRow({ device }: { readonly device: RelayClientDeviceRecord |
| 56 | /> | 56 | /> |
| 57 | <MobileClientStatusBadge enabled={device.liveActivities.enabled} label="Live Activities" /> | 57 | <MobileClientStatusBadge enabled={device.liveActivities.enabled} label="Live Activities" /> |
| 58 | </div> | 58 | </div> |
| 59 | <p className="mt-1.5 text-xs leading-[1.125rem] text-muted-foreground/80"> | 59 | <p className="mt-1.5 text-xs leading-4.5 text-muted-foreground/80"> |
| 60 | {mobileClientNotificationDetail(device)} | 60 | {mobileClientNotificationDetail(device)} |
| 61 | </p> | 61 | </p> |
| 62 | </ClerkUserProfileRow> | 62 | </ClerkUserProfileRow> |
| ... | @@ -123,7 +123,7 @@ export function MobileClientsUserProfilePage() { | ... | @@ -123,7 +123,7 @@ export function MobileClientsUserProfilePage() { |
| 123 | <div> | 123 | <div> |
| 124 | {devicesState.error ? ( | 124 | {devicesState.error ? ( |
| 125 | <div | 125 | <div |
| 126 | className="mb-4 flex flex-col gap-3 border-t border-destructive/35 py-3 text-[0.8125rem] sm:flex-row sm:items-center sm:justify-between" | 126 | className="mb-4 flex flex-col gap-3 border-t border-destructive/35 py-3 text-xs sm:flex-row sm:items-center sm:justify-between" |
| 127 | role="alert" | 127 | role="alert" |
| 128 | > | 128 | > |
| 129 | <div> | 129 | <div> |
apps/web/src/components/clerk/T3ConnectUserProfilePage.tsx+7-7| ... | @@ -51,10 +51,10 @@ export function T3ConnectEnvironmentRow(props: { | ... | @@ -51,10 +51,10 @@ export function T3ConnectEnvironmentRow(props: { |
| 51 | <Collapsible open={props.confirmationOpen} onOpenChange={props.onConfirmationChange}> | 51 | <Collapsible open={props.confirmationOpen} onOpenChange={props.onConfirmationChange}> |
| 52 | <div className="flex items-start gap-4"> | 52 | <div className="flex items-start gap-4"> |
| 53 | <div className="min-w-0 flex-1"> | 53 | <div className="min-w-0 flex-1"> |
| 54 | <h3 className="truncate text-[0.8125rem] leading-[1.125rem] font-medium text-foreground"> | 54 | <h3 className="truncate text-sm leading-4.5 font-medium text-foreground"> |
| 55 | {environment.label} | 55 | {environment.label} |
| 56 | </h3> | 56 | </h3> |
| 57 | <p className="mt-1 text-xs leading-[1.125rem] text-muted-foreground"> | 57 | <p className="mt-1 text-xs leading-4.5 text-muted-foreground"> |
| 58 | {linkedAtLabel(environment.linkedAt)} · {endpointLabel(environment)} | 58 | {linkedAtLabel(environment.linkedAt)} · {endpointLabel(environment)} |
| 59 | </p> | 59 | </p> |
| 60 | </div> | 60 | </div> |
| ... | @@ -74,13 +74,13 @@ export function T3ConnectEnvironmentRow(props: { | ... | @@ -74,13 +74,13 @@ export function T3ConnectEnvironmentRow(props: { |
| 74 | role="group" | 74 | role="group" |
| 75 | aria-label={`Confirm deregistration of ${environment.label}`} | 75 | aria-label={`Confirm deregistration of ${environment.label}`} |
| 76 | > | 76 | > |
| 77 | <h4 className="text-[0.8125rem] leading-[1.125rem] font-semibold text-foreground"> | 77 | <h4 className="text-sm leading-4.5 font-semibold text-foreground"> |
| 78 | Deregister server | 78 | Deregister server |
| 79 | </h4> | 79 | </h4> |
| 80 | <p className="mt-1 text-[0.8125rem] leading-[1.125rem] text-muted-foreground"> | 80 | <p className="mt-1 text-xs leading-4.5 text-muted-foreground"> |
| 81 | “{environment.label}” will be removed from this account. | 81 | “{environment.label}” will be removed from this account. |
| 82 | </p> | 82 | </p> |
| 83 | <p className="mt-4 max-w-xl text-[0.8125rem] leading-[1.125rem] text-muted-foreground"> | 83 | <p className="mt-4 max-w-xl text-xs leading-4.5 text-muted-foreground"> |
| 84 | T3 Connect access will be revoked, any managed tunnel will be removed, and a host | 84 | T3 Connect access will be revoked, any managed tunnel will be removed, and a host |
| 85 | space will become available. Local connections on your devices are not changed. | 85 | space will become available. Local connections on your devices are not changed. |
| 86 | </p> | 86 | </p> |
| ... | @@ -205,7 +205,7 @@ export function T3ConnectUserProfilePage() { | ... | @@ -205,7 +205,7 @@ export function T3ConnectUserProfilePage() { |
| 205 | > | 205 | > |
| 206 | <div> | 206 | <div> |
| 207 | {environmentsState.error ? ( | 207 | {environmentsState.error ? ( |
| 208 | <div className="mb-4 border-t border-destructive/35 py-3 text-[0.8125rem]" role="alert"> | 208 | <div className="mb-4 border-t border-destructive/35 py-3 text-xs" role="alert"> |
| 209 | <p className="font-medium text-destructive-foreground"> | 209 | <p className="font-medium text-destructive-foreground"> |
| 210 | Could not load T3 Connect environments | 210 | Could not load T3 Connect environments |
| 211 | </p> | 211 | </p> |
| ... | @@ -214,7 +214,7 @@ export function T3ConnectUserProfilePage() { | ... | @@ -214,7 +214,7 @@ export function T3ConnectUserProfilePage() { |
| 214 | ) : null} | 214 | ) : null} |
| 215 | 215 | ||
| 216 | {isInitialLoad ? ( | 216 | {isInitialLoad ? ( |
| 217 | <p className="border-t py-4 text-[0.8125rem] text-muted-foreground" role="status"> | 217 | <p className="border-t py-4 text-xs text-muted-foreground" role="status"> |
| 218 | Loading environments… | 218 | Loading environments… |
| 219 | </p> | 219 | </p> |
| 220 | ) : environments.length > 0 ? ( | 220 | ) : environments.length > 0 ? ( |
apps/web/src/components/cloud/ConnectCliAuthSurface.tsx+1-3| ... | @@ -23,9 +23,7 @@ function ConnectCliAuthMessage({ | ... | @@ -23,9 +23,7 @@ function ConnectCliAuthMessage({ |
| 23 | return ( | 23 | return ( |
| 24 | <> | 24 | <> |
| 25 | {eyebrow ? ( | 25 | {eyebrow ? ( |
| 26 | <p className="text-[10px] font-semibold tracking-[0.18em] text-primary uppercase"> | 26 | <p className="text-3xs font-semibold tracking-widest text-primary uppercase">{eyebrow}</p> |
| 27 | {eyebrow} | ||
| 28 | </p> | ||
| 29 | ) : null} | 27 | ) : null} |
| 30 | <h1 className="mt-2 text-2xl font-semibold tracking-tight sm:text-3xl">{title}</h1> | 28 | <h1 className="mt-2 text-2xl font-semibold tracking-tight sm:text-3xl">{title}</h1> |
| 31 | <p className="mt-2 text-sm leading-relaxed text-muted-foreground">{description}</p> | 29 | <p className="mt-2 text-sm leading-relaxed text-muted-foreground">{description}</p> |
apps/web/src/components/composerContextPresentation.tsx+1-1| ... | @@ -269,7 +269,7 @@ function ComposerReviewCommentDetails({ comment }: { comment: ReviewCommentConte | ... | @@ -269,7 +269,7 @@ function ComposerReviewCommentDetails({ comment }: { comment: ReviewCommentConte |
| 269 | <div className="space-y-2 overflow-hidden rounded-lg border border-border/70 bg-background/70 p-3"> | 269 | <div className="space-y-2 overflow-hidden rounded-lg border border-border/70 bg-background/70 p-3"> |
| 270 | <div className="space-y-1"> | 270 | <div className="space-y-1"> |
| 271 | <div className="truncate text-xs font-medium text-foreground">{comment.filePath}</div> | 271 | <div className="truncate text-xs font-medium text-foreground">{comment.filePath}</div> |
| 272 | <div className="text-secondary-label text-[11px]"> | 272 | <div className="text-secondary-label text-2xs"> |
| 273 | {comment.sectionTitle} · {comment.rangeLabel} | 273 | {comment.sectionTitle} · {comment.rangeLabel} |
| 274 | </div> | 274 | </div> |
| 275 | </div> | 275 | </div> |
apps/web/src/components/contextChipParts.tsx+4-4| ... | @@ -208,8 +208,8 @@ export function ImageChipButton({ | ... | @@ -208,8 +208,8 @@ export function ImageChipButton({ |
| 208 | <ImageIcon /> | 208 | <ImageIcon /> |
| 209 | )} | 209 | )} |
| 210 | <ContextChipLabel className="max-w-72">{middleTruncateAttachmentName(name)}</ContextChipLabel> | 210 | <ContextChipLabel className="max-w-72">{middleTruncateAttachmentName(name)}</ContextChipLabel> |
| 211 | <span className="shrink-0 text-[10px] text-current">{size}</span> | 211 | <span className="shrink-0 text-3xs text-current">{size}</span> |
| 212 | {suffix ? <span className="text-[10px] text-current">{suffix}</span> : null} | 212 | {suffix ? <span className="text-3xs text-current">{suffix}</span> : null} |
| 213 | </ContextChip> | 213 | </ContextChip> |
| 214 | ); | 214 | ); |
| 215 | } | 215 | } |
| ... | @@ -284,8 +284,8 @@ function FileChipContent(props: { | ... | @@ -284,8 +284,8 @@ function FileChipContent(props: { |
| 284 | <ContextChipLabel className="max-w-72"> | 284 | <ContextChipLabel className="max-w-72"> |
| 285 | {middleTruncateAttachmentName(props.name)} | 285 | {middleTruncateAttachmentName(props.name)} |
| 286 | </ContextChipLabel> | 286 | </ContextChipLabel> |
| 287 | <span className="shrink-0 text-[10px] text-current">{props.size}</span> | 287 | <span className="shrink-0 text-3xs text-current">{props.size}</span> |
| 288 | {props.suffix ? <span className="text-[10px] text-current">{props.suffix}</span> : null} | 288 | {props.suffix ? <span className="text-3xs text-current">{props.suffix}</span> : null} |
| 289 | </> | 289 | </> |
| 290 | ); | 290 | ); |
| 291 | } | 291 | } |
apps/web/src/components/device/DeviceStreamView.tsx+1-1| ... | @@ -404,7 +404,7 @@ export function DeviceStreamView(props: { | ... | @@ -404,7 +404,7 @@ export function DeviceStreamView(props: { |
| 404 | }} | 404 | }} |
| 405 | > | 405 | > |
| 406 | {element.label ? ( | 406 | {element.label ? ( |
| 407 | <span className="absolute -top-3.5 left-0 max-w-full truncate rounded-sm bg-info px-1 text-[9px] leading-3.5 text-white"> | 407 | <span className="absolute -top-3.5 left-0 max-w-full truncate rounded-sm bg-info px-1 text-3xs leading-3.5 text-white"> |
| 408 | {element.label} | 408 | {element.label} |
| 409 | </span> | 409 | </span> |
| 410 | ) : null} | 410 | ) : null} |
apps/web/src/components/device/DeviceToolsPanel.tsx+1-1| ... | @@ -640,7 +640,7 @@ function EventLogSection(props: { | ... | @@ -640,7 +640,7 @@ function EventLogSection(props: { |
| 640 | /> | 640 | /> |
| 641 | </CollapsibleTrigger> | 641 | </CollapsibleTrigger> |
| 642 | <CollapsiblePanel> | 642 | <CollapsiblePanel> |
| 643 | <ol className="max-h-64 overflow-y-auto px-3 py-2 font-mono text-[11px] leading-relaxed"> | 643 | <ol className="max-h-64 overflow-y-auto px-3 py-2 font-mono text-2xs leading-relaxed"> |
| 644 | {entries.length === 0 ? ( | 644 | {entries.length === 0 ? ( |
| 645 | <li className="text-muted-foreground">No events yet.</li> | 645 | <li className="text-muted-foreground">No events yet.</li> |
| 646 | ) : ( | 646 | ) : ( |
apps/web/src/components/diffs/DiffCommentAnnotation.tsx+2-2| ... | @@ -65,7 +65,7 @@ export function DiffCommentAnnotation({ | ... | @@ -65,7 +65,7 @@ export function DiffCommentAnnotation({ |
| 65 | onPointerDown={(event) => event.stopPropagation()} | 65 | onPointerDown={(event) => event.stopPropagation()} |
| 66 | > | 66 | > |
| 67 | <MessageCircle className="mt-0.5 size-3.5 shrink-0 text-primary/70" aria-hidden="true" /> | 67 | <MessageCircle className="mt-0.5 size-3.5 shrink-0 text-primary/70" aria-hidden="true" /> |
| 68 | <p className="min-w-0 flex-1 whitespace-pre-wrap text-[13px] leading-5">{displayedText}</p> | 68 | <p className="min-w-0 flex-1 whitespace-pre-wrap text-sm leading-5">{displayedText}</p> |
| 69 | {onDelete ? ( | 69 | {onDelete ? ( |
| 70 | <span className="-my-1 -mr-1 flex shrink-0 opacity-0 transition-opacity group-hover/comment:opacity-100 focus-within:opacity-100 max-sm:opacity-100"> | 70 | <span className="-my-1 -mr-1 flex shrink-0 opacity-0 transition-opacity group-hover/comment:opacity-100 focus-within:opacity-100 max-sm:opacity-100"> |
| 71 | <Button | 71 | <Button |
| ... | @@ -113,7 +113,7 @@ export function DiffCommentAnnotation({ | ... | @@ -113,7 +113,7 @@ export function DiffCommentAnnotation({ |
| 113 | }} | 113 | }} |
| 114 | /> | 114 | /> |
| 115 | <div className="mt-1.5 flex items-center gap-1"> | 115 | <div className="mt-1.5 flex items-center gap-1"> |
| 116 | <span className="mr-auto text-[10px] text-muted-foreground/70">⌘/Ctrl Enter to send</span> | 116 | <span className="mr-auto text-3xs text-muted-foreground/70">⌘/Ctrl Enter to send</span> |
| 117 | <Button variant="ghost-muted" size="xs" onClick={onCancel}> | 117 | <Button variant="ghost-muted" size="xs" onClick={onCancel}> |
| 118 | Cancel | 118 | Cancel |
| 119 | </Button> | 119 | </Button> |
apps/web/src/components/files/FilePreviewPanel.tsx+1-1| ... | @@ -1172,7 +1172,7 @@ export default function FilePreviewPanel({ | ... | @@ -1172,7 +1172,7 @@ export default function FilePreviewPanel({ |
| 1172 | !isMedia && | 1172 | !isMedia && |
| 1173 | !renderBrowserFile && | 1173 | !renderBrowserFile && |
| 1174 | file.data?.truncated ? ( | 1174 | file.data?.truncated ? ( |
| 1175 | <div className="shrink-0 border-b border-warning/20 bg-warning-surface px-3 py-1.5 text-[11px] text-warning-foreground"> | 1175 | <div className="shrink-0 border-b border-warning/20 bg-warning-surface px-3 py-1.5 text-2xs text-warning-foreground"> |
| 1176 | Preview limited to the first 1 MB of a {file.data.byteLength.toLocaleString()} byte file. | 1176 | Preview limited to the first 1 MB of a {file.data.byteLength.toLocaleString()} byte file. |
| 1177 | </div> | 1177 | </div> |
| 1178 | ) : null} | 1178 | ) : null} |
apps/web/src/components/files/fileSurfaceChrome.tsx+1-1| ... | @@ -114,7 +114,7 @@ export function FileSurfaceNotice(props: { readonly children: ReactNode }) { | ... | @@ -114,7 +114,7 @@ export function FileSurfaceNotice(props: { readonly children: ReactNode }) { |
| 114 | return ( | 114 | return ( |
| 115 | <div | 115 | <div |
| 116 | role="status" | 116 | role="status" |
| 117 | className="shrink-0 border-b border-warning/20 bg-warning-surface px-3 py-1.5 text-[11px] text-warning-foreground" | 117 | className="shrink-0 border-b border-warning/20 bg-warning-surface px-3 py-1.5 text-2xs text-warning-foreground" |
| 118 | > | 118 | > |
| 119 | {props.children} | 119 | {props.children} |
| 120 | </div> | 120 | </div> |
apps/web/src/components/onboarding/WelcomeWizard.tsx+3-5| ... | @@ -193,7 +193,7 @@ export function WelcomeWizard({ | ... | @@ -193,7 +193,7 @@ export function WelcomeWizard({ |
| 193 | identity={ | 193 | identity={ |
| 194 | <div className="flex items-baseline gap-1.5" role="img" aria-label="T3 Code"> | 194 | <div className="flex items-baseline gap-1.5" role="img" aria-label="T3 Code"> |
| 195 | <T3Wordmark className="h-4 w-auto shrink-0" aria-hidden /> | 195 | <T3Wordmark className="h-4 w-auto shrink-0" aria-hidden /> |
| 196 | <span className="text-[1.4rem] font-medium tracking-tight text-muted-foreground"> | 196 | <span className="text-2xl font-medium tracking-tight text-muted-foreground"> |
| 197 | Code | 197 | Code |
| 198 | </span> | 198 | </span> |
| 199 | </div> | 199 | </div> |
| ... | @@ -892,7 +892,7 @@ function AgentInstallTerminal({ | ... | @@ -892,7 +892,7 @@ function AgentInstallTerminal({ |
| 892 | className="mt-4 overflow-hidden rounded-lg border border-border/70 bg-background text-foreground" | 892 | className="mt-4 overflow-hidden rounded-lg border border-border/70 bg-background text-foreground" |
| 893 | > | 893 | > |
| 894 | <div className="flex items-center justify-between border-b border-border/60 bg-background/60 px-3 py-1.5"> | 894 | <div className="flex items-center justify-between border-b border-border/60 bg-background/60 px-3 py-1.5"> |
| 895 | <span className="text-[11px] font-medium text-muted-foreground"> | 895 | <span className="text-2xs font-medium text-muted-foreground"> |
| 896 | {setupState === "writeFailed" ? ( | 896 | {setupState === "writeFailed" ? ( |
| 897 | <> | 897 | <> |
| 898 | Run <code className="rounded bg-muted px-1 font-mono">{command}</code> in this | 898 | Run <code className="rounded bg-muted px-1 font-mono">{command}</code> in this |
| ... | @@ -1445,9 +1445,7 @@ function ImportCandidateRow({ | ... | @@ -1445,9 +1445,7 @@ function ImportCandidateRow({ |
| 1445 | {label} | 1445 | {label} |
| 1446 | </span> | 1446 | </span> |
| 1447 | {secondary !== undefined ? ( | 1447 | {secondary !== undefined ? ( |
| 1448 | <span className="truncate font-mono text-[11px] text-muted-foreground"> | 1448 | <span className="truncate font-mono text-2xs text-muted-foreground">{secondary}</span> |
| 1449 | {secondary} | ||
| 1450 | </span> | ||
| 1451 | ) : null} | 1449 | ) : null} |
| 1452 | </TooltipTrigger> | 1450 | </TooltipTrigger> |
| 1453 | <TooltipPopup variant="code">{candidate.path}</TooltipPopup> | 1451 | <TooltipPopup variant="code">{candidate.path}</TooltipPopup> |
apps/web/src/components/preview/AgentBrowserCursor.tsx+1-1| ... | @@ -55,7 +55,7 @@ function AgentBrowserCursorEvent(props: { | ... | @@ -55,7 +55,7 @@ function AgentBrowserCursorEvent(props: { |
| 55 | 55 | ||
| 56 | return ( | 56 | return ( |
| 57 | <div | 57 | <div |
| 58 | className="pointer-events-none absolute left-0 top-0 z-40 transition-[transform,opacity] duration-150 ease-out motion-reduce:transition-none" | 58 | className="pointer-events-none absolute left-0 top-0 z-40 transition-[opacity,transform] duration-150 ease-out motion-reduce:transition-none" |
| 59 | style={{ | 59 | style={{ |
| 60 | opacity: agentBrowserCursorOpacity(active, controller), | 60 | opacity: agentBrowserCursorOpacity(active, controller), |
| 61 | transform: `translate3d(${event.x * zoomFactor * (content?.scale ?? 1) + (content?.x ?? 0) - (content?.scrollLeft ?? 0)}px, ${event.y * zoomFactor * (content?.scale ?? 1) + (content?.y ?? 0) - (content?.scrollTop ?? 0)}px, 0)`, | 61 | transform: `translate3d(${event.x * zoomFactor * (content?.scale ?? 1) + (content?.x ?? 0) - (content?.scrollLeft ?? 0)}px, ${event.y * zoomFactor * (content?.scale ?? 1) + (content?.y ?? 0) - (content?.scrollTop ?? 0)}px, 0)`, |
apps/web/src/components/preview/BrowserMockup.tsx+3-3| ... | @@ -6,16 +6,16 @@ export function BrowserMockup({ className }: { className?: string }) { | ... | @@ -6,16 +6,16 @@ export function BrowserMockup({ className }: { className?: string }) { |
| 6 | <div | 6 | <div |
| 7 | aria-hidden | 7 | aria-hidden |
| 8 | className={cn( | 8 | className={cn( |
| 9 | "relative flex flex-col gap-0.5 overflow-hidden rounded-[5px] border border-border/60 bg-card p-1 shadow-xs/5", | 9 | "relative flex flex-col gap-0.5 overflow-hidden rounded-sm border border-border/60 bg-card p-1 shadow-xs/5", |
| 10 | className, | 10 | className, |
| 11 | )} | 11 | )} |
| 12 | > | 12 | > |
| 13 | <div className="flex gap-[2px]"> | 13 | <div className="flex gap-0.5"> |
| 14 | <span className="size-[3px] rounded-full bg-destructive/80" /> | 14 | <span className="size-[3px] rounded-full bg-destructive/80" /> |
| 15 | <span className="size-[3px] rounded-full bg-warning/80" /> | 15 | <span className="size-[3px] rounded-full bg-warning/80" /> |
| 16 | <span className="size-[3px] rounded-full bg-success/80" /> | 16 | <span className="size-[3px] rounded-full bg-success/80" /> |
| 17 | </div> | 17 | </div> |
| 18 | <div className="mt-[1px] flex flex-1 flex-col gap-[2px]"> | 18 | <div className="mt-[1px] flex flex-1 flex-col gap-0.5"> |
| 19 | <span className="h-[2px] w-full rounded-full bg-muted-foreground/30" /> | 19 | <span className="h-[2px] w-full rounded-full bg-muted-foreground/30" /> |
| 20 | <span className="h-[2px] w-3/5 rounded-full bg-muted-foreground/20" /> | 20 | <span className="h-[2px] w-3/5 rounded-full bg-muted-foreground/20" /> |
| 21 | </div> | 21 | </div> |
apps/web/src/components/preview/PreviewPanelShell.tsx+1-1| ... | @@ -126,7 +126,7 @@ export function PreviewPanelShell(props: { | ... | @@ -126,7 +126,7 @@ export function PreviewPanelShell(props: { |
| 126 | : "shrink-0 border-l border-border" | 126 | : "shrink-0 border-l border-border" |
| 127 | : "w-full", | 127 | : "w-full", |
| 128 | collapsible && | 128 | collapsible && |
| 129 | "[[data-panel-animations=true]_&]:transition-[width] [[data-panel-animations=true]_&]:[transition-duration:var(--panel-animation-duration)] [[data-panel-animations=true]_&]:ease-out", | 129 | "[[data-panel-animations=true]_&]:transition-[width] [[data-panel-animations=true]_&]:duration-(--panel-animation-duration) [[data-panel-animations=true]_&]:ease-out", |
| 130 | collapsible && open && "[[data-panel-animations=true]_&]:starting:w-0!", | 130 | collapsible && open && "[[data-panel-animations=true]_&]:starting:w-0!", |
| 131 | collapsible && !open && "pointer-events-none", | 131 | collapsible && !open && "pointer-events-none", |
| 132 | )} | 132 | )} |
apps/web/src/components/pullRequest/PullRequestCodeTab.tsx+2-2| ... | @@ -828,7 +828,7 @@ function PullRequestCodeTab({ | ... | @@ -828,7 +828,7 @@ function PullRequestCodeTab({ |
| 828 | <PullRequestDiffStat | 828 | <PullRequestDiffStat |
| 829 | additions={additions} | 829 | additions={additions} |
| 830 | deletions={deletions} | 830 | deletions={deletions} |
| 831 | className="font-mono text-[11px]" | 831 | className="font-mono text-2xs" |
| 832 | /> | 832 | /> |
| 833 | ); | 833 | ); |
| 834 | const viewedFiles = filesViewedRef.current; | 834 | const viewedFiles = filesViewedRef.current; |
| ... | @@ -842,7 +842,7 @@ function PullRequestCodeTab({ | ... | @@ -842,7 +842,7 @@ function PullRequestCodeTab({ |
| 842 | attribute is what the header's capture listener looks for. */} | 842 | attribute is what the header's capture listener looks for. */} |
| 843 | <label | 843 | <label |
| 844 | data-viewed-toggle="" | 844 | data-viewed-toggle="" |
| 845 | className="flex cursor-pointer select-none items-center gap-1.5 text-[11px] text-muted-foreground" | 845 | className="flex cursor-pointer select-none items-center gap-1.5 text-2xs text-muted-foreground" |
| 846 | onClick={(event) => event.stopPropagation()} | 846 | onClick={(event) => event.stopPropagation()} |
| 847 | > | 847 | > |
| 848 | <Checkbox | 848 | <Checkbox |
apps/web/src/components/pullRequest/PullRequestComposer.tsx+1-1| ... | @@ -93,7 +93,7 @@ export function PullRequestComposer({ | ... | @@ -93,7 +93,7 @@ export function PullRequestComposer({ |
| 93 | {pendingComments.length > 0 ? ( | 93 | {pendingComments.length > 0 ? ( |
| 94 | <span | 94 | <span |
| 95 | aria-hidden | 95 | aria-hidden |
| 96 | className="absolute -top-1 -right-1 flex h-3.5 min-w-3.5 items-center justify-center rounded-full bg-info px-1 text-[9px] font-semibold tabular-nums text-white" | 96 | className="absolute -top-1 -right-1 flex h-3.5 min-w-3.5 items-center justify-center rounded-full bg-info px-1 text-3xs font-semibold tabular-nums text-white" |
| 97 | > | 97 | > |
| 98 | {pendingComments.length} | 98 | {pendingComments.length} |
| 99 | </span> | 99 | </span> |
apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx+4-4| ... | @@ -2260,7 +2260,7 @@ export function PullRequestDetailPanel({ | ... | @@ -2260,7 +2260,7 @@ export function PullRequestDetailPanel({ |
| 2260 | <span className="shrink-0">{formatRelativeTimeLabel(detail.updatedAt)}</span> | 2260 | <span className="shrink-0">{formatRelativeTimeLabel(detail.updatedAt)}</span> |
| 2261 | </span> | 2261 | </span> |
| 2262 | <span aria-hidden className="h-3 w-px shrink-0 bg-border/70" /> | 2262 | <span aria-hidden className="h-3 w-px shrink-0 bg-border/70" /> |
| 2263 | <span className="flex min-w-0 flex-1 items-center gap-1.5 font-mono text-[11px] text-muted-foreground/65"> | 2263 | <span className="flex min-w-0 flex-1 items-center gap-1.5 font-mono text-2xs text-muted-foreground/65"> |
| 2264 | {/* An out-of-date base wears the warning on the branch name itself, so the | 2264 | {/* An out-of-date base wears the warning on the branch name itself, so the |
| 2265 | name is amber and pointing at either the name or the mark opens the way | 2265 | name is amber and pointing at either the name or the mark opens the way |
| 2266 | out. Up to date, the name keeps its plain tooltip. */} | 2266 | out. Up to date, the name keeps its plain tooltip. */} |
| ... | @@ -2322,7 +2322,7 @@ export function PullRequestDetailPanel({ | ... | @@ -2322,7 +2322,7 @@ export function PullRequestDetailPanel({ |
| 2322 | <TooltipPopup side="top">{detail.headBranch}</TooltipPopup> | 2322 | <TooltipPopup side="top">{detail.headBranch}</TooltipPopup> |
| 2323 | </Tooltip> | 2323 | </Tooltip> |
| 2324 | </span> | 2324 | </span> |
| 2325 | <span className="ml-auto inline-flex shrink-0 items-center justify-end gap-2 text-[11px]"> | 2325 | <span className="ml-auto inline-flex shrink-0 items-center justify-end gap-2 text-2xs"> |
| 2326 | <span | 2326 | <span |
| 2327 | className="inline-flex items-center gap-1 tabular-nums" | 2327 | className="inline-flex items-center gap-1 tabular-nums" |
| 2328 | aria-label={`${detail.changedFiles.toLocaleString()} changed ${ | 2328 | aria-label={`${detail.changedFiles.toLocaleString()} changed ${ |
| ... | @@ -2335,7 +2335,7 @@ export function PullRequestDetailPanel({ | ... | @@ -2335,7 +2335,7 @@ export function PullRequestDetailPanel({ |
| 2335 | <PullRequestDiffStat | 2335 | <PullRequestDiffStat |
| 2336 | additions={detail.additions} | 2336 | additions={detail.additions} |
| 2337 | deletions={detail.deletions} | 2337 | deletions={detail.deletions} |
| 2338 | className="shrink-0 font-mono text-[11px]" | 2338 | className="shrink-0 font-mono text-2xs" |
| 2339 | /> | 2339 | /> |
| 2340 | </span> | 2340 | </span> |
| 2341 | </div> | 2341 | </div> |
| ... | @@ -2609,7 +2609,7 @@ export function PullRequestDetailPanel({ | ... | @@ -2609,7 +2609,7 @@ export function PullRequestDetailPanel({ |
| 2609 | <div className="ml-auto flex shrink-0 items-center gap-2 text-xs text-muted-foreground"> | 2609 | <div className="ml-auto flex shrink-0 items-center gap-2 text-xs text-muted-foreground"> |
| 2610 | <PullRequestMetaLine | 2610 | <PullRequestMetaLine |
| 2611 | className={cn( | 2611 | className={cn( |
| 2612 | "whitespace-nowrap text-[11px] transition-opacity", | 2612 | "whitespace-nowrap text-2xs transition-opacity", |
| 2613 | (activityPending || activityError) && "opacity-35", | 2613 | (activityPending || activityError) && "opacity-35", |
| 2614 | )} | 2614 | )} |
| 2615 | > | 2615 | > |
apps/web/src/components/pullRequest/PullRequestLinkPreview.tsx+1-1| ... | @@ -106,7 +106,7 @@ export function PullRequestLinkPreview({ | ... | @@ -106,7 +106,7 @@ export function PullRequestLinkPreview({ |
| 106 | )) | 106 | )) |
| 107 | ) : ( | 107 | ) : ( |
| 108 | <div className="min-w-0"> | 108 | <div className="min-w-0"> |
| 109 | <div className="flex min-w-0 items-center gap-1.5 text-[11px] text-muted-foreground"> | 109 | <div className="flex min-w-0 items-center gap-1.5 text-2xs text-muted-foreground"> |
| 110 | <span className="min-w-0 truncate">{detail.repository}</span> | 110 | <span className="min-w-0 truncate">{detail.repository}</span> |
| 111 | <span className="shrink-0">#{detail.number}</span> | 111 | <span className="shrink-0">#{detail.number}</span> |
| 112 | <span aria-hidden>·</span> | 112 | <span aria-hidden>·</span> |
apps/web/src/components/pullRequest/PullRequestListRow.tsx+4-4| ... | @@ -68,7 +68,7 @@ export function PullRequestRowGlyph({ | ... | @@ -68,7 +68,7 @@ export function PullRequestRowGlyph({ |
| 68 | /> | 68 | /> |
| 69 | </span> | 69 | </span> |
| 70 | </span> | 70 | </span> |
| 71 | {below ? <span className="inline-flex text-[11px]">{below}</span> : null} | 71 | {below ? <span className="inline-flex text-2xs">{below}</span> : null} |
| 72 | </span> | 72 | </span> |
| 73 | ); | 73 | ); |
| 74 | } | 74 | } |
| ... | @@ -100,15 +100,15 @@ export function PullRequestRowLines({ | ... | @@ -100,15 +100,15 @@ export function PullRequestRowLines({ |
| 100 | {number} | 100 | {number} |
| 101 | <span className="min-w-0 truncate text-sm">{title}</span> | 101 | <span className="min-w-0 truncate text-sm">{title}</span> |
| 102 | {signals ? ( | 102 | {signals ? ( |
| 103 | <span className="flex shrink-0 items-center gap-1 text-[11px]">{signals}</span> | 103 | <span className="flex shrink-0 items-center gap-1 text-2xs">{signals}</span> |
| 104 | ) : null} | 104 | ) : null} |
| 105 | {status ? ( | 105 | {status ? ( |
| 106 | <span className="ml-auto flex shrink-0 items-center gap-1.5 text-[11px]">{status}</span> | 106 | <span className="ml-auto flex shrink-0 items-center gap-1.5 text-2xs">{status}</span> |
| 107 | ) : null} | 107 | ) : null} |
| 108 | </span> | 108 | </span> |
| 109 | <span | 109 | <span |
| 110 | className={cn( | 110 | className={cn( |
| 111 | "flex min-w-0 items-center gap-1.5 overflow-hidden text-[11px] text-muted-foreground", | 111 | "flex min-w-0 items-center gap-1.5 overflow-hidden text-2xs text-muted-foreground", |
| 112 | metaClassName, | 112 | metaClassName, |
| 113 | )} | 113 | )} |
| 114 | > | 114 | > |
apps/web/src/components/pullRequest/PullRequestRow.tsx+1-1| ... | @@ -204,7 +204,7 @@ function PullRequestRowImpl({ | ... | @@ -204,7 +204,7 @@ function PullRequestRowImpl({ |
| 204 | <Tooltip> | 204 | <Tooltip> |
| 205 | <TooltipTrigger | 205 | <TooltipTrigger |
| 206 | render={ | 206 | render={ |
| 207 | <span className="flex min-w-6 items-center gap-1 overflow-hidden rounded-full border border-border/60 px-1 text-[10px]" /> | 207 | <span className="flex min-w-6 items-center gap-1 overflow-hidden rounded-full border border-border/60 px-1 text-3xs" /> |
| 208 | } | 208 | } |
| 209 | > | 209 | > |
| 210 | <span className="sr-only">matched in the description</span> | 210 | <span className="sr-only">matched in the description</span> |
apps/web/src/components/pullRequest/PullRequestSummaryTab.tsx+2-2| ... | @@ -401,7 +401,7 @@ function CommentGroup({ | ... | @@ -401,7 +401,7 @@ function CommentGroup({ |
| 401 | </span> | 401 | </span> |
| 402 | ))} | 402 | ))} |
| 403 | {authors.length > 3 ? ( | 403 | {authors.length > 3 ? ( |
| 404 | <span className="relative flex size-6 items-center justify-center rounded-full bg-muted text-[10px] text-muted-foreground ring-2 ring-background"> | 404 | <span className="relative flex size-6 items-center justify-center rounded-full bg-muted text-3xs text-muted-foreground ring-2 ring-background"> |
| 405 | +{authors.length - 3} | 405 | +{authors.length - 3} |
| 406 | </span> | 406 | </span> |
| 407 | ) : null} | 407 | ) : null} |
| ... | @@ -412,7 +412,7 @@ function CommentGroup({ | ... | @@ -412,7 +412,7 @@ function CommentGroup({ |
| 412 | > | 412 | > |
| 413 | <span className="min-w-0 flex-1 space-y-1"> | 413 | <span className="min-w-0 flex-1 space-y-1"> |
| 414 | <span className="block text-xs font-medium text-foreground/90">{label}</span> | 414 | <span className="block text-xs font-medium text-foreground/90">{label}</span> |
| 415 | <span className="flex flex-wrap gap-x-1.5 text-[11px] text-muted-foreground"> | 415 | <span className="flex flex-wrap gap-x-1.5 text-2xs text-muted-foreground"> |
| 416 | <span> | 416 | <span> |
| 417 | {authors.length} {authors.length === 1 ? "author" : "authors"} | 417 | {authors.length} {authors.length === 1 ? "author" : "authors"} |
| 418 | </span> | 418 | </span> |
apps/web/src/components/pullRequest/PullRequestTimelineTab.tsx+8-10| ... | @@ -141,7 +141,7 @@ function ActorTimelineMarker({ | ... | @@ -141,7 +141,7 @@ function ActorTimelineMarker({ |
| 141 | <PullRequestActorAvatar | 141 | <PullRequestActorAvatar |
| 142 | actor={actor} | 142 | actor={actor} |
| 143 | className={cn( | 143 | className={cn( |
| 144 | "size-7 bg-muted text-[9px] transition-opacity", | 144 | "size-7 bg-muted text-3xs transition-opacity", |
| 145 | muted && "opacity-45 grayscale", | 145 | muted && "opacity-45 grayscale", |
| 146 | )} | 146 | )} |
| 147 | /> | 147 | /> |
| ... | @@ -156,9 +156,7 @@ function friendlyReviewState(value: string): string { | ... | @@ -156,9 +156,7 @@ function friendlyReviewState(value: string): string { |
| 156 | 156 | ||
| 157 | function ReviewStateBadge({ state }: { state: string }) { | 157 | function ReviewStateBadge({ state }: { state: string }) { |
| 158 | return ( | 158 | return ( |
| 159 | <span className="text-[10px] font-medium text-muted-foreground"> | 159 | <span className="text-3xs font-medium text-muted-foreground">{friendlyReviewState(state)}</span> |
| 160 | {friendlyReviewState(state)} | ||
| 161 | </span> | ||
| 162 | ); | 160 | ); |
| 163 | } | 161 | } |
| 164 | 162 | ||
| ... | @@ -224,7 +222,7 @@ function ConversationCard({ | ... | @@ -224,7 +222,7 @@ function ConversationCard({ |
| 224 | <span className="text-muted-foreground">{event.title}</span> | 222 | <span className="text-muted-foreground">{event.title}</span> |
| 225 | {event.reviewState ? <ReviewStateBadge state={event.reviewState} /> : null} | 223 | {event.reviewState ? <ReviewStateBadge state={event.reviewState} /> : null} |
| 226 | </div> | 224 | </div> |
| 227 | <PullRequestMetaLine className="mt-1 flex-wrap text-[11px] text-muted-foreground"> | 225 | <PullRequestMetaLine className="mt-1 flex-wrap text-2xs text-muted-foreground"> |
| 228 | <span>{formatRelativeTimeLabel(event.at)}</span> | 226 | <span>{formatRelativeTimeLabel(event.at)}</span> |
| 229 | {event.path ? ( | 227 | {event.path ? ( |
| 230 | <span className="inline-flex min-w-0 items-center gap-1"> | 228 | <span className="inline-flex min-w-0 items-center gap-1"> |
| ... | @@ -330,7 +328,7 @@ function ConversationGroup({ | ... | @@ -330,7 +328,7 @@ function ConversationGroup({ |
| 330 | <span className="block text-xs font-semibold"> | 328 | <span className="block text-xs font-semibold"> |
| 331 | {events.length.toLocaleString()} {events.length === 1 ? "comment" : "comments"} | 329 | {events.length.toLocaleString()} {events.length === 1 ? "comment" : "comments"} |
| 332 | </span> | 330 | </span> |
| 333 | <span className="block truncate text-[10px] text-muted-foreground"> | 331 | <span className="block truncate text-3xs text-muted-foreground"> |
| 334 | {actors.length.toLocaleString()} {actors.length === 1 ? "author" : "authors"} ·{" "} | 332 | {actors.length.toLocaleString()} {actors.length === 1 ? "author" : "authors"} ·{" "} |
| 335 | {formatRelativeTimeLabel(first.at)} | 333 | {formatRelativeTimeLabel(first.at)} |
| 336 | </span> | 334 | </span> |
| ... | @@ -391,7 +389,7 @@ function CommitEvent({ | ... | @@ -391,7 +389,7 @@ function CommitEvent({ |
| 391 | <div className="truncate text-xs font-semibold text-foreground transition-colors group-hover:text-primary"> | 389 | <div className="truncate text-xs font-semibold text-foreground transition-colors group-hover:text-primary"> |
| 392 | {event.body ?? "Untitled commit"} | 390 | {event.body ?? "Untitled commit"} |
| 393 | </div> | 391 | </div> |
| 394 | <div className="mt-1 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[10px] text-muted-foreground"> | 392 | <div className="mt-1 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-3xs text-muted-foreground"> |
| 395 | <code className="font-mono">{event.id.slice(0, 7)}</code> | 393 | <code className="font-mono">{event.id.slice(0, 7)}</code> |
| 396 | <span>{formatRelativeTimeLabel(event.at)}</span> | 394 | <span>{formatRelativeTimeLabel(event.at)}</span> |
| 397 | </div> | 395 | </div> |
| ... | @@ -400,7 +398,7 @@ function CommitEvent({ | ... | @@ -400,7 +398,7 @@ function CommitEvent({ |
| 400 | <PullRequestDiffStat | 398 | <PullRequestDiffStat |
| 401 | additions={event.additions} | 399 | additions={event.additions} |
| 402 | deletions={event.deletions} | 400 | deletions={event.deletions} |
| 403 | className="ml-auto shrink-0 font-mono text-[10px]" | 401 | className="ml-auto shrink-0 font-mono text-3xs" |
| 404 | /> | 402 | /> |
| 405 | ) : null} | 403 | ) : null} |
| 406 | </div> | 404 | </div> |
| ... | @@ -433,7 +431,7 @@ function LifecycleEvent({ event }: { event: PullRequestTimelineEvent }) { | ... | @@ -433,7 +431,7 @@ function LifecycleEvent({ event }: { event: PullRequestTimelineEvent }) { |
| 433 | {event.actor ? <ActorName actor={event.actor} /> : null} | 431 | {event.actor ? <ActorName actor={event.actor} /> : null} |
| 434 | <span className="font-semibold text-foreground">{presentation.label}</span> | 432 | <span className="font-semibold text-foreground">{presentation.label}</span> |
| 435 | </div> | 433 | </div> |
| 436 | <div className="mt-0.5 text-[11px] text-muted-foreground"> | 434 | <div className="mt-0.5 text-2xs text-muted-foreground"> |
| 437 | {formatRelativeTimeLabel(event.at)} | 435 | {formatRelativeTimeLabel(event.at)} |
| 438 | </div> | 436 | </div> |
| 439 | </div> | 437 | </div> |
| ... | @@ -500,7 +498,7 @@ function ReviewVerdictEvent({ | ... | @@ -500,7 +498,7 @@ function ReviewVerdictEvent({ |
| 500 | </Tooltip> | 498 | </Tooltip> |
| 501 | </div> | 499 | </div> |
| 502 | <div className="mt-0.5 flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1"> | 500 | <div className="mt-0.5 flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1"> |
| 503 | <PullRequestMetaLine className="flex-wrap text-[11px] text-muted-foreground"> | 501 | <PullRequestMetaLine className="flex-wrap text-2xs text-muted-foreground"> |
| 504 | <span>{formatRelativeTimeLabel(event.at)}</span> | 502 | <span>{formatRelativeTimeLabel(event.at)}</span> |
| 505 | {event.path ? ( | 503 | {event.path ? ( |
| 506 | <span className="inline-flex min-w-0 items-center gap-1"> | 504 | <span className="inline-flex min-w-0 items-center gap-1"> |
apps/web/src/components/pullRequest/ThreadPullRequestsPanel.tsx+1-1| ... | @@ -308,7 +308,7 @@ function EnabledThreadPullRequestsPanel({ threadRef }: { threadRef: ScopedThread | ... | @@ -308,7 +308,7 @@ function EnabledThreadPullRequestsPanel({ threadRef }: { threadRef: ScopedThread |
| 308 | ))} | 308 | ))} |
| 309 | </div> | 309 | </div> |
| 310 | </ScrollArea> | 310 | </ScrollArea> |
| 311 | <footer className="flex items-center justify-between border-t border-border/60 px-2 py-1.5 text-[.7rem] text-muted-foreground"> | 311 | <footer className="flex items-center justify-between border-t border-border/60 px-2 py-1.5 text-2xs text-muted-foreground"> |
| 312 | <span> | 312 | <span> |
| 313 | {openCount} open · {links.length} linked | 313 | {openCount} open · {links.length} linked |
| 314 | {lastSynced ? ` · synced ${formatRelativeTimeLabel(lastSynced)}` : ""} | 314 | {lastSynced ? ` · synced ${formatRelativeTimeLabel(lastSynced)}` : ""} |
apps/web/src/components/pullRequest/pullRequestPresentation.tsx+1-1| ... | @@ -428,7 +428,7 @@ export function PullRequestActorAvatar({ | ... | @@ -428,7 +428,7 @@ export function PullRequestActorAvatar({ |
| 428 | <span | 428 | <span |
| 429 | aria-hidden | 429 | aria-hidden |
| 430 | className={cn( | 430 | className={cn( |
| 431 | "flex size-4 shrink-0 items-center justify-center rounded-full bg-muted text-[8px] font-medium text-muted-foreground", | 431 | "flex size-4 shrink-0 items-center justify-center rounded-full bg-muted text-3xs font-medium text-muted-foreground", |
| 432 | className, | 432 | className, |
| 433 | )} | 433 | )} |
| 434 | > | 434 | > |
apps/web/src/components/search/HighlightedSearchLine.tsx+1-1| ... | @@ -111,7 +111,7 @@ function HighlightedTokens(props: { | ... | @@ -111,7 +111,7 @@ function HighlightedTokens(props: { |
| 111 | .map((segment) => | 111 | .map((segment) => |
| 112 | segment.isMatch ? ( | 112 | segment.isMatch ? ( |
| 113 | <mark | 113 | <mark |
| 114 | className="rounded-[2px] bg-primary/25 text-inherit" | 114 | className="rounded-xs bg-primary/25 text-inherit" |
| 115 | key={`${segment.start}:${segment.end}:match`} | 115 | key={`${segment.start}:${segment.end}:match`} |
| 116 | style={tokenStyle(segment.token)} | 116 | style={tokenStyle(segment.token)} |
| 117 | > | 117 | > |
apps/web/src/components/search/ProjectContentSearchDialog.tsx+1-1| ... | @@ -265,7 +265,7 @@ function OpenContentSearchDialog(props: { | ... | @@ -265,7 +265,7 @@ function OpenContentSearchDialog(props: { |
| 265 | {path.directory} | 265 | {path.directory} |
| 266 | </span> | 266 | </span> |
| 267 | ) : null} | 267 | ) : null} |
| 268 | <span className="ml-auto rounded-full bg-muted px-1.5 py-0.5 tabular-nums text-[10px] text-muted-foreground"> | 268 | <span className="ml-auto rounded-full bg-muted px-1.5 py-0.5 tabular-nums text-3xs text-muted-foreground"> |
| 269 | {group.matches.length} | 269 | {group.matches.length} |
| 270 | </span> | 270 | </span> |
| 271 | </div> | 271 | </div> |
apps/web/src/components/settings/AddProviderInstanceDialog.tsx+4-4| ... | @@ -310,7 +310,7 @@ export function AddProviderInstanceDialog({ | ... | @@ -310,7 +310,7 @@ export function AddProviderInstanceDialog({ |
| 310 | value={label} | 310 | value={label} |
| 311 | onChange={(event) => setLabel(event.target.value)} | 311 | onChange={(event) => setLabel(event.target.value)} |
| 312 | /> | 312 | /> |
| 313 | <span className="text-[11px] text-muted-foreground"> | 313 | <span className="text-2xs text-muted-foreground"> |
| 314 | Shown in the provider list. Optional. | 314 | Shown in the provider list. Optional. |
| 315 | </span> | 315 | </span> |
| 316 | </label> | 316 | </label> |
| ... | @@ -326,9 +326,9 @@ export function AddProviderInstanceDialog({ | ... | @@ -326,9 +326,9 @@ export function AddProviderInstanceDialog({ |
| 326 | aria-invalid={showInstanceIdError} | 326 | aria-invalid={showInstanceIdError} |
| 327 | /> | 327 | /> |
| 328 | {showInstanceIdError ? ( | 328 | {showInstanceIdError ? ( |
| 329 | <span className="text-[11px] text-destructive">{instanceIdError}</span> | 329 | <span className="text-2xs text-destructive">{instanceIdError}</span> |
| 330 | ) : ( | 330 | ) : ( |
| 331 | <span className="text-[11px] text-muted-foreground"> | 331 | <span className="text-2xs text-muted-foreground"> |
| 332 | Routing key used by threads and sessions. Letters, digits, '-', or '_'. | 332 | Routing key used by threads and sessions. Letters, digits, '-', or '_'. |
| 333 | </span> | 333 | </span> |
| 334 | )} | 334 | )} |
| ... | @@ -374,7 +374,7 @@ export function AddProviderInstanceDialog({ | ... | @@ -374,7 +374,7 @@ export function AddProviderInstanceDialog({ |
| 374 | </Button> | 374 | </Button> |
| 375 | ) : null} | 375 | ) : null} |
| 376 | </div> | 376 | </div> |
| 377 | <span className="text-[11px] text-muted-foreground"> | 377 | <span className="text-2xs text-muted-foreground"> |
| 378 | Optional marker shown in the picker. | 378 | Optional marker shown in the picker. |
| 379 | </span> | 379 | </span> |
| 380 | </div> | 380 | </div> |
apps/web/src/components/settings/ConnectionsSettings.tsx+10-10| ... | @@ -771,11 +771,11 @@ const PairingLinkListRow = memo(function PairingLinkListRow({ | ... | @@ -771,11 +771,11 @@ const PairingLinkListRow = memo(function PairingLinkListRow({ |
| 771 | <AccessScopeSummary scopes={pairingLink.scopes} label="Pairing link scopes" /> | 771 | <AccessScopeSummary scopes={pairingLink.scopes} label="Pairing link scopes" /> |
| 772 | </p> | 772 | </p> |
| 773 | {!credential ? ( | 773 | {!credential ? ( |
| 774 | <p className="text-[11px] text-muted-foreground/70"> | 774 | <p className="text-2xs text-muted-foreground/70"> |
| 775 | Create a new link to share from this client. | 775 | Create a new link to share from this client. |
| 776 | </p> | 776 | </p> |
| 777 | ) : shareablePairingUrl === null ? ( | 777 | ) : shareablePairingUrl === null ? ( |
| 778 | <p className="text-[11px] text-muted-foreground/70"> | 778 | <p className="text-2xs text-muted-foreground/70"> |
| 779 | Copy the token and pair from another client using this backend&apos;s reachable host. | 779 | Copy the token and pair from another client using this backend&apos;s reachable host. |
| 780 | </p> | 780 | </p> |
| 781 | ) : null} | 781 | ) : null} |
| ... | @@ -882,7 +882,7 @@ const PairingLinkListRow = memo(function PairingLinkListRow({ | ... | @@ -882,7 +882,7 @@ const PairingLinkListRow = memo(function PairingLinkListRow({ |
| 882 | role="radiogroup" | 882 | role="radiogroup" |
| 883 | aria-label="Endpoint the pairing QR code and URL use" | 883 | aria-label="Endpoint the pairing QR code and URL use" |
| 884 | > | 884 | > |
| 885 | <p className="text-[11px] text-muted-foreground/70">Reach this machine via</p> | 885 | <p className="text-2xs text-muted-foreground/70">Reach this machine via</p> |
| 886 | {endpointCopyOptions.map((option) => { | 886 | {endpointCopyOptions.map((option) => { |
| 887 | const isSelected = option.id === selectedQrOption?.id; | 887 | const isSelected = option.id === selectedQrOption?.id; |
| 888 | return ( | 888 | return ( |
| ... | @@ -907,7 +907,7 @@ const PairingLinkListRow = memo(function PairingLinkListRow({ | ... | @@ -907,7 +907,7 @@ const PairingLinkListRow = memo(function PairingLinkListRow({ |
| 907 | > | 907 | > |
| 908 | {option.label} | 908 | {option.label} |
| 909 | </span> | 909 | </span> |
| 910 | <span className="min-w-0 truncate text-[11px] text-muted-foreground/70"> | 910 | <span className="min-w-0 truncate text-2xs text-muted-foreground/70"> |
| 911 | {option.detail} | 911 | {option.detail} |
| 912 | </span> | 912 | </span> |
| 913 | </button> | 913 | </button> |
| ... | @@ -919,7 +919,7 @@ const PairingLinkListRow = memo(function PairingLinkListRow({ | ... | @@ -919,7 +919,7 @@ const PairingLinkListRow = memo(function PairingLinkListRow({ |
| 919 | <Tooltip> | 919 | <Tooltip> |
| 920 | <TooltipTrigger | 920 | <TooltipTrigger |
| 921 | render={ | 921 | render={ |
| 922 | <code className="min-w-0 flex-1 truncate font-mono text-[11px] text-muted-foreground"> | 922 | <code className="min-w-0 flex-1 truncate font-mono text-2xs text-muted-foreground"> |
| 923 | {qrPairingUrl} | 923 | {qrPairingUrl} |
| 924 | </code> | 924 | </code> |
| 925 | } | 925 | } |
| ... | @@ -951,7 +951,7 @@ const PairingLinkListRow = memo(function PairingLinkListRow({ | ... | @@ -951,7 +951,7 @@ const PairingLinkListRow = memo(function PairingLinkListRow({ |
| 951 | </div> | 951 | </div> |
| 952 | ) : ( | 952 | ) : ( |
| 953 | <div className="flex size-[192px] shrink-0 items-center justify-center self-center rounded-xl border border-border/50 p-4 sm:self-start"> | 953 | <div className="flex size-[192px] shrink-0 items-center justify-center self-center rounded-xl border border-border/50 p-4 sm:self-start"> |
| 954 | <p className="text-center text-[11px] text-muted-foreground/70"> | 954 | <p className="text-center text-2xs text-muted-foreground/70"> |
| 955 | No QR for this endpoint. Another device scanning a loopback link would dial itself; | 955 | No QR for this endpoint. Another device scanning a loopback link would dial itself; |
| 956 | copy the URL for use on this machine instead. | 956 | copy the URL for use on this machine instead. |
| 957 | </p> | 957 | </p> |
| ... | @@ -1011,7 +1011,7 @@ const ConnectedClientListRow = memo(function ConnectedClientListRow({ | ... | @@ -1011,7 +1011,7 @@ const ConnectedClientListRow = memo(function ConnectedClientListRow({ |
| 1011 | /> | 1011 | /> |
| 1012 | <h3 className="text-sm font-medium text-foreground">{primaryLabel}</h3> | 1012 | <h3 className="text-sm font-medium text-foreground">{primaryLabel}</h3> |
| 1013 | {clientSession.current ? ( | 1013 | {clientSession.current ? ( |
| 1014 | <span className="text-[10px] text-muted-foreground/80 rounded-md border border-border/50 bg-muted/50 px-1 py-0.5"> | 1014 | <span className="text-3xs text-muted-foreground/80 rounded-md border border-border/50 bg-muted/50 px-1 py-0.5"> |
| 1015 | This device | 1015 | This device |
| 1016 | </span> | 1016 | </span> |
| 1017 | ) : null} | 1017 | ) : null} |
| ... | @@ -1335,14 +1335,14 @@ const AdvertisedEndpointListRow = memo(function AdvertisedEndpointListRow({ | ... | @@ -1335,14 +1335,14 @@ const AdvertisedEndpointListRow = memo(function AdvertisedEndpointListRow({ |
| 1335 | </Tooltip> | 1335 | </Tooltip> |
| 1336 | ) : null} | 1336 | ) : null} |
| 1337 | {!isAvailable ? ( | 1337 | {!isAvailable ? ( |
| 1338 | <span className="shrink-0 rounded-md border border-border/70 px-1 py-0.5 text-[10px] text-muted-foreground"> | 1338 | <span className="shrink-0 rounded-md border border-border/70 px-1 py-0.5 text-3xs text-muted-foreground"> |
| 1339 | Setup required | 1339 | Setup required |
| 1340 | </span> | 1340 | </span> |
| 1341 | ) : null} | 1341 | ) : null} |
| 1342 | </div> | 1342 | </div> |
| 1343 | <div className="ml-auto flex min-h-6 shrink-0 items-center justify-end gap-2"> | 1343 | <div className="ml-auto flex min-h-6 shrink-0 items-center justify-end gap-2"> |
| 1344 | {isDefault ? ( | 1344 | {isDefault ? ( |
| 1345 | <span className="rounded-md border border-primary/30 bg-primary/10 px-1 py-0.5 text-[10px] text-primary"> | 1345 | <span className="rounded-md border border-primary/30 bg-primary/10 px-1 py-0.5 text-3xs text-primary"> |
| 1346 | Default | 1346 | Default |
| 1347 | </span> | 1347 | </span> |
| 1348 | ) : null} | 1348 | ) : null} |
| ... | @@ -2660,7 +2660,7 @@ export function ConnectionsSettings() { | ... | @@ -2660,7 +2660,7 @@ export function ConnectionsSettings() { |
| 2660 | </label> | 2660 | </label> |
| 2661 | </div> | 2661 | </div> |
| 2662 | <div> | 2662 | <div> |
| 2663 | <span className="mt-1 block text-[11px] text-muted-foreground"> | 2663 | <span className="mt-1 block text-2xs text-muted-foreground"> |
| 2664 | Paste a full pairing URL here to fill both fields automatically. | 2664 | Paste a full pairing URL here to fill both fields automatically. |
| 2665 | </span> | 2665 | </span> |
| 2666 | </div> | 2666 | </div> |
apps/web/src/components/settings/CustomModelEditor.tsx+2-2| ... | @@ -169,7 +169,7 @@ export function CustomModelEditor({ | ... | @@ -169,7 +169,7 @@ export function CustomModelEditor({ |
| 169 | className="min-w-0 flex-1" | 169 | className="min-w-0 flex-1" |
| 170 | aria-label="Choice label" | 170 | aria-label="Choice label" |
| 171 | /> | 171 | /> |
| 172 | <label className="flex shrink-0 items-center gap-1.5 text-[11px] text-muted-foreground"> | 172 | <label className="flex shrink-0 items-center gap-1.5 text-2xs text-muted-foreground"> |
| 173 | <Switch | 173 | <Switch |
| 174 | size="sm" | 174 | size="sm" |
| 175 | checked={choice.isDefault} | 175 | checked={choice.isDefault} |
| ... | @@ -201,7 +201,7 @@ export function CustomModelEditor({ | ... | @@ -201,7 +201,7 @@ export function CustomModelEditor({ |
| 201 | className="flex flex-col gap-2 rounded-md border border-border/60 bg-background/40 p-2.5" | 201 | className="flex flex-col gap-2 rounded-md border border-border/60 bg-background/40 p-2.5" |
| 202 | > | 202 | > |
| 203 | <div className="flex flex-wrap items-center gap-2"> | 203 | <div className="flex flex-wrap items-center gap-2"> |
| 204 | <span className="w-14 shrink-0 text-[11px] text-muted-foreground">Option {index + 1}</span> | 204 | <span className="w-14 shrink-0 text-2xs text-muted-foreground">Option {index + 1}</span> |
| 205 | {presets.length > 0 ? ( | 205 | {presets.length > 0 ? ( |
| 206 | <Select | 206 | <Select |
| 207 | value={idSelectValue(descriptor)} | 207 | value={idSelectValue(descriptor)} |
apps/web/src/components/settings/DiagnosticsSettings.tsx+10-10| ... | @@ -94,7 +94,7 @@ function StatBlock({ | ... | @@ -94,7 +94,7 @@ function StatBlock({ |
| 94 | }) { | 94 | }) { |
| 95 | return ( | 95 | return ( |
| 96 | <div className="min-w-0 border-border/60 px-4 py-3 sm:px-5"> | 96 | <div className="min-w-0 border-border/60 px-4 py-3 sm:px-5"> |
| 97 | <div className="flex min-w-0 items-center gap-1.5 text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground/70"> | 97 | <div className="flex min-w-0 items-center gap-1.5 text-2xs font-medium uppercase tracking-widest text-muted-foreground/70"> |
| 98 | <span className="min-w-0 truncate">{label}</span> | 98 | <span className="min-w-0 truncate">{label}</span> |
| 99 | {tooltip ? ( | 99 | {tooltip ? ( |
| 100 | <Tooltip> | 100 | <Tooltip> |
| ... | @@ -183,7 +183,7 @@ function DiagnosticsTable({ | ... | @@ -183,7 +183,7 @@ function DiagnosticsTable({ |
| 183 | ))} | 183 | ))} |
| 184 | </colgroup> | 184 | </colgroup> |
| 185 | ) : null} | 185 | ) : null} |
| 186 | <thead className="border-b border-border/60 text-[11px] uppercase tracking-[0.08em] text-muted-foreground/70"> | 186 | <thead className="border-b border-border/60 text-2xs uppercase tracking-widest text-muted-foreground/70"> |
| 187 | <tr> | 187 | <tr> |
| 188 | {headers.map((header, index) => ( | 188 | {headers.map((header, index) => ( |
| 189 | <th | 189 | <th |
| ... | @@ -215,7 +215,7 @@ function TraceIdCell({ traceId }: { traceId: string }) { | ... | @@ -215,7 +215,7 @@ function TraceIdCell({ traceId }: { traceId: string }) { |
| 215 | <Tooltip> | 215 | <Tooltip> |
| 216 | <TooltipTrigger | 216 | <TooltipTrigger |
| 217 | render={ | 217 | render={ |
| 218 | <span className="min-w-0 flex-1 truncate font-mono text-[11px]"> | 218 | <span className="min-w-0 flex-1 truncate font-mono text-2xs"> |
| 219 | {shortenTraceId(traceId)} | 219 | {shortenTraceId(traceId)} |
| 220 | </span> | 220 | </span> |
| 221 | } | 221 | } |
| ... | @@ -362,7 +362,7 @@ function ProcessDiagnosticsTable({ | ... | @@ -362,7 +362,7 @@ function ProcessDiagnosticsTable({ |
| 362 | <col className="w-[11%]" /> | 362 | <col className="w-[11%]" /> |
| 363 | <col className="w-[6%]" /> | 363 | <col className="w-[6%]" /> |
| 364 | </colgroup> | 364 | </colgroup> |
| 365 | <thead className="sticky top-0 z-10 border-b border-border/60 bg-card text-[11px] uppercase tracking-[0.08em] text-muted-foreground/70"> | 365 | <thead className="sticky top-0 z-10 border-b border-border/60 bg-card text-2xs uppercase tracking-widest text-muted-foreground/70"> |
| 366 | <tr> | 366 | <tr> |
| 367 | <th className="px-4 py-2 font-semibold sm:pl-5">Name</th> | 367 | <th className="px-4 py-2 font-semibold sm:pl-5">Name</th> |
| 368 | <th className="px-3 py-2 text-right font-semibold">CPU</th> | 368 | <th className="px-3 py-2 text-right font-semibold">CPU</th> |
| ... | @@ -588,7 +588,7 @@ function ProcessResourceHistoryTable({ | ... | @@ -588,7 +588,7 @@ function ProcessResourceHistoryTable({ |
| 588 | <col className="w-[16%]" /> | 588 | <col className="w-[16%]" /> |
| 589 | <col className="w-[10%]" /> | 589 | <col className="w-[10%]" /> |
| 590 | </colgroup> | 590 | </colgroup> |
| 591 | <thead className="sticky top-0 z-10 border-b border-border/60 bg-card text-[11px] uppercase tracking-[0.08em] text-muted-foreground/70"> | 591 | <thead className="sticky top-0 z-10 border-b border-border/60 bg-card text-2xs uppercase tracking-widest text-muted-foreground/70"> |
| 592 | <tr> | 592 | <tr> |
| 593 | <th className="px-4 py-2 font-semibold sm:pl-5">Process</th> | 593 | <th className="px-4 py-2 font-semibold sm:pl-5">Process</th> |
| 594 | <th className="px-3 py-2 text-right font-semibold">CPU Time</th> | 594 | <th className="px-3 py-2 text-right font-semibold">CPU Time</th> |
| ... | @@ -662,15 +662,15 @@ function DiagnosticsLastChecked({ checkedAt }: { checkedAt: DateTime.Utc | null | ... | @@ -662,15 +662,15 @@ function DiagnosticsLastChecked({ checkedAt }: { checkedAt: DateTime.Utc | null |
| 662 | const relative = getRelativeTimeState(checkedAt ? DateTime.formatIso(checkedAt) : null); | 662 | const relative = getRelativeTimeState(checkedAt ? DateTime.formatIso(checkedAt) : null); |
| 663 | 663 | ||
| 664 | if (relative.status === "missing") { | 664 | if (relative.status === "missing") { |
| 665 | return <span className="text-[11px] text-muted-foreground/50">Checking</span>; | 665 | return <span className="text-2xs text-muted-foreground/50">Checking</span>; |
| 666 | } | 666 | } |
| 667 | 667 | ||
| 668 | if (relative.status === "invalid") { | 668 | if (relative.status === "invalid") { |
| 669 | return <span className="text-[11px] text-muted-foreground/50">Checked unavailable</span>; | 669 | return <span className="text-2xs text-muted-foreground/50">Checked unavailable</span>; |
| 670 | } | 670 | } |
| 671 | 671 | ||
| 672 | return ( | 672 | return ( |
| 673 | <span className="text-[11px] text-muted-foreground/60"> | 673 | <span className="text-2xs text-muted-foreground/60"> |
| 674 | {relative.suffix ? ( | 674 | {relative.suffix ? ( |
| 675 | <> | 675 | <> |
| 676 | Checked <span className="font-mono tabular-nums">{relative.value}</span> {relative.suffix} | 676 | Checked <span className="font-mono tabular-nums">{relative.value}</span> {relative.suffix} |
| ... | @@ -1222,7 +1222,7 @@ export function DiagnosticsSettingsPanel() { | ... | @@ -1222,7 +1222,7 @@ export function DiagnosticsSettingsPanel() { |
| 1222 | <col className="w-[26%]" /> | 1222 | <col className="w-[26%]" /> |
| 1223 | <col className="w-[30%]" /> | 1223 | <col className="w-[30%]" /> |
| 1224 | </colgroup> | 1224 | </colgroup> |
| 1225 | <thead className="border-b border-border/60 text-[11px] uppercase tracking-[0.08em] text-muted-foreground/70"> | 1225 | <thead className="border-b border-border/60 text-2xs uppercase tracking-widest text-muted-foreground/70"> |
| 1226 | <tr> | 1226 | <tr> |
| 1227 | <th className="whitespace-nowrap px-4 py-2.5 font-semibold sm:pl-5">Time</th> | 1227 | <th className="whitespace-nowrap px-4 py-2.5 font-semibold sm:pl-5">Time</th> |
| 1228 | <th className="whitespace-nowrap px-4 py-2.5 font-semibold">Level</th> | 1228 | <th className="whitespace-nowrap px-4 py-2.5 font-semibold">Level</th> |
| ... | @@ -1241,7 +1241,7 @@ export function DiagnosticsSettingsPanel() { | ... | @@ -1241,7 +1241,7 @@ export function DiagnosticsSettingsPanel() { |
| 1241 | {formatRelativeNoWrap(event.seenAt)} | 1241 | {formatRelativeNoWrap(event.seenAt)} |
| 1242 | </td> | 1242 | </td> |
| 1243 | <td className="px-4 py-3 align-top"> | 1243 | <td className="px-4 py-3 align-top"> |
| 1244 | <span className="inline-flex rounded bg-muted px-1.5 py-0.5 font-mono text-[11px] font-medium uppercase text-foreground/80"> | 1244 | <span className="inline-flex rounded bg-muted px-1.5 py-0.5 font-mono text-2xs font-medium uppercase text-foreground/80"> |
| 1245 | {event.level} | 1245 | {event.level} |
| 1246 | </span> | 1246 | </span> |
| 1247 | </td> | 1247 | </td> |
apps/web/src/components/settings/FontFamilyPicker.tsx+1-3| ... | @@ -173,9 +173,7 @@ export function FontFamilyPicker({ | ... | @@ -173,9 +173,7 @@ export function FontFamilyPicker({ |
| 173 | {family} | 173 | {family} |
| 174 | </span> | 174 | </span> |
| 175 | <span className="flex shrink-0 items-center gap-1.5"> | 175 | <span className="flex shrink-0 items-center gap-1.5"> |
| 176 | {isDefault ? ( | 176 | {isDefault ? <span className="text-3xs text-muted-foreground/60">default</span> : null} |
| 177 | <span className="text-[10px] text-muted-foreground/60">default</span> | ||
| 178 | ) : null} | ||
| 179 | {item === selectedValue ? ( | 177 | {item === selectedValue ? ( |
| 180 | <CheckIcon className="size-3.5 text-muted-foreground" /> | 178 | <CheckIcon className="size-3.5 text-muted-foreground" /> |
| 181 | ) : null} | 179 | ) : null} |
apps/web/src/components/settings/KeybindingsSettings.tsx+8-8| ... | @@ -255,7 +255,7 @@ function WarningTooltipIcon({ | ... | @@ -255,7 +255,7 @@ function WarningTooltipIcon({ |
| 255 | tabIndex={focusable ? 0 : undefined} | 255 | tabIndex={focusable ? 0 : undefined} |
| 256 | aria-label={label} | 256 | aria-label={label} |
| 257 | className={cn( | 257 | className={cn( |
| 258 | "inline-flex size-5 shrink-0 items-center justify-center rounded-sm text-warning outline-none transition-colors hover:bg-warning/10 focus-visible:ring-[3px] focus-visible:ring-warning/25", | 258 | "inline-flex size-5 shrink-0 items-center justify-center rounded-sm text-warning outline-none transition-colors hover:bg-warning/10 focus-visible:ring-3 focus-visible:ring-warning/25", |
| 259 | className, | 259 | className, |
| 260 | )} | 260 | )} |
| 261 | /> | 261 | /> |
| ... | @@ -668,7 +668,7 @@ function WhenExpressionBuilder({ | ... | @@ -668,7 +668,7 @@ function WhenExpressionBuilder({ |
| 668 | ) : null} | 668 | ) : null} |
| 669 | </InputGroup> | 669 | </InputGroup> |
| 670 | {parseError ? ( | 670 | {parseError ? ( |
| 671 | <div className="flex items-center gap-1.5 text-[11px] text-destructive"> | 671 | <div className="flex items-center gap-1.5 text-2xs text-destructive"> |
| 672 | <CircleXIcon className="size-3.5" /> | 672 | <CircleXIcon className="size-3.5" /> |
| 673 | {parseError} | 673 | {parseError} |
| 674 | </div> | 674 | </div> |
| ... | @@ -698,7 +698,7 @@ function WhenExpressionBuilder({ | ... | @@ -698,7 +698,7 @@ function WhenExpressionBuilder({ |
| 698 | </div> | 698 | </div> |
| 699 | )} | 699 | )} |
| 700 | {parseError ? ( | 700 | {parseError ? ( |
| 701 | <div className="pointer-events-none absolute inset-0 flex items-center justify-center rounded-lg border border-destructive/30 bg-background/75 p-4 text-center text-xs text-destructive backdrop-blur-[1px]"> | 701 | <div className="pointer-events-none absolute inset-0 flex items-center justify-center rounded-lg border border-destructive/30 bg-background/75 p-4 text-center text-xs text-destructive backdrop-blur-xs"> |
| 702 | Fix the expression above to continue editing visually. | 702 | Fix the expression above to continue editing visually. |
| 703 | </div> | 703 | </div> |
| 704 | ) : null} | 704 | ) : null} |
| ... | @@ -842,7 +842,7 @@ function KeybindingKeyControl({ | ... | @@ -842,7 +842,7 @@ function KeybindingKeyControl({ |
| 842 | onClick={() => setDraft({ isRecording: true })} | 842 | onClick={() => setDraft({ isRecording: true })} |
| 843 | aria-label={`Edit shortcut for ${commandLabel(row.command)}: ${formatShortcutLabel(row.binding.shortcut)}`} | 843 | aria-label={`Edit shortcut for ${commandLabel(row.command)}: ${formatShortcutLabel(row.binding.shortcut)}`} |
| 844 | className={cn( | 844 | className={cn( |
| 845 | "inline-flex h-8 cursor-pointer items-center rounded-md border border-transparent px-1.5 sm:h-7 outline-none transition-colors hover:border-border/70 hover:bg-accent focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/24", | 845 | "inline-flex h-8 cursor-pointer items-center rounded-md border border-transparent px-1.5 sm:h-7 outline-none transition-colors hover:border-border/70 hover:bg-accent focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/24", |
| 846 | pillClassName, | 846 | pillClassName, |
| 847 | )} | 847 | )} |
| 848 | > | 848 | > |
| ... | @@ -989,7 +989,7 @@ function KeybindingRowWhen({ | ... | @@ -989,7 +989,7 @@ function KeybindingRowWhen({ |
| 989 | }) { | 989 | }) { |
| 990 | return ( | 990 | return ( |
| 991 | <span className="flex h-6 items-center gap-1.5"> | 991 | <span className="flex h-6 items-center gap-1.5"> |
| 992 | <span className="text-[12px] leading-none text-muted-foreground/70">When</span> | 992 | <span className="text-xs leading-none text-muted-foreground/70">When</span> |
| 993 | <WhenClauseControl | 993 | <WhenClauseControl |
| 994 | label={commandLabel(row.command)} | 994 | label={commandLabel(row.command)} |
| 995 | expression={editor.whenDraftExpression} | 995 | expression={editor.whenDraftExpression} |
| ... | @@ -1234,7 +1234,7 @@ function NewKeybindingSettingsRow(props: NewKeybindingProps) { | ... | @@ -1234,7 +1234,7 @@ function NewKeybindingSettingsRow(props: NewKeybindingProps) { |
| 1234 | title="New keybinding" | 1234 | title="New keybinding" |
| 1235 | description={ | 1235 | description={ |
| 1236 | <span className="flex h-6 items-center gap-1.5"> | 1236 | <span className="flex h-6 items-center gap-1.5"> |
| 1237 | <span className="text-[12px] leading-none text-muted-foreground/70">When</span> | 1237 | <span className="text-xs leading-none text-muted-foreground/70">When</span> |
| 1238 | <NewKeybindingWhen draft={draft} variables={variables} /> | 1238 | <NewKeybindingWhen draft={draft} variables={variables} /> |
| 1239 | </span> | 1239 | </span> |
| 1240 | } | 1240 | } |
| ... | @@ -1312,7 +1312,7 @@ function KeybindingsList(props: KeybindingsListProps) { | ... | @@ -1312,7 +1312,7 @@ function KeybindingsList(props: KeybindingsListProps) { |
| 1312 | /** Shown in the browser build only; the desktop app receives every shortcut. */ | 1312 | /** Shown in the browser build only; the desktop app receives every shortcut. */ |
| 1313 | function BrowserKeybindingNotice() { | 1313 | function BrowserKeybindingNotice() { |
| 1314 | return ( | 1314 | return ( |
| 1315 | <div className="flex items-center gap-2 px-3 py-2.5 text-[12px] leading-[1.45] text-muted-foreground sm:px-4"> | 1315 | <div className="flex items-center gap-2 px-3 py-2.5 text-xs leading-normal text-muted-foreground sm:px-4"> |
| 1316 | <TriangleAlertIcon className="size-3.5 shrink-0 text-warning" aria-hidden /> | 1316 | <TriangleAlertIcon className="size-3.5 shrink-0 text-warning" aria-hidden /> |
| 1317 | <span> | 1317 | <span> |
| 1318 | Some shortcuts may be claimed by the browser before T3 Code sees them. Use the desktop app | 1318 | Some shortcuts may be claimed by the browser before T3 Code sees them. Use the desktop app |
| ... | @@ -1488,7 +1488,7 @@ export function KeybindingsSettingsPanel() { | ... | @@ -1488,7 +1488,7 @@ export function KeybindingsSettingsPanel() { |
| 1488 | const cancelAdd = useCallback(() => setIsAddingBinding(false), []); | 1488 | const cancelAdd = useCallback(() => setIsAddingBinding(false), []); |
| 1489 | 1489 | ||
| 1490 | const bindingsCount = ( | 1490 | const bindingsCount = ( |
| 1491 | <span className="text-[11px] text-muted-foreground"> | 1491 | <span className="text-2xs text-muted-foreground"> |
| 1492 | {rows.length + (isAddingBinding ? 1 : 0)}{" "} | 1492 | {rows.length + (isAddingBinding ? 1 : 0)}{" "} |
| 1493 | {rows.length + (isAddingBinding ? 1 : 0) === 1 ? "binding" : "bindings"} | 1493 | {rows.length + (isAddingBinding ? 1 : 0) === 1 ? "binding" : "bindings"} |
| 1494 | </span> | 1494 | </span> |
apps/web/src/components/settings/OpenSourceLicenses.tsx+1-1| ... | @@ -179,7 +179,7 @@ function LicenseManifestError({ message, onRetry }: { message: string; onRetry: | ... | @@ -179,7 +179,7 @@ function LicenseManifestError({ message, onRetry }: { message: string; onRetry: |
| 179 | <div className="flex flex-col items-start gap-3 px-3 py-5 sm:px-4"> | 179 | <div className="flex flex-col items-start gap-3 px-3 py-5 sm:px-4"> |
| 180 | <div className="flex flex-col gap-1"> | 180 | <div className="flex flex-col gap-1"> |
| 181 | <h3 className="text-sm font-medium text-foreground">Open-source notices are unavailable</h3> | 181 | <h3 className="text-sm font-medium text-foreground">Open-source notices are unavailable</h3> |
| 182 | <p className="max-w-[70ch] text-pretty text-[13px] leading-[1.45] text-muted-foreground/80"> | 182 | <p className="max-w-[70ch] text-pretty text-xs leading-normal text-muted-foreground/80"> |
| 183 | {message} | 183 | {message} |
| 184 | </p> | 184 | </p> |
| 185 | </div> | 185 | </div> |
apps/web/src/components/settings/PanelAnimationsPreview.tsx+1-1| ... | @@ -5,7 +5,7 @@ import { cn } from "~/lib/utils"; | ... | @@ -5,7 +5,7 @@ import { cn } from "~/lib/utils"; |
| 5 | export function PanelAnimationsPreview({ durationMs }: { durationMs: number }) { | 5 | export function PanelAnimationsPreview({ durationMs }: { durationMs: number }) { |
| 6 | const [panelsOpen, setPanelsOpen] = useState(true); | 6 | const [panelsOpen, setPanelsOpen] = useState(true); |
| 7 | const transitionClass = | 7 | const transitionClass = |
| 8 | "transition-[width,height,border-width] [transition-duration:var(--preview-duration)] ease-out motion-reduce:transition-none"; | 8 | "transition-[width,height,border-width] duration-(--preview-duration) ease-out motion-reduce:transition-none"; |
| 9 | 9 | ||
| 10 | return ( | 10 | return ( |
| 11 | <button | 11 | <button |
apps/web/src/components/settings/ProjectActionsList.tsx+2-2| ... | @@ -34,12 +34,12 @@ export function ProjectActionsList({ | ... | @@ -34,12 +34,12 @@ export function ProjectActionsList({ |
| 34 | <ScriptIcon icon={script.icon} className="size-4 shrink-0 text-muted-foreground" /> | 34 | <ScriptIcon icon={script.icon} className="size-4 shrink-0 text-muted-foreground" /> |
| 35 | <span className="min-w-0 truncate">{script.name}</span> | 35 | <span className="min-w-0 truncate">{script.name}</span> |
| 36 | {script.runOnWorktreeCreate ? ( | 36 | {script.runOnWorktreeCreate ? ( |
| 37 | <span className="shrink-0 rounded-sm border border-border/60 px-1.5 py-px text-[11px] font-normal text-muted-foreground"> | 37 | <span className="shrink-0 rounded-sm border border-border/60 px-1.5 py-px text-2xs font-normal text-muted-foreground"> |
| 38 | setup | 38 | setup |
| 39 | </span> | 39 | </span> |
| 40 | ) : null} | 40 | ) : null} |
| 41 | {script.previewUrl ? ( | 41 | {script.previewUrl ? ( |
| 42 | <span className="shrink-0 rounded-sm border border-border/60 px-1.5 py-px text-[11px] font-normal text-muted-foreground max-sm:hidden"> | 42 | <span className="shrink-0 rounded-sm border border-border/60 px-1.5 py-px text-2xs font-normal text-muted-foreground max-sm:hidden"> |
| 43 | preview · desktop only | 43 | preview · desktop only |
| 44 | </span> | 44 | </span> |
| 45 | ) : null} | 45 | ) : null} |
apps/web/src/components/settings/ProviderInstanceCard.test.ts+1-1| ... | @@ -118,7 +118,7 @@ describe("deriveProviderModelsForDisplay", () => { | ... | @@ -118,7 +118,7 @@ describe("deriveProviderModelsForDisplay", () => { |
| 118 | 118 | ||
| 119 | expect(markup).toContain("Authenticated as"); | 119 | expect(markup).toContain("Authenticated as"); |
| 120 | expect(markup).toContain('aria-label="Toggle account email visibility"'); | 120 | expect(markup).toContain('aria-label="Toggle account email visibility"'); |
| 121 | expect(markup).toContain("blur-[2px]"); | 121 | expect(markup).toContain("blur-xs"); |
| 122 | expect(markup).not.toContain("developer@example.com"); | 122 | expect(markup).not.toContain("developer@example.com"); |
| 123 | }); | 123 | }); |
| 124 | it("surfaces a failed probe message in both the list row and the editor", () => { | 124 | it("surfaces a failed probe message in both the list row and the editor", () => { |
apps/web/src/components/settings/ProviderInstanceCard.tsx+7-7| ... | @@ -570,7 +570,7 @@ export function ProviderInstanceCard({ | ... | @@ -570,7 +570,7 @@ export function ProviderInstanceCard({ |
| 570 | showBadge={Boolean(accentColor)} | 570 | showBadge={Boolean(accentColor)} |
| 571 | className="size-5" | 571 | className="size-5" |
| 572 | iconClassName="size-4 text-foreground/80" | 572 | iconClassName="size-4 text-foreground/80" |
| 573 | badgeClassName="right-[-0.125rem] bottom-[-0.125rem] h-3 min-w-3 px-0.5 text-[7px]" | 573 | badgeClassName="right-[-0.125rem] bottom-[-0.125rem] h-3 min-w-3 px-0.5 text-3xs" |
| 574 | /> | 574 | /> |
| 575 | ) : FallbackIconComponent ? ( | 575 | ) : FallbackIconComponent ? ( |
| 576 | <span className="inline-flex size-5 shrink-0 items-center justify-center"> | 576 | <span className="inline-flex size-5 shrink-0 items-center justify-center"> |
| ... | @@ -578,7 +578,7 @@ export function ProviderInstanceCard({ | ... | @@ -578,7 +578,7 @@ export function ProviderInstanceCard({ |
| 578 | </span> | 578 | </span> |
| 579 | ) : ( | 579 | ) : ( |
| 580 | <span | 580 | <span |
| 581 | className="inline-flex size-5 shrink-0 items-center justify-center text-[10px] font-semibold leading-none text-foreground/80" | 581 | className="inline-flex size-5 shrink-0 items-center justify-center text-3xs font-semibold leading-none text-foreground/80" |
| 582 | aria-hidden | 582 | aria-hidden |
| 583 | > | 583 | > |
| 584 | {providerInstanceInitials(displayName)} | 584 | {providerInstanceInitials(displayName)} |
| ... | @@ -655,7 +655,7 @@ export function ProviderInstanceCard({ | ... | @@ -655,7 +655,7 @@ export function ProviderInstanceCard({ |
| 655 | <span className="flex min-w-0 items-center gap-2"> | 655 | <span className="flex min-w-0 items-center gap-2"> |
| 656 | <span className="truncate text-sm font-medium text-foreground">{displayName}</span> | 656 | <span className="truncate text-sm font-medium text-foreground">{displayName}</span> |
| 657 | {String(instanceId) !== String(instance.driver) ? ( | 657 | {String(instanceId) !== String(instance.driver) ? ( |
| 658 | <code className="min-w-0 truncate rounded bg-muted/60 px-1 py-0.5 text-[10px] text-muted-foreground"> | 658 | <code className="min-w-0 truncate rounded bg-muted/60 px-1 py-0.5 text-3xs text-muted-foreground"> |
| 659 | {instanceId} | 659 | {instanceId} |
| 660 | </code> | 660 | </code> |
| 661 | ) : null} | 661 | ) : null} |
| ... | @@ -708,7 +708,7 @@ export function ProviderInstanceCard({ | ... | @@ -708,7 +708,7 @@ export function ProviderInstanceCard({ |
| 708 | ) | 708 | ) |
| 709 | ) : null} | 709 | ) : null} |
| 710 | </span> | 710 | </span> |
| 711 | <span className="mt-0.5 flex items-start gap-1.5 text-[13px] leading-[1.45] text-muted-foreground/80"> | 711 | <span className="mt-0.5 flex items-start gap-1.5 text-xs leading-normal text-muted-foreground/80"> |
| 712 | {statusDotNode ? ( | 712 | {statusDotNode ? ( |
| 713 | <span className="flex h-[1.45em] shrink-0 items-center">{statusDotNode}</span> | 713 | <span className="flex h-[1.45em] shrink-0 items-center">{statusDotNode}</span> |
| 714 | ) : null} | 714 | ) : null} |
| ... | @@ -775,7 +775,7 @@ export function ProviderInstanceCard({ | ... | @@ -775,7 +775,7 @@ export function ProviderInstanceCard({ |
| 775 | <PopoverPopup side="bottom" align="end" width="md"> | 775 | <PopoverPopup side="bottom" align="end" width="md"> |
| 776 | <div className="grid min-w-0 gap-3"> | 776 | <div className="grid min-w-0 gap-3"> |
| 777 | <div className="grid gap-0.5"> | 777 | <div className="grid gap-0.5"> |
| 778 | <p className="text-[13px] font-semibold leading-tight text-foreground"> | 778 | <p className="text-sm font-semibold leading-tight text-foreground"> |
| 779 | {versionAdvisory.title} | 779 | {versionAdvisory.title} |
| 780 | </p> | 780 | </p> |
| 781 | <p | 781 | <p |
| ... | @@ -807,7 +807,7 @@ export function ProviderInstanceCard({ | ... | @@ -807,7 +807,7 @@ export function ProviderInstanceCard({ |
| 807 | </Button> | 807 | </Button> |
| 808 | ) : null} | 808 | ) : null} |
| 809 | {onRunVersionAction && updateCommand ? ( | 809 | {onRunVersionAction && updateCommand ? ( |
| 810 | <div className="flex items-center gap-2 text-[10px] font-medium uppercase tracking-wider text-muted-foreground"> | 810 | <div className="flex items-center gap-2 text-3xs font-medium uppercase tracking-wider text-muted-foreground"> |
| 811 | <span aria-hidden className="h-px flex-1 bg-border" /> | 811 | <span aria-hidden className="h-px flex-1 bg-border" /> |
| 812 | or, update manually using | 812 | or, update manually using |
| 813 | <span aria-hidden className="h-px flex-1 bg-border" /> | 813 | <span aria-hidden className="h-px flex-1 bg-border" /> |
| ... | @@ -815,7 +815,7 @@ export function ProviderInstanceCard({ | ... | @@ -815,7 +815,7 @@ export function ProviderInstanceCard({ |
| 815 | ) : null} | 815 | ) : null} |
| 816 | {updateCommand ? ( | 816 | {updateCommand ? ( |
| 817 | <div className="flex min-w-0 items-center gap-1 rounded-md border border-border/70 bg-muted/40 py-0.5 pr-0.5 pl-2"> | 817 | <div className="flex min-w-0 items-center gap-1 rounded-md border border-border/70 bg-muted/40 py-0.5 pr-0.5 pl-2"> |
| 818 | <code className="min-w-0 flex-1 truncate font-mono text-[11px] text-foreground"> | 818 | <code className="min-w-0 flex-1 truncate font-mono text-2xs text-foreground"> |
| 819 | {updateCommand} | 819 | {updateCommand} |
| 820 | </code> | 820 | </code> |
| 821 | <Tooltip> | 821 | <Tooltip> |
apps/web/src/components/settings/ProviderModelsSection.tsx+4-4| ... | @@ -470,19 +470,19 @@ export function ProviderModelsSection({ | ... | @@ -470,19 +470,19 @@ export function ProviderModelsSection({ |
| 470 | <span className="flex min-w-0 items-baseline gap-2"> | 470 | <span className="flex min-w-0 items-baseline gap-2"> |
| 471 | <span className={cn(nameClassName, "truncate")}>{model.name}</span> | 471 | <span className={cn(nameClassName, "truncate")}>{model.name}</span> |
| 472 | {model.name !== model.slug ? ( | 472 | {model.name !== model.slug ? ( |
| 473 | <code className="truncate font-mono text-[11px] text-muted-foreground/70"> | 473 | <code className="truncate font-mono text-2xs text-muted-foreground/70"> |
| 474 | {model.slug} | 474 | {model.slug} |
| 475 | </code> | 475 | </code> |
| 476 | ) : null} | 476 | ) : null} |
| 477 | {model.isCustom ? ( | 477 | {model.isCustom ? ( |
| 478 | <span className="text-[11px] text-muted-foreground/70">custom</span> | 478 | <span className="text-2xs text-muted-foreground/70">custom</span> |
| 479 | ) : null} | 479 | ) : null} |
| 480 | </span> | 480 | </span> |
| 481 | {/* | 481 | {/* |
| 482 | Always a grid item so the columns line up across rows; the text | 482 | Always a grid item so the columns line up across rows; the text |
| 483 | itself drops out on phone widths where it would starve the name. | 483 | itself drops out on phone widths where it would starve the name. |
| 484 | */} | 484 | */} |
| 485 | <span className="text-[11px] text-muted-foreground/70"> | 485 | <span className="text-2xs text-muted-foreground/70"> |
| 486 | {capLabels.length > 0 ? ( | 486 | {capLabels.length > 0 ? ( |
| 487 | <span className="hidden sm:inline">{capLabels.join(" · ")}</span> | 487 | <span className="hidden sm:inline">{capLabels.join(" · ")}</span> |
| 488 | ) : null} | 488 | ) : null} |
| ... | @@ -494,7 +494,7 @@ export function ProviderModelsSection({ | ... | @@ -494,7 +494,7 @@ export function ProviderModelsSection({ |
| 494 | }; | 494 | }; |
| 495 | 495 | ||
| 496 | const groupLabel = (label: string, isFirst: boolean) => ( | 496 | const groupLabel = (label: string, isFirst: boolean) => ( |
| 497 | <div className={cn("px-2 pb-1.5 text-[11px] text-muted-foreground", isFirst ? "pt-1" : "pt-5")}> | 497 | <div className={cn("px-2 pb-1.5 text-2xs text-muted-foreground", isFirst ? "pt-1" : "pt-5")}> |
| 498 | {label} | 498 | {label} |
| 499 | </div> | 499 | </div> |
| 500 | ); | 500 | ); |
apps/web/src/components/settings/ProviderSettingsForm.tsx+1-1| ... | @@ -240,7 +240,7 @@ function ProviderSettingsFieldRow({ | ... | @@ -240,7 +240,7 @@ function ProviderSettingsFieldRow({ |
| 240 | const inputId = `${idPrefix}-${field.key}`; | 240 | const inputId = `${idPrefix}-${field.key}`; |
| 241 | const descriptionClassName = | 241 | const descriptionClassName = |
| 242 | variant === "dialog" | 242 | variant === "dialog" |
| 243 | ? "text-[11px] text-muted-foreground" | 243 | ? "text-2xs text-muted-foreground" |
| 244 | : "mt-1 block text-xs text-muted-foreground"; | 244 | : "mt-1 block text-xs text-muted-foreground"; |
| 245 | const label = <span className="text-xs font-medium text-foreground">{field.label}</span>; | 245 | const label = <span className="text-xs font-medium text-foreground">{field.label}</span>; |
| 246 | const description = field.description ? ( | 246 | const description = field.description ? ( |
apps/web/src/components/settings/RedactedSensitiveText.tsx+2-2| ... | @@ -44,8 +44,8 @@ export function RedactedSensitiveText(props: { | ... | @@ -44,8 +44,8 @@ export function RedactedSensitiveText(props: { |
| 44 | <button | 44 | <button |
| 45 | type="button" | 45 | type="button" |
| 46 | className={cn( | 46 | className={cn( |
| 47 | "min-w-0 cursor-pointer rounded-sm font-mono text-[11px] leading-normal transition hover:text-foreground", | 47 | "min-w-0 cursor-pointer rounded-sm font-mono text-2xs leading-normal transition hover:text-foreground", |
| 48 | revealed ? "text-muted-foreground" : "select-none text-muted-foreground blur-[2px]", | 48 | revealed ? "text-muted-foreground" : "select-none text-muted-foreground blur-xs", |
| 49 | props.className, | 49 | props.className, |
| 50 | )} | 50 | )} |
| 51 | onClick={() => setRevealed((current) => !current)} | 51 | onClick={() => setRevealed((current) => !current)} |
apps/web/src/components/settings/ResourceTelemetryDiagnostics.tsx+35-35| ... | @@ -194,7 +194,7 @@ function SourceStatusBadge({ | ... | @@ -194,7 +194,7 @@ function SourceStatusBadge({ |
| 194 | return ( | 194 | return ( |
| 195 | <span | 195 | <span |
| 196 | className={cn( | 196 | className={cn( |
| 197 | "inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.08em]", | 197 | "inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-3xs font-semibold uppercase tracking-widest", |
| 198 | tone === "neutral" && "border-border/70 bg-muted/45 text-muted-foreground", | 198 | tone === "neutral" && "border-border/70 bg-muted/45 text-muted-foreground", |
| 199 | tone === "default" && "border-success/25 bg-success/10 text-success-foreground", | 199 | tone === "default" && "border-success/25 bg-success/10 text-success-foreground", |
| 200 | tone === "warning" && "border-warning/30 bg-warning/10 text-warning-foreground", | 200 | tone === "warning" && "border-warning/30 bg-warning/10 text-warning-foreground", |
| ... | @@ -218,14 +218,14 @@ function SourceStatusBadge({ | ... | @@ -218,14 +218,14 @@ function SourceStatusBadge({ |
| 218 | function LastSampleLabel({ sampledAt }: { sampledAt: DateTime.Utc | null }) { | 218 | function LastSampleLabel({ sampledAt }: { sampledAt: DateTime.Utc | null }) { |
| 219 | useRelativeTimeTick(); | 219 | useRelativeTimeTick(); |
| 220 | if (!sampledAt) { | 220 | if (!sampledAt) { |
| 221 | return <span className="text-[11px] text-muted-foreground/55">Waiting for sample</span>; | 221 | return <span className="text-2xs text-muted-foreground/55">Waiting for sample</span>; |
| 222 | } | 222 | } |
| 223 | const relative = formatRelativeTime(DateTime.formatIso(sampledAt)); | 223 | const relative = formatRelativeTime(DateTime.formatIso(sampledAt)); |
| 224 | if (!relative) { | 224 | if (!relative) { |
| 225 | return <span className="text-[11px] text-muted-foreground/55">Waiting for sample</span>; | 225 | return <span className="text-2xs text-muted-foreground/55">Waiting for sample</span>; |
| 226 | } | 226 | } |
| 227 | return ( | 227 | return ( |
| 228 | <span className="text-[11px] text-muted-foreground/60"> | 228 | <span className="text-2xs text-muted-foreground/60"> |
| 229 | Updated <span className="font-mono tabular-nums">{relative.value}</span> | 229 | Updated <span className="font-mono tabular-nums">{relative.value}</span> |
| 230 | {relative.suffix ? ` ${relative.suffix}` : ""} | 230 | {relative.suffix ? ` ${relative.suffix}` : ""} |
| 231 | </span> | 231 | </span> |
| ... | @@ -247,7 +247,7 @@ function IconStat({ | ... | @@ -247,7 +247,7 @@ function IconStat({ |
| 247 | }) { | 247 | }) { |
| 248 | return ( | 248 | return ( |
| 249 | <div className="group min-w-0 px-4 py-4 sm:px-5"> | 249 | <div className="group min-w-0 px-4 py-4 sm:px-5"> |
| 250 | <div className="flex items-center gap-2 text-[10px] font-semibold uppercase tracking-[0.11em] text-muted-foreground/70"> | 250 | <div className="flex items-center gap-2 text-3xs font-semibold uppercase tracking-widest text-muted-foreground/70"> |
| 251 | <span className="text-muted-foreground/55 transition-colors group-hover:text-foreground/65"> | 251 | <span className="text-muted-foreground/55 transition-colors group-hover:text-foreground/65"> |
| 252 | {icon} | 252 | {icon} |
| 253 | </span> | 253 | </span> |
| ... | @@ -255,7 +255,7 @@ function IconStat({ | ... | @@ -255,7 +255,7 @@ function IconStat({ |
| 255 | </div> | 255 | </div> |
| 256 | <div | 256 | <div |
| 257 | className={cn( | 257 | className={cn( |
| 258 | "mt-2.5 truncate font-mono text-2xl font-semibold tracking-[-0.05em] tabular-nums text-foreground", | 258 | "mt-2.5 truncate font-mono text-2xl font-semibold tracking-tighter tabular-nums text-foreground", |
| 259 | tone === "warning" && "text-warning-foreground", | 259 | tone === "warning" && "text-warning-foreground", |
| 260 | tone === "danger" && "text-destructive", | 260 | tone === "danger" && "text-destructive", |
| 261 | )} | 261 | )} |
| ... | @@ -263,7 +263,7 @@ function IconStat({ | ... | @@ -263,7 +263,7 @@ function IconStat({ |
| 263 | {value} | 263 | {value} |
| 264 | </div> | 264 | </div> |
| 265 | {detail ? ( | 265 | {detail ? ( |
| 266 | <div className="mt-1.5 truncate text-[10px] text-muted-foreground/60">{detail}</div> | 266 | <div className="mt-1.5 truncate text-3xs text-muted-foreground/60">{detail}</div> |
| 267 | ) : null} | 267 | ) : null} |
| 268 | </div> | 268 | </div> |
| 269 | ); | 269 | ); |
| ... | @@ -282,10 +282,10 @@ function AggregateCard({ | ... | @@ -282,10 +282,10 @@ function AggregateCard({ |
| 282 | <div className="relative overflow-hidden border-t border-border/60 px-4 py-4 first:border-t-0 md:border-t-0 md:border-l md:first:border-l-0 sm:px-5"> | 282 | <div className="relative overflow-hidden border-t border-border/60 px-4 py-4 first:border-t-0 md:border-t-0 md:border-l md:first:border-l-0 sm:px-5"> |
| 283 | <span className={cn("absolute inset-x-5 top-0 h-0.5 rounded-full opacity-75", accentClass)} /> | 283 | <span className={cn("absolute inset-x-5 top-0 h-0.5 rounded-full opacity-75", accentClass)} /> |
| 284 | <div className="flex items-center justify-between gap-3"> | 284 | <div className="flex items-center justify-between gap-3"> |
| 285 | <div className="text-[10px] font-semibold uppercase tracking-[0.11em] text-muted-foreground/75"> | 285 | <div className="text-3xs font-semibold uppercase tracking-widest text-muted-foreground/75"> |
| 286 | {label} | 286 | {label} |
| 287 | </div> | 287 | </div> |
| 288 | <div className="rounded-md bg-muted/55 px-1.5 py-0.5 font-mono text-[9px] tabular-nums text-muted-foreground/70"> | 288 | <div className="rounded-md bg-muted/55 px-1.5 py-0.5 font-mono text-3xs tabular-nums text-muted-foreground/70"> |
| 289 | {aggregate.processCount} {aggregate.processCount === 1 ? "process" : "processes"} | 289 | {aggregate.processCount} {aggregate.processCount === 1 ? "process" : "processes"} |
| 290 | </div> | 290 | </div> |
| 291 | </div> | 291 | </div> |
| ... | @@ -302,7 +302,7 @@ function AggregateCard({ | ... | @@ -302,7 +302,7 @@ function AggregateCard({ |
| 302 | function MetricPair({ label, value }: { label: string; value: string }) { | 302 | function MetricPair({ label, value }: { label: string; value: string }) { |
| 303 | return ( | 303 | return ( |
| 304 | <div className="min-w-0"> | 304 | <div className="min-w-0"> |
| 305 | <div className="text-[9px] font-semibold uppercase tracking-[0.08em] text-muted-foreground/45"> | 305 | <div className="text-3xs font-semibold uppercase tracking-widest text-muted-foreground/45"> |
| 306 | {label} | 306 | {label} |
| 307 | </div> | 307 | </div> |
| 308 | <div className="truncate font-mono text-xs font-medium tabular-nums text-foreground/90"> | 308 | <div className="truncate font-mono text-xs font-medium tabular-nums text-foreground/90"> |
| ... | @@ -319,8 +319,8 @@ function HealthSource({ label, health }: { label: string; health: ResourceTeleme | ... | @@ -319,8 +319,8 @@ function HealthSource({ label, health }: { label: string; health: ResourceTeleme |
| 319 | return ( | 319 | return ( |
| 320 | <div className="flex items-start justify-between gap-4 border-t border-border/50 py-3 first:border-t-0"> | 320 | <div className="flex items-start justify-between gap-4 border-t border-border/50 py-3 first:border-t-0"> |
| 321 | <div className="min-w-0"> | 321 | <div className="min-w-0"> |
| 322 | <div className="text-[13px] font-medium text-foreground">{label}</div> | 322 | <div className="text-sm font-medium text-foreground">{label}</div> |
| 323 | <div className="mt-1 text-[11px] leading-relaxed text-muted-foreground/65"> | 323 | <div className="mt-1 text-2xs leading-relaxed text-muted-foreground/65"> |
| 324 | {expectedInBrowser | 324 | {expectedInBrowser |
| 325 | ? "Available when this page runs inside the desktop app." | 325 | ? "Available when this page runs inside the desktop app." |
| 326 | : Option.match(health.lastError, { | 326 | : Option.match(health.lastError, { |
| ... | @@ -356,10 +356,10 @@ function DetailRow({ | ... | @@ -356,10 +356,10 @@ function DetailRow({ |
| 356 | }) { | 356 | }) { |
| 357 | return ( | 357 | return ( |
| 358 | <div className="flex items-center justify-between gap-4 border-t border-border/50 py-2.5 first:border-t-0"> | 358 | <div className="flex items-center justify-between gap-4 border-t border-border/50 py-2.5 first:border-t-0"> |
| 359 | <span className="text-[11px] text-muted-foreground/75">{label}</span> | 359 | <span className="text-2xs text-muted-foreground/75">{label}</span> |
| 360 | <span | 360 | <span |
| 361 | className={cn( | 361 | className={cn( |
| 362 | "min-w-0 truncate text-right font-mono text-[11px] tabular-nums text-foreground/85", | 362 | "min-w-0 truncate text-right font-mono text-2xs tabular-nums text-foreground/85", |
| 363 | valueClassName, | 363 | valueClassName, |
| 364 | )} | 364 | )} |
| 365 | > | 365 | > |
| ... | @@ -405,7 +405,7 @@ function ResourceHistoryChart({ | ... | @@ -405,7 +405,7 @@ function ResourceHistoryChart({ |
| 405 | 405 | ||
| 406 | return ( | 406 | return ( |
| 407 | <div className="border-t border-border/60 px-4 py-4 sm:px-5"> | 407 | <div className="border-t border-border/60 px-4 py-4 sm:px-5"> |
| 408 | <div className="mb-3 flex flex-wrap items-center gap-x-4 gap-y-1 text-[10px] text-muted-foreground/65"> | 408 | <div className="mb-3 flex flex-wrap items-center gap-x-4 gap-y-1 text-3xs text-muted-foreground/65"> |
| 409 | <span className="inline-flex items-center gap-1.5"> | 409 | <span className="inline-flex items-center gap-1.5"> |
| 410 | <span className="h-1.5 w-3 rounded-full bg-foreground/70" /> CPU average | 410 | <span className="h-1.5 w-3 rounded-full bg-foreground/70" /> CPU average |
| 411 | </span> | 411 | </span> |
| ... | @@ -529,7 +529,7 @@ function ProcessActions({ | ... | @@ -529,7 +529,7 @@ function ProcessActions({ |
| 529 | onSignal: (process: ResourceTelemetryProcess, signal: ServerProcessSignal) => void; | 529 | onSignal: (process: ResourceTelemetryProcess, signal: ServerProcessSignal) => void; |
| 530 | }) { | 530 | }) { |
| 531 | if (!canSignalProcess(process)) { | 531 | if (!canSignalProcess(process)) { |
| 532 | return <span className="text-[10px] text-muted-foreground/35">—</span>; | 532 | return <span className="text-3xs text-muted-foreground/35">—</span>; |
| 533 | } | 533 | } |
| 534 | const isSignaling = signalingKeys.has(processIdentityKey(process)); | 534 | const isSignaling = signalingKeys.has(processIdentityKey(process)); |
| 535 | return ( | 535 | return ( |
| ... | @@ -586,7 +586,7 @@ function ProcessTable({ | ... | @@ -586,7 +586,7 @@ function ProcessTable({ |
| 586 | <col className="w-[6%]" /> | 586 | <col className="w-[6%]" /> |
| 587 | <col className="w-[4%]" /> | 587 | <col className="w-[4%]" /> |
| 588 | </colgroup> | 588 | </colgroup> |
| 589 | <thead className="sticky top-0 z-10 border-b border-border/60 bg-card text-[10px] uppercase tracking-[0.08em] text-muted-foreground/65"> | 589 | <thead className="sticky top-0 z-10 border-b border-border/60 bg-card text-3xs uppercase tracking-widest text-muted-foreground/65"> |
| 590 | <tr> | 590 | <tr> |
| 591 | <th className="px-4 py-2 font-semibold sm:pl-5">Process</th> | 591 | <th className="px-4 py-2 font-semibold sm:pl-5">Process</th> |
| 592 | <th className="px-3 py-2 font-semibold">Category</th> | 592 | <th className="px-3 py-2 font-semibold">Category</th> |
| ... | @@ -618,7 +618,7 @@ function ProcessTable({ | ... | @@ -618,7 +618,7 @@ function ProcessTable({ |
| 618 | onToggle={toggle} | 618 | onToggle={toggle} |
| 619 | /> | 619 | /> |
| 620 | </td> | 620 | </td> |
| 621 | <td className="truncate px-3 py-2 text-[11px] text-muted-foreground"> | 621 | <td className="truncate px-3 py-2 text-2xs text-muted-foreground"> |
| 622 | {categoryLabel(process.category)} | 622 | {categoryLabel(process.category)} |
| 623 | </td> | 623 | </td> |
| 624 | <td className="px-3 py-2 text-right font-mono tabular-nums"> | 624 | <td className="px-3 py-2 text-right font-mono tabular-nums"> |
| ... | @@ -689,7 +689,7 @@ function HistoryProcessTable({ | ... | @@ -689,7 +689,7 @@ function HistoryProcessTable({ |
| 689 | <col className="w-[7%]" /> | 689 | <col className="w-[7%]" /> |
| 690 | <col className="w-[5%]" /> | 690 | <col className="w-[5%]" /> |
| 691 | </colgroup> | 691 | </colgroup> |
| 692 | <thead className="sticky top-0 z-10 border-b border-border/60 bg-card text-[10px] uppercase tracking-[0.08em] text-muted-foreground/65"> | 692 | <thead className="sticky top-0 z-10 border-b border-border/60 bg-card text-3xs uppercase tracking-widest text-muted-foreground/65"> |
| 693 | <tr> | 693 | <tr> |
| 694 | <th className="px-4 py-2 font-semibold sm:pl-5">Process</th> | 694 | <th className="px-4 py-2 font-semibold sm:pl-5">Process</th> |
| 695 | <th className="px-3 py-2 font-semibold">Category</th> | 695 | <th className="px-3 py-2 font-semibold">Category</th> |
| ... | @@ -726,7 +726,7 @@ function HistoryProcessTable({ | ... | @@ -726,7 +726,7 @@ function HistoryProcessTable({ |
| 726 | </TooltipPopup> | 726 | </TooltipPopup> |
| 727 | </Tooltip> | 727 | </Tooltip> |
| 728 | </td> | 728 | </td> |
| 729 | <td className="truncate px-3 py-2 text-[11px] text-muted-foreground"> | 729 | <td className="truncate px-3 py-2 text-2xs text-muted-foreground"> |
| 730 | {categoryLabel(process.category)} | 730 | {categoryLabel(process.category)} |
| 731 | </td> | 731 | </td> |
| 732 | <td className="px-3 py-2 text-right font-mono tabular-nums"> | 732 | <td className="px-3 py-2 text-right font-mono tabular-nums"> |
| ... | @@ -771,7 +771,7 @@ function AttributionTable({ entries }: { entries: ReadonlyArray<ResourceAttribut | ... | @@ -771,7 +771,7 @@ function AttributionTable({ entries }: { entries: ReadonlyArray<ResourceAttribut |
| 771 | <col className="w-[10%]" /> | 771 | <col className="w-[10%]" /> |
| 772 | <col className="w-[12%]" /> | 772 | <col className="w-[12%]" /> |
| 773 | </colgroup> | 773 | </colgroup> |
| 774 | <thead className="border-b border-border/60 text-[10px] uppercase tracking-[0.08em] text-muted-foreground/65"> | 774 | <thead className="border-b border-border/60 text-3xs uppercase tracking-widest text-muted-foreground/65"> |
| 775 | <tr> | 775 | <tr> |
| 776 | <th className="px-4 py-2 font-semibold sm:pl-5">Component</th> | 776 | <th className="px-4 py-2 font-semibold sm:pl-5">Component</th> |
| 777 | <th className="px-3 py-2 font-semibold">Operation</th> | 777 | <th className="px-3 py-2 font-semibold">Operation</th> |
| ... | @@ -983,10 +983,10 @@ export function ResourceTelemetryDiagnostics({ | ... | @@ -983,10 +983,10 @@ export function ResourceTelemetryDiagnostics({ |
| 983 | </div> | 983 | </div> |
| 984 | } | 984 | } |
| 985 | > | 985 | > |
| 986 | <div className="overflow-hidden rounded-2xl border border-border/70 bg-card shadow-[0_1px_1px_rgb(0_0_0/0.03),0_8px_30px_rgb(0_0_0/0.035)]"> | 986 | <div className="overflow-hidden rounded-2xl border border-border/70 bg-card shadow-sm/5"> |
| 987 | <div className="flex flex-col gap-3 border-b border-border/60 bg-linear-to-r from-muted/45 via-muted/20 to-transparent px-4 py-4 sm:flex-row sm:items-center sm:justify-between sm:px-5"> | 987 | <div className="flex flex-col gap-3 border-b border-border/60 bg-linear-to-r from-muted/45 via-muted/20 to-transparent px-4 py-4 sm:flex-row sm:items-center sm:justify-between sm:px-5"> |
| 988 | <div> | 988 | <div> |
| 989 | <div className="text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground/70"> | 989 | <div className="text-3xs font-semibold uppercase tracking-widest text-muted-foreground/70"> |
| 990 | T3 system footprint | 990 | T3 system footprint |
| 991 | </div> | 991 | </div> |
| 992 | <p className="mt-1 max-w-xl text-xs leading-relaxed text-muted-foreground"> | 992 | <p className="mt-1 max-w-xl text-xs leading-relaxed text-muted-foreground"> |
| ... | @@ -994,7 +994,7 @@ export function ResourceTelemetryDiagnostics({ | ... | @@ -994,7 +994,7 @@ export function ResourceTelemetryDiagnostics({ |
| 994 | the monitor itself. | 994 | the monitor itself. |
| 995 | </p> | 995 | </p> |
| 996 | </div> | 996 | </div> |
| 997 | <div className="flex items-center gap-2 text-[10px] text-muted-foreground/65"> | 997 | <div className="flex items-center gap-2 text-3xs text-muted-foreground/65"> |
| 998 | <span className="size-1.5 rounded-full bg-success" /> | 998 | <span className="size-1.5 rounded-full bg-success" /> |
| 999 | Sampling every {snapshot ? formatSampleInterval(snapshot.sampleIntervalMs) : "..."} | 999 | Sampling every {snapshot ? formatSampleInterval(snapshot.sampleIntervalMs) : "..."} |
| 1000 | </div> | 1000 | </div> |
| ... | @@ -1091,9 +1091,9 @@ export function ResourceTelemetryDiagnostics({ | ... | @@ -1091,9 +1091,9 @@ export function ResourceTelemetryDiagnostics({ |
| 1091 | ) : null | 1091 | ) : null |
| 1092 | } | 1092 | } |
| 1093 | > | 1093 | > |
| 1094 | <div className="grid overflow-hidden rounded-2xl border border-border/70 bg-card shadow-[0_1px_1px_rgb(0_0_0/0.03)] md:grid-cols-2 md:divide-x md:divide-border/60"> | 1094 | <div className="grid overflow-hidden rounded-2xl border border-border/70 bg-card shadow-xs/5 md:grid-cols-2 md:divide-x md:divide-border/60"> |
| 1095 | <div className="px-4 py-4 sm:px-5"> | 1095 | <div className="px-4 py-4 sm:px-5"> |
| 1096 | <div className="mb-3 flex items-center gap-2 text-[10px] font-semibold uppercase tracking-[0.12em] text-muted-foreground/70"> | 1096 | <div className="mb-3 flex items-center gap-2 text-3xs font-semibold uppercase tracking-widest text-muted-foreground/70"> |
| 1097 | <span className="flex size-6 items-center justify-center rounded-md bg-muted/60"> | 1097 | <span className="flex size-6 items-center justify-center rounded-md bg-muted/60"> |
| 1098 | <BatteryIcon className="size-3.5" /> | 1098 | <BatteryIcon className="size-3.5" /> |
| 1099 | </span> | 1099 | </span> |
| ... | @@ -1150,10 +1150,10 @@ export function ResourceTelemetryDiagnostics({ | ... | @@ -1150,10 +1150,10 @@ export function ResourceTelemetryDiagnostics({ |
| 1150 | </> | 1150 | </> |
| 1151 | ) : ( | 1151 | ) : ( |
| 1152 | <div className="rounded-xl border border-dashed border-border/70 bg-muted/20 px-4 py-5"> | 1152 | <div className="rounded-xl border border-dashed border-border/70 bg-muted/20 px-4 py-5"> |
| 1153 | <div className="text-[13px] font-medium text-foreground"> | 1153 | <div className="text-sm font-medium text-foreground"> |
| 1154 | Desktop host signals not connected | 1154 | Desktop host signals not connected |
| 1155 | </div> | 1155 | </div> |
| 1156 | <p className="mt-1.5 max-w-sm text-[11px] leading-relaxed text-muted-foreground/70"> | 1156 | <p className="mt-1.5 max-w-sm text-2xs leading-relaxed text-muted-foreground/70"> |
| 1157 | Power, idle, lock, and thermal state are supplied by the desktop host. Process | 1157 | Power, idle, lock, and thermal state are supplied by the desktop host. Process |
| 1158 | telemetry remains fully active in this browser session. | 1158 | telemetry remains fully active in this browser session. |
| 1159 | </p> | 1159 | </p> |
| ... | @@ -1161,7 +1161,7 @@ export function ResourceTelemetryDiagnostics({ | ... | @@ -1161,7 +1161,7 @@ export function ResourceTelemetryDiagnostics({ |
| 1161 | )} | 1161 | )} |
| 1162 | </div> | 1162 | </div> |
| 1163 | <div className="border-t border-border/60 px-4 py-4 md:border-t-0 sm:px-5"> | 1163 | <div className="border-t border-border/60 px-4 py-4 md:border-t-0 sm:px-5"> |
| 1164 | <div className="mb-3 flex items-center gap-2 text-[10px] font-semibold uppercase tracking-[0.12em] text-muted-foreground/70"> | 1164 | <div className="mb-3 flex items-center gap-2 text-3xs font-semibold uppercase tracking-widest text-muted-foreground/70"> |
| 1165 | <span className="flex size-6 items-center justify-center rounded-md bg-muted/60"> | 1165 | <span className="flex size-6 items-center justify-center rounded-md bg-muted/60"> |
| 1166 | <GaugeIcon className="size-3.5" /> | 1166 | <GaugeIcon className="size-3.5" /> |
| 1167 | </span> | 1167 | </span> |
| ... | @@ -1228,7 +1228,7 @@ export function ResourceTelemetryDiagnostics({ | ... | @@ -1228,7 +1228,7 @@ export function ResourceTelemetryDiagnostics({ |
| 1228 | </div> | 1228 | </div> |
| 1229 | } | 1229 | } |
| 1230 | > | 1230 | > |
| 1231 | <div className="overflow-hidden rounded-2xl border border-border/70 bg-card shadow-[0_1px_1px_rgb(0_0_0/0.03)]"> | 1231 | <div className="overflow-hidden rounded-2xl border border-border/70 bg-card shadow-xs/5"> |
| 1232 | {history.error ? ( | 1232 | {history.error ? ( |
| 1233 | <div className="flex items-start gap-2 border-b border-destructive/20 bg-destructive/5 px-4 py-3 text-xs text-destructive sm:px-5"> | 1233 | <div className="flex items-start gap-2 border-b border-destructive/20 bg-destructive/5 px-4 py-3 text-xs text-destructive sm:px-5"> |
| 1234 | <AlertTriangleIcon className="mt-0.5 size-3.5 shrink-0" /> | 1234 | <AlertTriangleIcon className="mt-0.5 size-3.5 shrink-0" /> |
| ... | @@ -1245,13 +1245,13 @@ export function ResourceTelemetryDiagnostics({ | ... | @@ -1245,13 +1245,13 @@ export function ResourceTelemetryDiagnostics({ |
| 1245 | icon={<CpuIcon className="size-4 text-muted-foreground" />} | 1245 | icon={<CpuIcon className="size-4 text-muted-foreground" />} |
| 1246 | headerAction={ | 1246 | headerAction={ |
| 1247 | snapshot ? ( | 1247 | snapshot ? ( |
| 1248 | <span className="text-[10px] text-muted-foreground/55"> | 1248 | <span className="text-3xs text-muted-foreground/55"> |
| 1249 | Identity: <span className="font-mono">PID + start time</span> | 1249 | Identity: <span className="font-mono">PID + start time</span> |
| 1250 | </span> | 1250 | </span> |
| 1251 | ) : null | 1251 | ) : null |
| 1252 | } | 1252 | } |
| 1253 | > | 1253 | > |
| 1254 | <div className="overflow-hidden rounded-2xl border border-border/70 bg-card shadow-[0_1px_1px_rgb(0_0_0/0.03)]"> | 1254 | <div className="overflow-hidden rounded-2xl border border-border/70 bg-card shadow-xs/5"> |
| 1255 | <ProcessTable | 1255 | <ProcessTable |
| 1256 | processes={snapshot?.processes ?? []} | 1256 | processes={snapshot?.processes ?? []} |
| 1257 | signalingKeys={signalingKeys} | 1257 | signalingKeys={signalingKeys} |
| ... | @@ -1264,11 +1264,11 @@ export function ResourceTelemetryDiagnostics({ | ... | @@ -1264,11 +1264,11 @@ export function ResourceTelemetryDiagnostics({ |
| 1264 | title="Instrumented application I/O" | 1264 | title="Instrumented application I/O" |
| 1265 | icon={<DatabaseIcon className="size-4 text-muted-foreground" />} | 1265 | icon={<DatabaseIcon className="size-4 text-muted-foreground" />} |
| 1266 | headerAction={ | 1266 | headerAction={ |
| 1267 | <span className="text-[10px] text-muted-foreground/55">Logical bytes by operation</span> | 1267 | <span className="text-3xs text-muted-foreground/55">Logical bytes by operation</span> |
| 1268 | } | 1268 | } |
| 1269 | > | 1269 | > |
| 1270 | <div className="overflow-hidden rounded-2xl border border-border/70 bg-card shadow-[0_1px_1px_rgb(0_0_0/0.03)]"> | 1270 | <div className="overflow-hidden rounded-2xl border border-border/70 bg-card shadow-xs/5"> |
| 1271 | <div className="bg-muted/15 px-4 py-3 text-[11px] leading-relaxed text-muted-foreground sm:px-5"> | 1271 | <div className="bg-muted/15 px-4 py-3 text-2xs leading-relaxed text-muted-foreground sm:px-5"> |
| 1272 | Native counters identify which process is reading or writing. These application-level | 1272 | Native counters identify which process is reading or writing. These application-level |
| 1273 | counters identify known T3 operations so process spikes can be correlated with specific | 1273 | counters identify known T3 operations so process spikes can be correlated with specific |
| 1274 | persistence and logging paths. | 1274 | persistence and logging paths. |
apps/web/src/components/settings/SettingsPanels.tsx+4-4| ... | @@ -264,7 +264,7 @@ function AboutVersionTitle() { | ... | @@ -264,7 +264,7 @@ function AboutVersionTitle() { |
| 264 | return ( | 264 | return ( |
| 265 | <span className="inline-flex items-baseline gap-2"> | 265 | <span className="inline-flex items-baseline gap-2"> |
| 266 | <span>Version</span> | 266 | <span>Version</span> |
| 267 | <code className="text-[11px] font-medium text-muted-foreground">{APP_VERSION}</code> | 267 | <code className="text-2xs font-medium text-muted-foreground">{APP_VERSION}</code> |
| 268 | </span> | 268 | </span> |
| 269 | ); | 269 | ); |
| 270 | } | 270 | } |
| ... | @@ -1368,8 +1368,8 @@ export function AppearanceSettingsPanel() { | ... | @@ -1368,8 +1368,8 @@ export function AppearanceSettingsPanel() { |
| 1368 | : "flex shrink-0 gap-1" | 1368 | : "flex shrink-0 gap-1" |
| 1369 | } | 1369 | } |
| 1370 | > | 1370 | > |
| 1371 | <span className="size-2 rounded-full bg-[var(--diff-deletion)]" /> | 1371 | <span className="size-2 rounded-full bg-diff-deletion" /> |
| 1372 | <span className="size-2 rounded-full bg-[var(--diff-addition)]" /> | 1372 | <span className="size-2 rounded-full bg-diff-addition" /> |
| 1373 | </span> | 1373 | </span> |
| 1374 | <SelectValue> | 1374 | <SelectValue> |
| 1375 | {settings.diffColorScheme === "blue-orange" ? "Blue & orange" : "Red & green"} | 1375 | {settings.diffColorScheme === "blue-orange" ? "Blue & orange" : "Red & green"} |
| ... | @@ -2046,7 +2046,7 @@ function LegacyFeaturesSection() { | ... | @@ -2046,7 +2046,7 @@ function LegacyFeaturesSection() { |
| 2046 | <section id="legacy-features" ref={targetRef} tabIndex={-1} className="space-y-2.5"> | 2046 | <section id="legacy-features" ref={targetRef} tabIndex={-1} className="space-y-2.5"> |
| 2047 | <Collapsible open={open} onOpenChange={setOpen}> | 2047 | <Collapsible open={open} onOpenChange={setOpen}> |
| 2048 | <CollapsibleTrigger className="group flex min-h-8 w-full items-center gap-2 px-3 sm:px-4"> | 2048 | <CollapsibleTrigger className="group flex min-h-8 w-full items-center gap-2 px-3 sm:px-4"> |
| 2049 | <h2 className="text-sm font-normal tracking-[-0.005em] text-foreground/70 transition-colors group-hover:text-foreground"> | 2049 | <h2 className="text-sm font-normal text-foreground/70 transition-colors group-hover:text-foreground"> |
| 2050 | Legacy features | 2050 | Legacy features |
| 2051 | </h2> | 2051 | </h2> |
| 2052 | <ChevronRightIcon className="size-4 text-muted-foreground transition-transform duration-200 group-data-panel-open:rotate-90" /> | 2052 | <ChevronRightIcon className="size-4 text-muted-foreground transition-transform duration-200 group-data-panel-open:rotate-90" /> |
apps/web/src/components/settings/SettingsSidebarNav.tsx+1-1| ... | @@ -311,7 +311,7 @@ export function SettingsSidebarNav({ pathname }: { pathname: string }) { | ... | @@ -311,7 +311,7 @@ export function SettingsSidebarNav({ pathname }: { pathname: string }) { |
| 311 | <span className="block truncate text-sm font-medium text-sidebar-foreground"> | 311 | <span className="block truncate text-sm font-medium text-sidebar-foreground"> |
| 312 | {item.title} | 312 | {item.title} |
| 313 | </span> | 313 | </span> |
| 314 | <span className="block truncate text-[11px] text-sidebar-muted-foreground/75"> | 314 | <span className="block truncate text-2xs text-sidebar-muted-foreground/75"> |
| 315 | {SETTINGS_SECTION_LABELS[item.to]} | 315 | {SETTINGS_SECTION_LABELS[item.to]} |
| 316 | </span> | 316 | </span> |
| 317 | </span> | 317 | </span> |
apps/web/src/components/settings/SnapShotSetupDialog.tsx+2-6| ... | @@ -268,9 +268,7 @@ export function SnapShotSetupDialog({ | ... | @@ -268,9 +268,7 @@ export function SnapShotSetupDialog({ |
| 268 | permissions={[ | 268 | permissions={[ |
| 269 | { | 269 | { |
| 270 | id: "screenRecording", | 270 | id: "screenRecording", |
| 271 | icon: ( | 271 | icon: <MacScreenRecordingIcon className="size-8 shrink-0 drop-shadow-sm" />, |
| 272 | <MacScreenRecordingIcon className="size-8 shrink-0 drop-shadow-[0_1px_1px_#0005]" /> | ||
| 273 | ), | ||
| 274 | title: "Screen Recording", | 272 | title: "Screen Recording", |
| 275 | description: "Capture the window you're using.", | 273 | description: "Capture the window you're using.", |
| 276 | granted: macPermissions.screenRecording, | 274 | granted: macPermissions.screenRecording, |
| ... | @@ -278,9 +276,7 @@ export function SnapShotSetupDialog({ | ... | @@ -278,9 +276,7 @@ export function SnapShotSetupDialog({ |
| 278 | }, | 276 | }, |
| 279 | { | 277 | { |
| 280 | id: "accessibility", | 278 | id: "accessibility", |
| 281 | icon: ( | 279 | icon: <MacAccessibilityIcon className="size-8 shrink-0 drop-shadow-sm" />, |
| 282 | <MacAccessibilityIcon className="size-8 shrink-0 drop-shadow-[0_1px_1px_#0005]" /> | ||
| 283 | ), | ||
| 284 | title: "Accessibility", | 280 | title: "Accessibility", |
| 285 | description: includeAccessibility | 281 | description: includeAccessibility |
| 286 | ? "Include text and controls from the captured app." | 282 | ? "Include text and controls from the captured app." |
apps/web/src/components/settings/SourceControlSettings.tsx+4-6| ... | @@ -242,8 +242,8 @@ function itemSummary({ | ... | @@ -242,8 +242,8 @@ function itemSummary({ |
| 242 | return ( | 242 | return ( |
| 243 | <span> | 243 | <span> |
| 244 | {item.label} is not authenticated on this server. Sign in or configure credentials using | 244 | {item.label} is not authenticated on this server. Sign in or configure credentials using |
| 245 | the <code className="rounded bg-muted px-1 py-px text-[11px]">{item.executable}</code>{" "} | 245 | the <code className="rounded bg-muted px-1 py-px text-2xs">{item.executable}</code> tool |
| 246 | tool on the server host to enable change request features. | 246 | on the server host to enable change request features. |
| 247 | </span> | 247 | </span> |
| 248 | ); | 248 | ); |
| 249 | } | 249 | } |
| ... | @@ -294,9 +294,7 @@ function DiscoveryItemRow({ | ... | @@ -294,9 +294,7 @@ function DiscoveryItemRow({ |
| 294 | <div className="min-w-0 flex-1 space-y-1"> | 294 | <div className="min-w-0 flex-1 space-y-1"> |
| 295 | <div className="flex min-w-0 flex-wrap items-center gap-2"> | 295 | <div className="flex min-w-0 flex-wrap items-center gap-2"> |
| 296 | <SourceControlItemMark item={item} /> | 296 | <SourceControlItemMark item={item} /> |
| 297 | <span className="truncate text-sm font-medium tracking-[-0.005em] text-foreground"> | 297 | <span className="truncate text-sm font-medium text-foreground">{item.label}</span> |
| 298 | {item.label} | ||
| 299 | </span> | ||
| 300 | {version ? <code className="text-xs text-muted-foreground">{version}</code> : null} | 298 | {version ? <code className="text-xs text-muted-foreground">{version}</code> : null} |
| 301 | {isVcsNotReady(item) ? ( | 299 | {isVcsNotReady(item) ? ( |
| 302 | <Badge variant="warning" size="sm"> | 300 | <Badge variant="warning" size="sm"> |
| ... | @@ -309,7 +307,7 @@ function DiscoveryItemRow({ | ... | @@ -309,7 +307,7 @@ function DiscoveryItemRow({ |
| 309 | </Badge> | 307 | </Badge> |
| 310 | ) : null} | 308 | ) : null} |
| 311 | </div> | 309 | </div> |
| 312 | <p className="flex min-w-0 flex-wrap items-center gap-x-1 text-[13px] leading-[1.45] text-muted-foreground/80"> | 310 | <p className="flex min-w-0 flex-wrap items-center gap-x-1 text-xs leading-normal text-muted-foreground/80"> |
| 313 | {itemSummary({ item, auth, authAccount })} | 311 | {itemSummary({ item, auth, authAccount })} |
| 314 | </p> | 312 | </p> |
| 315 | </div> | 313 | </div> |
apps/web/src/components/settings/ThemeColorPicker.tsx+4-4| ... | @@ -171,7 +171,7 @@ function ThemeColorPickerPanel({ | ... | @@ -171,7 +171,7 @@ function ThemeColorPickerPanel({ |
| 171 | <div className="flex items-center justify-between border-b border-border/70 px-4 py-3"> | 171 | <div className="flex items-center justify-between border-b border-border/70 px-4 py-3"> |
| 172 | <div className="min-w-0"> | 172 | <div className="min-w-0"> |
| 173 | <p className="truncate text-xs font-semibold text-foreground">{label}</p> | 173 | <p className="truncate text-xs font-semibold text-foreground">{label}</p> |
| 174 | <p className="text-[11px] text-muted-foreground">Choose a color</p> | 174 | <p className="text-2xs text-muted-foreground">Choose a color</p> |
| 175 | </div> | 175 | </div> |
| 176 | <span | 176 | <span |
| 177 | className="size-7 shrink-0 rounded-full shadow-sm" | 177 | className="size-7 shrink-0 rounded-full shadow-sm" |
| ... | @@ -193,7 +193,7 @@ function ThemeColorPickerPanel({ | ... | @@ -193,7 +193,7 @@ function ThemeColorPickerPanel({ |
| 193 | /> | 193 | /> |
| 194 | <div className="grid grid-cols-[1fr_1.2fr] gap-2"> | 194 | <div className="grid grid-cols-[1fr_1.2fr] gap-2"> |
| 195 | <label className="grid min-w-0 gap-1"> | 195 | <label className="grid min-w-0 gap-1"> |
| 196 | <span className="px-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground"> | 196 | <span className="px-1 text-3xs font-semibold uppercase tracking-widest text-muted-foreground"> |
| 197 | HEX | 197 | HEX |
| 198 | </span> | 198 | </span> |
| 199 | <span className="flex min-w-0 items-center gap-2 rounded-lg border border-input bg-background px-2 focus-within:border-ring"> | 199 | <span className="flex min-w-0 items-center gap-2 rounded-lg border border-input bg-background px-2 focus-within:border-ring"> |
| ... | @@ -219,7 +219,7 @@ function ThemeColorPickerPanel({ | ... | @@ -219,7 +219,7 @@ function ThemeColorPickerPanel({ |
| 219 | </span> | 219 | </span> |
| 220 | </label> | 220 | </label> |
| 221 | <label className="grid min-w-0 gap-1"> | 221 | <label className="grid min-w-0 gap-1"> |
| 222 | <span className="px-1 text-[10px] font-semibold uppercase tracking-[0.08em] text-muted-foreground"> | 222 | <span className="px-1 text-3xs font-semibold uppercase tracking-widest text-muted-foreground"> |
| 223 | RGB | 223 | RGB |
| 224 | </span> | 224 | </span> |
| 225 | <span className="flex min-w-0 items-center rounded-lg border border-input bg-background px-2 focus-within:border-ring"> | 225 | <span className="flex min-w-0 items-center rounded-lg border border-input bg-background px-2 focus-within:border-ring"> |
| ... | @@ -323,7 +323,7 @@ export const ThemeColorField = memo(function ThemeColorField({ | ... | @@ -323,7 +323,7 @@ export const ThemeColorField = memo(function ThemeColorField({ |
| 323 | <div | 323 | <div |
| 324 | className={cn( | 324 | className={cn( |
| 325 | "flex min-h-11 min-w-0 items-center gap-2 rounded-lg px-2 py-1.5 transition-[background-color,box-shadow]", | 325 | "flex min-h-11 min-w-0 items-center gap-2 rounded-lg px-2 py-1.5 transition-[background-color,box-shadow]", |
| 326 | selected && "bg-accent/60 shadow-[inset_0_0_0_1px_var(--ring)]", | 326 | selected && "bg-accent/60 inset-ring inset-ring-ring", |
| 327 | )} | 327 | )} |
| 328 | data-theme-color-role={role} | 328 | data-theme-color-role={role} |
| 329 | > | 329 | > |
apps/web/src/components/settings/ThemeImportDialog.tsx+4-4| ... | @@ -111,12 +111,12 @@ function ThemeJsonEditor({ | ... | @@ -111,12 +111,12 @@ function ThemeJsonEditor({ |
| 111 | }, []); | 111 | }, []); |
| 112 | 112 | ||
| 113 | return ( | 113 | return ( |
| 114 | <div className="relative overflow-hidden rounded-xl border border-input bg-background shadow-xs/5 focus-within:border-ring focus-within:ring-[3px] focus-within:ring-ring/24"> | 114 | <div className="relative overflow-hidden rounded-xl border border-input bg-background shadow-xs/5 focus-within:border-ring focus-within:ring-3 focus-within:ring-ring/24"> |
| 115 | {isPlainText ? null : ( | 115 | {isPlainText ? null : ( |
| 116 | <pre | 116 | <pre |
| 117 | ref={highlightRef} | 117 | ref={highlightRef} |
| 118 | aria-hidden | 118 | aria-hidden |
| 119 | className="pointer-events-none absolute inset-0 m-0 overflow-hidden whitespace-pre-wrap break-words p-3 font-mono text-[12px] leading-5 text-foreground" | 119 | className="pointer-events-none absolute inset-0 m-0 overflow-hidden whitespace-pre-wrap break-words p-3 font-mono text-xs leading-5 text-foreground" |
| 120 | > | 120 | > |
| 121 | <code dangerouslySetInnerHTML={{ __html: highlightedJson }} /> | 121 | <code dangerouslySetInnerHTML={{ __html: highlightedJson }} /> |
| 122 | </pre> | 122 | </pre> |
| ... | @@ -124,7 +124,7 @@ function ThemeJsonEditor({ | ... | @@ -124,7 +124,7 @@ function ThemeJsonEditor({ |
| 124 | <textarea | 124 | <textarea |
| 125 | aria-label="Theme JSON" | 125 | aria-label="Theme JSON" |
| 126 | className={cn( | 126 | className={cn( |
| 127 | "relative z-10 block min-h-44 w-full resize-y overflow-auto bg-transparent p-3 font-mono text-[12px] leading-5 caret-foreground outline-none placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground", | 127 | "relative z-10 block min-h-44 w-full resize-y overflow-auto bg-transparent p-3 font-mono text-xs leading-5 caret-foreground outline-none placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground", |
| 128 | isPlainText ? "text-foreground" : "text-transparent", | 128 | isPlainText ? "text-foreground" : "text-transparent", |
| 129 | )} | 129 | )} |
| 130 | id={id} | 130 | id={id} |
| ... | @@ -438,7 +438,7 @@ export function ThemeImportDialog({ | ... | @@ -438,7 +438,7 @@ export function ThemeImportDialog({ |
| 438 | 438 | ||
| 439 | <div className="flex items-center gap-3" aria-hidden> | 439 | <div className="flex items-center gap-3" aria-hidden> |
| 440 | <div className="h-px flex-1 bg-border" /> | 440 | <div className="h-px flex-1 bg-border" /> |
| 441 | <span className="text-muted-foreground text-[11px] uppercase tracking-wider"> | 441 | <span className="text-muted-foreground text-2xs uppercase tracking-wider"> |
| 442 | or import a file | 442 | or import a file |
| 443 | </span> | 443 | </span> |
| 444 | <div className="h-px flex-1 bg-border" /> | 444 | <div className="h-px flex-1 bg-border" /> |
apps/web/src/components/settings/ThemeSettings.tsx+5-5| ... | @@ -231,12 +231,12 @@ function ThemeLibraryCard({ | ... | @@ -231,12 +231,12 @@ function ThemeLibraryCard({ |
| 231 | </button> | 231 | </button> |
| 232 | </ThemeVariantTooltip> | 232 | </ThemeVariantTooltip> |
| 233 | <span | 233 | <span |
| 234 | className="pointer-events-none absolute bottom-0 left-1/2 inline-flex max-w-24 -translate-x-1/2 items-center gap-1 text-[11px] font-medium text-foreground" | 234 | className="pointer-events-none absolute bottom-0 left-1/2 inline-flex max-w-24 -translate-x-1/2 items-center gap-1 text-2xs font-medium text-foreground" |
| 235 | style={{ marginLeft: rootOffsetX }} | 235 | style={{ marginLeft: rootOffsetX }} |
| 236 | > | 236 | > |
| 237 | <span className="truncate">{selected.option.label}</span> | 237 | <span className="truncate">{selected.option.label}</span> |
| 238 | {options.length > 1 ? ( | 238 | {options.length > 1 ? ( |
| 239 | <span className="shrink-0 rounded-full bg-muted px-1 text-[9px] text-muted-foreground"> | 239 | <span className="shrink-0 rounded-full bg-muted px-1 text-3xs text-muted-foreground"> |
| 240 | +{options.length - 1} | 240 | +{options.length - 1} |
| 241 | </span> | 241 | </span> |
| 242 | ) : null} | 242 | ) : null} |
| ... | @@ -256,7 +256,7 @@ function ThemeLibraryCard({ | ... | @@ -256,7 +256,7 @@ function ThemeLibraryCard({ |
| 256 | aria-label={`Use ${option.label} for ${mode} mode${optionIsActive ? ", currently active" : ""}`} | 256 | aria-label={`Use ${option.label} for ${mode} mode${optionIsActive ? ", currently active" : ""}`} |
| 257 | aria-pressed={optionIsActive} | 257 | aria-pressed={optionIsActive} |
| 258 | className={cn( | 258 | className={cn( |
| 259 | "absolute left-1/2 top-1 z-30 flex size-7 items-center justify-center rounded-full bg-background shadow-sm outline-none transition-[transform,opacity] duration-200 ease-out motion-reduce:transition-none focus-visible:ring-2 focus-visible:ring-ring", | 259 | "absolute left-1/2 top-1 z-30 flex size-7 items-center justify-center rounded-full bg-background shadow-sm outline-none transition-[opacity,transform] duration-200 ease-out motion-reduce:transition-none focus-visible:ring-2 focus-visible:ring-ring", |
| 260 | optionIsActive ? "ring-2 ring-ring" : "ring-1 ring-border/70", | 260 | optionIsActive ? "ring-2 ring-ring" : "ring-1 ring-border/70", |
| 261 | )} | 261 | )} |
| 262 | style={{ | 262 | style={{ |
| ... | @@ -884,12 +884,12 @@ export function ThemeLibrary({ | ... | @@ -884,12 +884,12 @@ export function ThemeLibrary({ |
| 884 | 884 | ||
| 885 | return ( | 885 | return ( |
| 886 | <div className="space-y-3"> | 886 | <div className="space-y-3"> |
| 887 | <h3 className="px-3 text-sm font-normal tracking-[-0.005em] text-foreground/70 sm:px-4"> | 887 | <h3 className="px-3 text-sm font-normal text-foreground/70 sm:px-4"> |
| 888 | {searchableSetting("color-scheme").title} | 888 | {searchableSetting("color-scheme").title} |
| 889 | </h3> | 889 | </h3> |
| 890 | {renderModeTiles()} | 890 | {renderModeTiles()} |
| 891 | <div className="flex min-h-8 flex-wrap items-center justify-between gap-3 px-3 pt-2 sm:px-4"> | 891 | <div className="flex min-h-8 flex-wrap items-center justify-between gap-3 px-3 pt-2 sm:px-4"> |
| 892 | <h3 className="text-sm font-normal tracking-[-0.005em] text-foreground/70"> | 892 | <h3 className="text-sm font-normal text-foreground/70"> |
| 893 | {searchableSetting("theme").title} | 893 | {searchableSetting("theme").title} |
| 894 | </h3> | 894 | </h3> |
| 895 | <div className="flex flex-wrap items-center justify-end gap-2"> | 895 | <div className="flex flex-wrap items-center justify-end gap-2"> |
apps/web/src/components/settings/ThemeWireframe.tsx+2-2| ... | @@ -66,7 +66,7 @@ function ThemeWireframePane({ | ... | @@ -66,7 +66,7 @@ function ThemeWireframePane({ |
| 66 | 66 | ||
| 67 | {/* Composer */} | 67 | {/* Composer */} |
| 68 | <span | 68 | <span |
| 69 | className="absolute bottom-[8%] left-[26%] right-[6%] flex h-[15%] items-center justify-between rounded-md px-[2.5%]" | 69 | className="absolute bottom-[8%] left-[26%] right-[6%] flex h-[15%] items-center justify-between rounded-md px-1" |
| 70 | style={{ | 70 | style={{ |
| 71 | backgroundColor: colors.surface, | 71 | backgroundColor: colors.surface, |
| 72 | boxShadow: `inset 0 0 0 1px ${line}`, | 72 | boxShadow: `inset 0 0 0 1px ${line}`, |
| ... | @@ -92,7 +92,7 @@ function ThemeWireframePane({ | ... | @@ -92,7 +92,7 @@ function ThemeWireframePane({ |
| 92 | > | 92 | > |
| 93 | {[0, 1, 2].map((row) => ( | 93 | {[0, 1, 2].map((row) => ( |
| 94 | <span | 94 | <span |
| 95 | className="absolute left-[11%] right-[11%] flex items-center gap-[5%]" | 95 | className="absolute left-[11%] right-[11%] flex items-center gap-1" |
| 96 | key={row} | 96 | key={row} |
| 97 | style={{ top: `${10 + row * 30}%`, height: "20%" }} | 97 | style={{ top: `${10 + row * 30}%`, height: "20%" }} |
| 98 | > | 98 | > |
apps/web/src/components/settings/settingsLayout.tsx+4-4| ... | @@ -202,7 +202,7 @@ export function SettingsSection({ | ... | @@ -202,7 +202,7 @@ export function SettingsSection({ |
| 202 | className="flex min-h-7 items-start justify-between gap-4 px-3 sm:px-4" | 202 | className="flex min-h-7 items-start justify-between gap-4 px-3 sm:px-4" |
| 203 | > | 203 | > |
| 204 | <div className="min-w-0"> | 204 | <div className="min-w-0"> |
| 205 | <h2 className="flex min-h-7 items-center gap-2 text-sm font-normal tracking-[-0.005em] text-foreground/70"> | 205 | <h2 className="flex min-h-7 items-center gap-2 text-sm font-normal text-foreground/70"> |
| 206 | {icon} | 206 | {icon} |
| 207 | {title} | 207 | {title} |
| 208 | </h2> | 208 | </h2> |
| ... | @@ -228,7 +228,7 @@ export function SettingsUnavailableGroup({ | ... | @@ -228,7 +228,7 @@ export function SettingsUnavailableGroup({ |
| 228 | 228 | ||
| 229 | return ( | 229 | return ( |
| 230 | <div className="border-border/60 bg-muted/20 py-1.5"> | 230 | <div className="border-border/60 bg-muted/20 py-1.5"> |
| 231 | <div className="flex items-start gap-2 px-3 py-2 text-[12px] leading-relaxed text-muted-foreground sm:px-4"> | 231 | <div className="flex items-start gap-2 px-3 py-2 text-xs leading-relaxed text-muted-foreground sm:px-4"> |
| 232 | <InfoIcon className="mt-0.5 size-3.5 shrink-0 text-warning" /> | 232 | <InfoIcon className="mt-0.5 size-3.5 shrink-0 text-warning" /> |
| 233 | <p>{message}</p> | 233 | <p>{message}</p> |
| 234 | </div> | 234 | </div> |
| ... | @@ -435,7 +435,7 @@ export function SettingsRow({ | ... | @@ -435,7 +435,7 @@ export function SettingsRow({ |
| 435 | <div className="flex flex-col gap-3 @min-[32rem]/settings-row:grid @min-[32rem]/settings-row:grid-cols-[minmax(0,1fr)_minmax(10rem,auto)] @min-[32rem]/settings-row:items-center @min-[32rem]/settings-row:gap-8"> | 435 | <div className="flex flex-col gap-3 @min-[32rem]/settings-row:grid @min-[32rem]/settings-row:grid-cols-[minmax(0,1fr)_minmax(10rem,auto)] @min-[32rem]/settings-row:items-center @min-[32rem]/settings-row:gap-8"> |
| 436 | <div className="min-w-0 flex-1 space-y-1"> | 436 | <div className="min-w-0 flex-1 space-y-1"> |
| 437 | <div className="flex min-h-5 items-center gap-1.5"> | 437 | <div className="flex min-h-5 items-center gap-1.5"> |
| 438 | <h3 className="text-sm font-medium tracking-[-0.005em] text-foreground">{title}</h3> | 438 | <h3 className="text-sm font-medium text-foreground">{title}</h3> |
| 439 | {renderedInheritance ? ( | 439 | {renderedInheritance ? ( |
| 440 | <span className="inline-flex h-5 w-5 shrink-0 items-center justify-center"> | 440 | <span className="inline-flex h-5 w-5 shrink-0 items-center justify-center"> |
| 441 | {renderedInheritance} | 441 | {renderedInheritance} |
| ... | @@ -446,7 +446,7 @@ export function SettingsRow({ | ... | @@ -446,7 +446,7 @@ export function SettingsRow({ |
| 446 | </span> | 446 | </span> |
| 447 | </div> | 447 | </div> |
| 448 | {description ? ( | 448 | {description ? ( |
| 449 | <p className="max-w-xl text-[13px] leading-[1.45] text-muted-foreground/80"> | 449 | <p className="max-w-xl text-xs leading-normal text-muted-foreground/80"> |
| 450 | {description} | 450 | {description} |
| 451 | </p> | 451 | </p> |
| 452 | ) : null} | 452 | ) : null} |
apps/web/src/components/sidebar/SidebarProviderUpdatePill.tsx+2-2| ... | @@ -125,7 +125,7 @@ export function SidebarProviderUpdatePill() { | ... | @@ -125,7 +125,7 @@ export function SidebarProviderUpdatePill() { |
| 125 | 125 | ||
| 126 | return ( | 126 | return ( |
| 127 | <div | 127 | <div |
| 128 | className={`group/provider-update relative flex min-h-7 w-full shrink-0 items-center overflow-hidden rounded-lg text-[11px] leading-4 font-medium transform-gpu transition-all duration-180 ease-[cubic-bezier(0.22,1,0.36,1)] will-change-transform ${ | 128 | className={`group/provider-update relative flex min-h-7 w-full shrink-0 items-center overflow-hidden rounded-lg text-2xs leading-4 font-medium transform-gpu transition-all duration-180 ease-drawer will-change-transform ${ |
| 129 | PROVIDER_UPDATE_PILL_STYLES[displayedView.tone] | 129 | PROVIDER_UPDATE_PILL_STYLES[displayedView.tone] |
| 130 | } ${ | 130 | } ${ |
| 131 | exitingKey === displayedView.key | 131 | exitingKey === displayedView.key |
| ... | @@ -152,7 +152,7 @@ export function SidebarProviderUpdatePill() { | ... | @@ -152,7 +152,7 @@ export function SidebarProviderUpdatePill() { |
| 152 | <div | 152 | <div |
| 153 | key={displayedView.key} | 153 | key={displayedView.key} |
| 154 | aria-hidden="true" | 154 | aria-hidden="true" |
| 155 | className={`pointer-events-none absolute inset-y-0 left-0 w-full origin-left animate-[provider-update-pill-countdown_var(--provider-update-pill-dismiss-ms)_linear_forwards] border-r border-current/15 shadow-[inset_0_1px_0_rgb(255_255_255_/_0.08)] ${ | 155 | className={`pointer-events-none absolute inset-y-0 left-0 w-full origin-left scale-x-0 transition-transform duration-(--provider-update-pill-dismiss-ms) ease-linear starting:scale-x-100 border-r border-current/15 inset-shadow-2xs inset-shadow-white/8 ${ |
| 156 | PROVIDER_UPDATE_PILL_PROGRESS_STYLES[displayedView.tone] | 156 | PROVIDER_UPDATE_PILL_PROGRESS_STYLES[displayedView.tone] |
| 157 | }`} | 157 | }`} |
| 158 | style={ | 158 | style={ |
apps/web/src/components/sidebar/SidebarThreadHeader.tsx+1-1| ... | @@ -83,7 +83,7 @@ export function SidebarThreadHeader({ | ... | @@ -83,7 +83,7 @@ export function SidebarThreadHeader({ |
| 83 | ref={searchFieldRef} | 83 | ref={searchFieldRef} |
| 84 | className="flex h-8 min-w-0 flex-1 items-center gap-2 rounded-md px-2 py-1.5 text-sm font-medium text-sidebar-muted-foreground hover:bg-sidebar-row-hover hover:text-sidebar-foreground" | 84 | className="flex h-8 min-w-0 flex-1 items-center gap-2 rounded-md px-2 py-1.5 text-sm font-medium text-sidebar-muted-foreground hover:bg-sidebar-row-hover hover:text-sidebar-foreground" |
| 85 | > | 85 | > |
| 86 | <SearchIcon className="size-4 shrink-0 text-[var(--sidebar-icon-color)]" /> | 86 | <SearchIcon className="size-4 shrink-0 text-(--sidebar-icon-color)" /> |
| 87 | <SidebarInput | 87 | <SidebarInput |
| 88 | ref={searchInputRef} | 88 | ref={searchInputRef} |
| 89 | nativeInput | 89 | nativeInput |
apps/web/src/components/sidebar/SidebarUpdatePill.tsx+1-1| ... | @@ -311,7 +311,7 @@ function SidebarUpdateControl() { | ... | @@ -311,7 +311,7 @@ function SidebarUpdateControl() { |
| 311 | !isInteractionDisabled && "hover:bg-sidebar-row-hover", | 311 | !isInteractionDisabled && "hover:bg-sidebar-row-hover", |
| 312 | ) | 312 | ) |
| 313 | : cn( | 313 | : cn( |
| 314 | "text-[var(--sidebar-icon-color)]", | 314 | "text-(--sidebar-icon-color)", |
| 315 | !isInteractionDisabled && "hover:bg-sidebar-row-hover hover:text-sidebar-foreground", | 315 | !isInteractionDisabled && "hover:bg-sidebar-row-hover hover:text-sidebar-foreground", |
| 316 | ), | 316 | ), |
| 317 | disabled && !showUpdateIconState && "opacity-60", | 317 | disabled && !showUpdateIconState && "opacity-60", |
apps/web/src/components/usage/UsageLimitsPooled.tsx+5-5| ... | @@ -52,7 +52,7 @@ function AccountChip({ email }: { readonly email: string }) { | ... | @@ -52,7 +52,7 @@ function AccountChip({ email }: { readonly email: string }) { |
| 52 | <span | 52 | <span |
| 53 | role="img" | 53 | role="img" |
| 54 | aria-label={`Account ${accountInitials(email)}`} | 54 | aria-label={`Account ${accountInitials(email)}`} |
| 55 | className="inline-flex size-4 shrink-0 items-center justify-center rounded-full text-[9px] leading-none font-semibold" | 55 | className="inline-flex size-4 shrink-0 items-center justify-center rounded-full text-3xs leading-none font-semibold" |
| 56 | style={{ backgroundColor: `oklch(0.85 0.08 ${hue})`, color: `oklch(0.35 0.1 ${hue})` }} | 56 | style={{ backgroundColor: `oklch(0.85 0.08 ${hue})`, color: `oklch(0.35 0.1 ${hue})` }} |
| 57 | > | 57 | > |
| 58 | {accountInitials(email)} | 58 | {accountInitials(email)} |
| ... | @@ -269,7 +269,7 @@ function PoolSegment({ | ... | @@ -269,7 +269,7 @@ function PoolSegment({ |
| 269 | ) : null} | 269 | ) : null} |
| 270 | <span | 270 | <span |
| 271 | aria-hidden | 271 | aria-hidden |
| 272 | className="absolute inset-0 flex items-center justify-center text-[10px] leading-none font-semibold text-foreground/80 tabular-nums @2xl/pool:hidden" | 272 | className="absolute inset-0 flex items-center justify-center text-3xs leading-none font-semibold text-foreground/80 tabular-nums @2xl/pool:hidden" |
| 273 | > | 273 | > |
| 274 | {index} | 274 | {index} |
| 275 | </span> | 275 | </span> |
| ... | @@ -277,7 +277,7 @@ function PoolSegment({ | ... | @@ -277,7 +277,7 @@ function PoolSegment({ |
| 277 | <AccountName account={account} className="min-w-0 truncate font-medium text-foreground" /> | 277 | <AccountName account={account} className="min-w-0 truncate font-medium text-foreground" /> |
| 278 | <span className="shrink-0 font-semibold text-foreground tabular-nums">{remaining}%</span> | 278 | <span className="shrink-0 font-semibold text-foreground tabular-nums">{remaining}%</span> |
| 279 | {/* Countdown and badge get their own plate: fill and hatching run under them otherwise. */} | 279 | {/* Countdown and badge get their own plate: fill and hatching run under them otherwise. */} |
| 280 | <span className="ms-auto flex shrink-0 items-center gap-1.5 rounded-sm bg-background/85 px-1.5 py-0.5 text-[11px] text-foreground tabular-nums"> | 280 | <span className="ms-auto flex shrink-0 items-center gap-1.5 rounded-sm bg-background/85 px-1.5 py-0.5 text-2xs text-foreground tabular-nums"> |
| 281 | {resetsIn?.replace("resets in ", "↻ ") ?? ""} | 281 | {resetsIn?.replace("resets in ", "↻ ") ?? ""} |
| 282 | {credits ? ( | 282 | {credits ? ( |
| 283 | <> | 283 | <> |
| ... | @@ -348,7 +348,7 @@ function LegendRow({ | ... | @@ -348,7 +348,7 @@ function LegendRow({ |
| 348 | render={<Button variant="ghost" size="compact" />} | 348 | render={<Button variant="ghost" size="compact" />} |
| 349 | className="min-w-0 @2xl/pool:hidden" | 349 | className="min-w-0 @2xl/pool:hidden" |
| 350 | > | 350 | > |
| 351 | <span className="relative inline-flex size-4 shrink-0 items-center justify-center rounded-sm text-[10px] leading-none font-semibold text-foreground/80 tabular-nums"> | 351 | <span className="relative inline-flex size-4 shrink-0 items-center justify-center rounded-sm text-3xs leading-none font-semibold text-foreground/80 tabular-nums"> |
| 352 | <span | 352 | <span |
| 353 | aria-hidden | 353 | aria-hidden |
| 354 | className="absolute inset-0 rounded-sm opacity-35" | 354 | className="absolute inset-0 rounded-sm opacity-35" |
| ... | @@ -359,7 +359,7 @@ function LegendRow({ | ... | @@ -359,7 +359,7 @@ function LegendRow({ |
| 359 | </span> | 359 | </span> |
| 360 | <AccountName account={account} className="min-w-0 truncate font-medium text-foreground" /> | 360 | <AccountName account={account} className="min-w-0 truncate font-medium text-foreground" /> |
| 361 | <span className="shrink-0 font-semibold text-foreground tabular-nums">{remaining}%</span> | 361 | <span className="shrink-0 font-semibold text-foreground tabular-nums">{remaining}%</span> |
| 362 | <span className="ms-auto flex shrink-0 items-center gap-1.5 text-[11px] text-muted-foreground tabular-nums"> | 362 | <span className="ms-auto flex shrink-0 items-center gap-1.5 text-2xs text-muted-foreground tabular-nums"> |
| 363 | {resetsIn?.replace("resets in ", "↻ ") ?? ""} | 363 | {resetsIn?.replace("resets in ", "↻ ") ?? ""} |
| 364 | {credits ? ( | 364 | {credits ? ( |
| 365 | <> | 365 | <> |
apps/web/src/components/usage/UsagePage.tsx+1-1| ... | @@ -428,7 +428,7 @@ export function UsagePage() { | ... | @@ -428,7 +428,7 @@ export function UsagePage() { |
| 428 | <span className="truncate"> | 428 | <span className="truncate"> |
| 429 | {PROVIDER_PRESENTATION[provider].label} | 429 | {PROVIDER_PRESENTATION[provider].label} |
| 430 | </span> | 430 | </span> |
| 431 | <span className="shrink-0 whitespace-nowrap text-[11px] text-muted-foreground tabular-nums"> | 431 | <span className="shrink-0 whitespace-nowrap text-2xs text-muted-foreground tabular-nums"> |
| 432 | {sessionLabel} | 432 | {sessionLabel} |
| 433 | </span> | 433 | </span> |
| 434 | </span> | 434 | </span> |
apps/web/src/components/usage/UsageProviderChart.tsx+2-2| ... | @@ -322,7 +322,7 @@ export function UsageProviderChart({ | ... | @@ -322,7 +322,7 @@ export function UsageProviderChart({ |
| 322 | {ticks.map((tick) => ( | 322 | {ticks.map((tick) => ( |
| 323 | <span | 323 | <span |
| 324 | key={tick} | 324 | key={tick} |
| 325 | className="absolute right-0 -translate-y-1/2 text-[10px] text-muted-foreground tabular-nums" | 325 | className="absolute right-0 -translate-y-1/2 text-3xs text-muted-foreground tabular-nums" |
| 326 | style={{ top: `${(toY(tick) / VIEW_HEIGHT) * 100}%` }} | 326 | style={{ top: `${(toY(tick) / VIEW_HEIGHT) * 100}%` }} |
| 327 | > | 327 | > |
| 328 | {tick === 0 ? "0" : format(tick)} | 328 | {tick === 0 ? "0" : format(tick)} |
| ... | @@ -434,7 +434,7 @@ export function UsageProviderChart({ | ... | @@ -434,7 +434,7 @@ export function UsageProviderChart({ |
| 434 | </div> | 434 | </div> |
| 435 | </div> | 435 | </div> |
| 436 | 436 | ||
| 437 | <div className="flex justify-between pl-16 text-[10px] text-muted-foreground uppercase"> | 437 | <div className="flex justify-between pl-16 text-3xs text-muted-foreground uppercase"> |
| 438 | <span>{periods[0] === undefined ? "" : formatPeriod(periods[0])}</span> | 438 | <span>{periods[0] === undefined ? "" : formatPeriod(periods[0])}</span> |
| 439 | <span> | 439 | <span> |
| 440 | {periods[Math.floor(periods.length / 2)] === undefined | 440 | {periods[Math.floor(periods.length / 2)] === undefined |
apps/web/src/index.css+46-34| ... | @@ -116,6 +116,17 @@ html[data-mobile-composer-route-transition="true"]::view-transition-old(t3-mobil | ... | @@ -116,6 +116,17 @@ html[data-mobile-composer-route-transition="true"]::view-transition-old(t3-mobil |
| 116 | --workspace-titlebar-control-size: 1.75rem; | 116 | --workspace-titlebar-control-size: 1.75rem; |
| 117 | --workspace-titlebar-control-gap: 0.75rem; | 117 | --workspace-titlebar-control-gap: 0.75rem; |
| 118 | --workspace-titlebar-scroll-fade-height: 1.5rem; | 118 | --workspace-titlebar-scroll-fade-height: 1.5rem; |
| 119 | /* The prompt on phones: iOS zooms into any input under 16px on focus. */ | ||
| 120 | --font-size-prompt-touch: max(var(--font-size-prompt, 1rem), 16px); | ||
| 121 | /* Horizontal gutter shared by the page header and the chat column, clear of | ||
| 122 | the device's safe area. */ | ||
| 123 | --workspace-gutter: 0.75rem; | ||
| 124 | --workspace-gutter-start: calc(env(safe-area-inset-left) + var(--workspace-gutter)); | ||
| 125 | --workspace-gutter-end: calc(env(safe-area-inset-right) + var(--workspace-gutter)); | ||
| 126 | |||
| 127 | @variant sm { | ||
| 128 | --workspace-gutter: 1.25rem; | ||
| 129 | } | ||
| 119 | 130 | ||
| 120 | @variant dark { | 131 | @variant dark { |
| 121 | --appearance-contrast-target: white; | 132 | --appearance-contrast-target: white; |
| ... | @@ -148,6 +159,41 @@ html[data-mobile-composer-route-transition="true"]::view-transition-old(t3-mobil | ... | @@ -148,6 +159,41 @@ html[data-mobile-composer-route-transition="true"]::view-transition-old(t3-mobil |
| 148 | } | 159 | } |
| 149 | 160 | ||
| 150 | @theme inline { | 161 | @theme inline { |
| 162 | /* Two steps below Tailwind's text-xs (12px) for dense UI: metadata rows, | ||
| 163 | badges, counters, keyboard hints and diagnostics tables. 2xs is 11px, | ||
| 164 | 3xs is 10px and the floor of the scale. Registered with tailwind-merge in | ||
| 165 | lib/utils.ts so cn() treats them as font sizes, not colours. */ | ||
| 166 | --text-2xs: 0.6875rem; | ||
| 167 | --text-2xs--line-height: calc(1 / 0.6875); | ||
| 168 | --text-3xs: 0.625rem; | ||
| 169 | --text-3xs--line-height: calc(0.875 / 0.625); | ||
| 170 | /* Motion. drawer is the decelerating curve for surfaces that slide or pop in | ||
| 171 | (composer context, pills). */ | ||
| 172 | --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1); | ||
| 173 | /* The composer's elevation: a soft drop pulled in under the surface, shared | ||
| 174 | by the composer, its context strip and attached banners. */ | ||
| 175 | --shadow-composer: 0 12px 28px -18px rgb(0 0 0 / 40%); | ||
| 176 | --shadow-composer-dark: 0 14px 32px -18px rgb(0 0 0 / 75%); | ||
| 177 | /* Dark-mode shade where an attached surface meets the composer: 10px of | ||
| 178 | shadow fading away from the seam. Inline, so the offsets resolve on the | ||
| 179 | element. below: the context strip under the composer (1rem seam, faint | ||
| 180 | white fill). above: an attached banner over it (its tint on top). */ | ||
| 181 | --background-image-composer-seam-below: | ||
| 182 | linear-gradient( | ||
| 183 | to bottom, | ||
| 184 | transparent 0 1rem, | ||
| 185 | rgb(0 0 0 / 18%) 1rem, | ||
| 186 | transparent calc(1rem + 10px) | ||
| 187 | ), | ||
| 188 | linear-gradient(rgb(255 255 255 / 1%), rgb(255 255 255 / 1%)); | ||
| 189 | --background-image-composer-seam-above: | ||
| 190 | linear-gradient(var(--chat-composer-attached-tint), var(--chat-composer-attached-tint)), | ||
| 191 | linear-gradient( | ||
| 192 | to top, | ||
| 193 | transparent 0 var(--chat-composer-attachment-overlap), | ||
| 194 | rgb(0 0 0 / 18%) var(--chat-composer-attachment-overlap), | ||
| 195 | transparent calc(var(--chat-composer-attachment-overlap) + 10px) | ||
| 196 | ); | ||
| 151 | --color-zinc-25: oklch(99.2% 0 0); | 197 | --color-zinc-25: oklch(99.2% 0 0); |
| 152 | --animate-skeleton: skeleton 2.4s infinite; | 198 | --animate-skeleton: skeleton 2.4s infinite; |
| 153 | /* Duty-cycled indicator animations: long holds with stepped ramps, so the | 199 | /* Duty-cycled indicator animations: long holds with stepped ramps, so the |
| ... | @@ -1936,40 +1982,6 @@ code { | ... | @@ -1936,40 +1982,6 @@ code { |
| 1936 | overflow-wrap: anywhere; | 1982 | overflow-wrap: anywhere; |
| 1937 | } | 1983 | } |
| 1938 | 1984 | ||
| 1939 | /* Prompt-stash save acknowledgement: the new count fades up from just below | ||
| 1940 | its resting position, once, then stops. One-shot and event-driven (React | ||
| 1941 | remounts the element by key on each stash) — no continuous animation. */ | ||
| 1942 | @keyframes prompt-stash-count-enter { | ||
| 1943 | from { | ||
| 1944 | opacity: 0; | ||
| 1945 | transform: translateY(2px); | ||
| 1946 | } | ||
| 1947 | to { | ||
| 1948 | opacity: 1; | ||
| 1949 | transform: translateY(0); | ||
| 1950 | } | ||
| 1951 | } | ||
| 1952 | |||
| 1953 | /* Expanded capture preview swaps between the screenshot and its extracted text. | ||
| 1954 | One-shot fade on whichever panel mounts, so nothing repaints continuously. */ | ||
| 1955 | @keyframes snap-shot-contents-enter { | ||
| 1956 | from { | ||
| 1957 | opacity: 0; | ||
| 1958 | } | ||
| 1959 | to { | ||
| 1960 | opacity: 1; | ||
| 1961 | } | ||
| 1962 | } | ||
| 1963 | |||
| 1964 | @keyframes provider-update-pill-countdown { | ||
| 1965 | from { | ||
| 1966 | transform: scaleX(1); | ||
| 1967 | } | ||
| 1968 | to { | ||
| 1969 | transform: scaleX(0); | ||
| 1970 | } | ||
| 1971 | } | ||
| 1972 | |||
| 1973 | :root { | 1985 | :root { |
| 1974 | --diff-addition: var(--success); | 1986 | --diff-addition: var(--success); |
| 1975 | --diff-deletion: var(--destructive); | 1987 | --diff-deletion: var(--destructive); |
apps/web/src/lib/utils.ts+5-1| ... | @@ -1,9 +1,13 @@ | ... | @@ -1,9 +1,13 @@ |
| 1 | import { MessageId, ProjectId, ThreadId } from "@t3tools/contracts"; | 1 | import { MessageId, ProjectId, ThreadId } from "@t3tools/contracts"; |
| 2 | import { type CxOptions, cx } from "class-variance-authority"; | 2 | import { type CxOptions, cx } from "class-variance-authority"; |
| 3 | import * as Encoding from "effect/Encoding"; | 3 | import * as Encoding from "effect/Encoding"; |
| 4 | import { twMerge } from "tailwind-merge"; | 4 | import { extendTailwindMerge } from "tailwind-merge"; |
| 5 | import { DraftId } from "../composerDraftStore"; | 5 | import { DraftId } from "../composerDraftStore"; |
| 6 | 6 | ||
| 7 | // The theme's extra font sizes (index.css). Unregistered, tailwind-merge reads | ||
| 8 | // text-2xs as a colour and drops it next to text-muted-foreground. | ||
| 9 | const twMerge = extendTailwindMerge({ extend: { theme: { text: ["2xs", "3xs"] } } }); | ||
| 10 | |||
| 7 | export function cn(...inputs: CxOptions) { | 11 | export function cn(...inputs: CxOptions) { |
| 8 | return twMerge(cx(inputs)); | 12 | return twMerge(cx(inputs)); |
| 9 | } | 13 | } |
vite.config.ts+40| ... | @@ -225,6 +225,41 @@ export default defineConfig({ | ... | @@ -225,6 +225,41 @@ export default defineConfig({ |
| 225 | rules: { | 225 | rules: { |
| 226 | // A className built at runtime on a ui component is one no-restyle cannot read. | 226 | // A className built at runtime on a ui component is one no-restyle cannot read. |
| 227 | "shadcn/require-static-classes": "error", | 227 | "shadcn/require-static-classes": "error", |
| 228 | // Appearance values come from the theme and Tailwind's scales. Layout stays free | ||
| 229 | // (placement belongs to the parent); the other entries are values no scale can hold. | ||
| 230 | "shadcn/no-arbitrary-values": [ | ||
| 231 | "error", | ||
| 232 | { | ||
| 233 | allow: [ | ||
| 234 | "layout", | ||
| 235 | // Which properties an element animates is per-element behaviour, like layout, | ||
| 236 | // not a design value; timing curves and durations still come from the theme. | ||
| 237 | "transition", | ||
| 238 | // Overlays that follow their frame's corner, which is set at runtime | ||
| 239 | // (floating preview) or by the element they decorate (composer outline). | ||
| 240 | "rounded-[inherit]", | ||
| 241 | // Inline chips size in em so they scale with the text they sit in | ||
| 242 | // (the composer honours the prompt font-size preference). | ||
| 243 | "gap-[0.33em]", | ||
| 244 | "px-[0.5em]", | ||
| 245 | "rounded-[0.5em]", | ||
| 246 | "text-[0.86em]", | ||
| 247 | // Project icons render from 14px to 48px and keep one proportional corner. | ||
| 248 | "rounded-[25%]", | ||
| 249 | // An emoji project icon fills its container, whatever size the parent gives it. | ||
| 250 | "text-[length:80cqh]", | ||
| 251 | // The platform's own selection colour on a selected composer chip. | ||
| 252 | "bg-[Highlight]", | ||
| 253 | // Brand marks keep their brand colours (Cursor, Grok, Claude). | ||
| 254 | "fill-[#26251E]", | ||
| 255 | "fill-[#EDECEC]", | ||
| 256 | "fill-[#0F0F0F]", | ||
| 257 | "fill-[#F5F5F5]", | ||
| 258 | "fill-[#d97757]", | ||
| 259 | "text-[#d97757]", | ||
| 260 | ], | ||
| 261 | }, | ||
| 262 | ], | ||
| 228 | "shadcn/no-restyle": [ | 263 | "shadcn/no-restyle": [ |
| 229 | "error", | 264 | "error", |
| 230 | { | 265 | { |
| ... | @@ -242,6 +277,11 @@ export default defineConfig({ | ... | @@ -242,6 +277,11 @@ export default defineConfig({ |
| 242 | ], | 277 | ], |
| 243 | }, | 278 | }, |
| 244 | }, | 279 | }, |
| 280 | { | ||
| 281 | // The sign-in masthead is T3 brand artwork: fixed gradients, not theme surfaces. | ||
| 282 | files: ["apps/web/src/components/auth/AuthSurfaceShell.tsx"], | ||
| 283 | rules: { "shadcn/no-arbitrary-values": "off" }, | ||
| 284 | }, | ||
| 245 | { | 285 | { |
| 246 | // Shared client code must not call APIs missing from Hermes. Our ESNext | 286 | // Shared client code must not call APIs missing from Hermes. Our ESNext |
| 247 | // TypeScript target accepts them even when they would crash mobile at launch. | 287 | // TypeScript target accepts them even when they would crash mobile at launch. |