authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-24 10:49:05-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-24 10:49:05-07:00
logf26ee083fe41720207fb10616359500dcecc19d3
treec0668ed670d5c836eb9c1a00979e38a5d66a1435
parent315fcca10a826d8aa1cbdffc3ef5b5eb5a1e2f9d
signature Signed by PGP key B5690EEEBB952194

fix(web): appearance classes use theme tokens and scale values (#13397)

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({
175175 }}
176176 >
177177 {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">
179179 Dimensions
180180 </span>
181181 ) : null}
apps/web/src/browser/HostedBrowserWebview.tsx+1-1
......@@ -352,7 +352,7 @@ export function HostedBrowserWebview(props: {
352352 />
353353 {activeDrag ? (
354354 <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"
356356 style={{
357357 left: layout.viewportX + layout.viewportWidth / 2,
358358 top: layout.viewportY + 10,
apps/web/src/components/AgentsPanel.tsx+12-12
......@@ -162,12 +162,12 @@ function AgentRow({ agent }: { agent: RuntimeSubagent }) {
162162 <span className="col-start-2 row-start-1 flex min-w-0 items-baseline gap-2">
163163 <span className="min-w-0 truncate text-sm font-medium">{agent.title}</span>
164164 {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">
166166 {role}
167167 </span>
168168 ) : null}
169169 </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">
171171 <span className="inline-flex items-center gap-1">
172172 <AgentElapsed agent={agent} />
173173 {agent.status === "completed" ? (
......@@ -183,7 +183,7 @@ function AgentRow({ agent }: { agent: RuntimeSubagent }) {
183183 >
184184 {activity ?? statusLabel}
185185 </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">
187187 {metadata.join(" · ")}
188188 </span>
189189 <span className="sr-only">{statusLabel}</span>
......@@ -234,7 +234,7 @@ function PhaseRail({ group }: { group: AgentPanelWorkflowGroup }) {
234234 >
235235 <span
236236 className={cn(
237 "font-mono text-[.65rem]",
237 "font-mono text-3xs",
238238 phase.state === "running"
239239 ? "text-info-foreground"
240240 : phase.state === "done"
......@@ -247,7 +247,7 @@ function PhaseRail({ group }: { group: AgentPanelWorkflowGroup }) {
247247 </span>
248248 <span className="flex items-center gap-0.5">
249249 {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>
251251 ) : (
252252 phase.members.map((member) => <StatusDot key={member.id} status={member.status} />)
253253 )}
......@@ -281,7 +281,7 @@ function WorkflowScriptView({
281281 <div className="mx-1.5 mb-1 rounded-md border border-border/60 bg-background/60">
282282 <div className="flex items-center gap-2 border-b border-border/50 px-2 py-1">
283283 <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">
285285 {scriptPath.split("/").at(-1)}
286286 </span>
287287 <Button
......@@ -296,7 +296,7 @@ function WorkflowScriptView({
296296 </div>
297297 <div className="max-h-72 overflow-auto p-2">
298298 {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">
300300 {result.value.contents}
301301 {result.value.truncated ? "\n… (truncated)" : ""}
302302 </pre>
......@@ -339,7 +339,7 @@ function PhaseSection({
339339 onClick={() => setOpen((value) => !value)}
340340 aria-expanded={open}
341341 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",
343343 phase.state === "done"
344344 ? "text-success-foreground"
345345 : phase.state === "running"
......@@ -399,7 +399,7 @@ function ExpandedWorkflowSection({
399399 const canShowScript = scriptPath !== undefined && environmentId !== null && threadId !== null;
400400 return (
401401 <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">
403403 <StatusDot status={group.workflow.status} />
404404 <span className="min-w-0 truncate">
405405 {group.workflow.workflowName ?? group.workflow.title}
......@@ -486,7 +486,7 @@ function CollapsedWorkflowSection({
486486 <span className="truncate text-sm">
487487 {group.workflow.workflowName ?? group.workflow.title}
488488 </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">
490490 {failed > 0 ? <span className="text-destructive-foreground">{failed} failed</span> : null}
491491 <span>{members.length} agents</span>
492492 <span className="tabular-nums">· {formatSubagentTokenCount(totalTokens)} tok</span>
......@@ -557,7 +557,7 @@ export function AgentsPanel({
557557 ))}
558558 {model.directAgents.length > 0 ? (
559559 <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">
561561 Direct spawns
562562 </div>
563563 {model.directAgents.map((agent) => (
......@@ -567,7 +567,7 @@ export function AgentsPanel({
567567 ) : null}
568568 </div>
569569 </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">
571571 <span className="flex items-center gap-2">
572572 {model.runningCount + model.waitingCount > 0 ? (
573573 <span className="text-info-foreground">
apps/web/src/components/BranchToolbar.tsx+2-2
......@@ -185,7 +185,7 @@ const MobileRunContextSelector = memo(function MobileRunContextSelector({
185185 >
186186 <span
187187 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"
189189 >
190190 {autoEnvironmentLabel ??
191191 (showEnvironmentIndicator ? (activeEnvironment?.label ?? "Run on") : workspaceLabel)}
......@@ -197,7 +197,7 @@ const MobileRunContextSelector = memo(function MobileRunContextSelector({
197197 if (isLocked) {
198198 return (
199199 <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"
201201 data-composer-context-control
202202 >
203203 {triggerContent}
apps/web/src/components/BranchToolbarBranchSelector.tsx+2-2
......@@ -757,7 +757,7 @@ export function BranchToolbarBranchSelector({
757757 >
758758 <div className="flex w-full min-w-0 items-center justify-between gap-2">
759759 <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>}
761761 </div>
762762 </ComboboxItem>
763763 );
......@@ -819,7 +819,7 @@ export function BranchToolbarBranchSelector({
819819 >
820820 <span
821821 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"
823823 >
824824 <MiddleTruncate value={triggerLabel} />
825825 </span>
apps/web/src/components/BranchToolbarEnvModeSelector.tsx+3-3
......@@ -61,7 +61,7 @@ export const BranchToolbarEnvModeSelector = memo(function BranchToolbarEnvModeSe
6161 <Tooltip>
6262 <TooltipTrigger
6363 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"
6565 data-composer-context-control
6666 >
6767 {forceNewWorktree ? (
......@@ -77,7 +77,7 @@ export const BranchToolbarEnvModeSelector = memo(function BranchToolbarEnvModeSe
7777 >
7878 <span
7979 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"
8181 >
8282 {forceNewWorktree
8383 ? resolveEnvModeLabel("worktree")
......@@ -133,7 +133,7 @@ export const BranchToolbarEnvModeSelector = memo(function BranchToolbarEnvModeSe
133133 >
134134 <span
135135 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"
137137 >
138138 <SelectValue />
139139 </span>
apps/web/src/components/BranchToolbarEnvironmentSelector.tsx+3-3
......@@ -63,7 +63,7 @@ export const BranchToolbarEnvironmentSelector = memo(function BranchToolbarEnvir
6363 <Tooltip>
6464 <TooltipTrigger
6565 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"
6767 data-composer-context-control
6868 >
6969 <EnvironmentMachineIcon
......@@ -76,7 +76,7 @@ export const BranchToolbarEnvironmentSelector = memo(function BranchToolbarEnvir
7676 >
7777 <span
7878 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"
8080 >
8181 {activeEnvironment?.label ?? "Run on"}
8282 </span>
......@@ -123,7 +123,7 @@ export const BranchToolbarEnvironmentSelector = memo(function BranchToolbarEnvir
123123 >
124124 <span
125125 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"
127127 >
128128 <SelectValue />
129129 </span>
apps/web/src/components/ChatMarkdown.tsx+3-3
......@@ -974,12 +974,12 @@ function MarkdownCodeBlock({
974974
975975 return (
976976 <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"
978978 data-language={language}
979979 data-wrap={wrapped ? "true" : "false"}
980980 >
981981 <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">
983983 <MarkdownCodeBlockTitleContent
984984 fenceTitle={fenceTitle}
985985 language={language}
......@@ -2201,7 +2201,7 @@ const MarkdownFileLink = memo(function MarkdownFileLink({
22012201 <TooltipPopup side="top" variant="code">
22022202 {/* The full path: the chip already shows the shortened form, and a link
22032203 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">
22052205 {targetPath}
22062206 </div>
22072207 </TooltipPopup>
apps/web/src/components/ChatView.tsx+3-3
......@@ -1220,7 +1220,7 @@ const PersistentThreadTerminalDrawer = memo(function PersistentThreadTerminalDra
12201220 "grid shrink-0 overflow-clip",
12211221 active ? (visible ? "grid-rows-[1fr]" : "grid-rows-[0fr]") : "hidden",
12221222 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",
12241224 active && visible && "[[data-panel-animations=true]_&]:starting:grid-rows-[0fr]!",
12251225 )}
12261226 >
......@@ -9588,7 +9588,7 @@ export default function ChatView(props: ChatViewProps) {
95889588 className={cn(
95899589 "flex shrink-0",
95909590 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",
95929592 rightPanelOpen ? "pointer-events-auto opacity-100" : "pointer-events-none opacity-0",
95939593 )}
95949594 inert={!rightPanelOpen}
......@@ -10015,7 +10015,7 @@ export default function ChatView(props: ChatViewProps) {
1001510015 >
1001610016 <div
1001710017 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)"
1001910019 >
1002010020 <div
1002110021 data-chat-composer-stack="true"
apps/web/src/components/ComposerPromptEditorTiptap.tsx+2-2
......@@ -190,7 +190,7 @@ function resolvedThemeFromDocument(): "light" | "dark" {
190190 * paints the editor's node selection over it.
191191 */
192192const 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-['']";
194194
195195const ComposerMentionExtension = Node.create({
196196 name: "composer-mention",
......@@ -1242,7 +1242,7 @@ function ComposerPromptEditorTiptapInner(props: ComposerPromptEditorProps) {
12421242 <ComposerCitationCommentContext value={citationCommentActions}>
12431243 <div
12441244 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)",
12461246 containerClassName,
12471247 )}
12481248 >
apps/web/src/components/ContextChip.tsx+3-3
......@@ -23,7 +23,7 @@ import { cn } from "~/lib/utils";
2323 * span with tabIndex for a tooltip) gets the focus outline.
2424 */
2525const 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",
2727 {
2828 defaultVariants: { kind: "neutral" },
2929 variants: {
......@@ -71,7 +71,7 @@ const contextChipVariants = cva(
7171 "citation",
7272 ],
7373 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",
7575 },
7676 // State colors win over any kind.
7777 { state: "unresolved", className: "text-foreground" },
......@@ -115,7 +115,7 @@ function ContextChipLabel({ className, ...props }: React.ComponentProps<"span">)
115115function ContextChipAction({ className, render, ...props }: useRender.ComponentProps<"button">) {
116116 const defaultProps = {
117117 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]",
119119 className,
120120 ),
121121 "data-slot": "context-chip-action",
apps/web/src/components/DiffPanel.tsx+6-6
......@@ -765,7 +765,7 @@ export default function DiffPanel({
765765 value={baseRefQuery}
766766 onChange={(event) => setBaseRefQuery(event.target.value)}
767767 />
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">
769769 <span aria-hidden="true" />
770770 <div className="grid min-w-0 grid-cols-[minmax(0,1fr)_2rem] items-center">
771771 <span>Branch</span>
......@@ -841,7 +841,7 @@ export default function DiffPanel({
841841 <DiffStatLabel
842842 additions={diffLineStat.additions}
843843 deletions={diffLineStat.deletions}
844 className="mr-1 text-[11px]"
844 className="mr-1 text-2xs"
845845 layout="inline"
846846 />
847847 ) : null}
......@@ -992,14 +992,14 @@ export default function DiffPanel({
992992 <>
993993 <div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden bg-background">
994994 {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">
996996 This preview exceeds the size limit. Changes shown are incomplete.
997997 {selectedGitSource?.files ? " Totals include all changes." : ""}
998998 </p>
999999 )}
10001000 {selectedPatchError && !renderablePatch && (
10011001 <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>
10031003 </div>
10041004 )}
10051005 {!renderablePatch && !lazySource ? (
......@@ -1181,12 +1181,12 @@ export default function DiffPanel({
11811181 ) : (
11821182 <div className="min-h-0 flex-1 overflow-auto p-2">
11831183 <div className="space-y-2">
1184 <p className="text-[11px] text-muted-foreground/75">
1184 <p className="text-2xs text-muted-foreground/75">
11851185 {renderablePatch?.kind === "raw" ? renderablePatch.reason : null}
11861186 </p>
11871187 <pre
11881188 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",
11901190 wordWrap
11911191 ? "overflow-auto whitespace-pre-wrap wrap-break-word"
11921192 : "overflow-auto",
apps/web/src/components/DiffPanelShell.tsx+1-1
......@@ -13,7 +13,7 @@ function getDiffPanelHeaderRowClassName(mode: DiffPanelMode) {
1313 "flex items-center justify-between gap-2",
1414 mode === "embedded" ? "px-2" : "px-4",
1515 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)"
1717 : "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",
1818 );
1919}
apps/web/src/components/LegacySidebar.tsx+5-5
......@@ -234,7 +234,7 @@ const PROJECT_GROUPING_MODE_LABELS: Record<SidebarProjectGroupingMode, string> =
234234 separate: "Keep separate",
235235};
236236const 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";
238238
239239function SidebarThreadDetailPrewarmer({ threadRef }: { readonly threadRef: ScopedThreadRef }) {
240240 useEnvironmentThread(threadRef.environmentId, threadRef.threadId);
......@@ -850,7 +850,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP
850850 data-thread-selection-safe
851851 data-testid={`thread-archive-confirm-${thread.id}`}
852852 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"
854854 onPointerDown={stopPropagationOnPointerDown}
855855 onClick={handleConfirmArchiveClick}
856856 >
......@@ -920,7 +920,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP
920920 render={
921921 <span
922922 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"
924924 />
925925 }
926926 >
......@@ -930,7 +930,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP
930930 </Tooltip>
931931 ) : (
932932 <span
933 className={`text-[10px] tabular-nums ${
933 className={`text-3xs tabular-nums ${
934934 isHighlighted ? "text-foreground" : "text-secondary-label"
935935 }`}
936936 >
......@@ -2410,7 +2410,7 @@ const SidebarProjectItem = memo(function SidebarProjectItem(props: SidebarProjec
24102410 {project.displayName}
24112411 </span>
24122412 {project.groupedProjectCount > 1 ? (
2413 <span className="shrink-0 text-secondary-label text-[10px]">
2413 <span className="shrink-0 text-secondary-label text-3xs">
24142414 {project.groupedProjectCount} projects
24152415 </span>
24162416 ) : null}
apps/web/src/components/ProjectFavicon.tsx+2-2
......@@ -19,7 +19,7 @@ const DynamicIcon = lazy(() =>
1919);
2020
2121function DynamicProjectIconFallback() {
22 return <FolderCodeIcon className="size-full text-[inherit]" />;
22 return <FolderCodeIcon className="size-full text-inherit" />;
2323}
2424
2525// The slice of a project that decides its icon. Every surface must pass the
......@@ -176,7 +176,7 @@ function ProjectFaviconImage({
176176 <img
177177 src={displayedSrc}
178178 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)}
180180 onError={() => handleLoadError(displayedSrc)}
181181 />
182182 ) : null}
apps/web/src/components/PullRequestContextDetails.tsx+1-1
......@@ -15,7 +15,7 @@ export function PullRequestContextDetails({ metadata }: { metadata: PullRequestC
1515 <span className={state.toneClassName}>{state.label}</span>
1616 </div>
1717 <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">
1919 <code className="truncate">{metadata.headBranch}</code>
2020 <ArrowRightIcon className="size-3 shrink-0" aria-hidden="true" />
2121 <code className="truncate">{metadata.baseBranch}</code>
apps/web/src/components/RightPanelTabs.tsx+11-10
......@@ -488,7 +488,7 @@ function RightPanelEmptyState(props: {
488488 {action.badgeCount > 0 ? (
489489 <span
490490 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"
492492 >
493493 {action.badgeCount}
494494 </span>
......@@ -505,13 +505,13 @@ function RightPanelEmptyState(props: {
505505 aria-label="Open a surface"
506506 data-surface-launcher-keys={availableActions.map((action) => action.shortcut).join("")}
507507 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",
509509 // The panel topbar sits above this container; matching bottom padding
510510 // 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)",
512512 )}
513513 >
514 <div className="w-full max-w-xs">
514 <div className="w-full max-w-xs py-6">
515515 <h3 className="mb-3 text-center font-medium text-foreground text-sm">Open a surface</h3>
516516 <div className="flex flex-col gap-0.5">
517517 {actions.map((action) =>
......@@ -534,7 +534,7 @@ function RightPanelEmptyState(props: {
534534 type="button"
535535 onClick={action.onClick}
536536 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",
538538 isHighlighted(action) && "bg-accent/60",
539539 )}
540540 >
......@@ -589,7 +589,7 @@ function RightPanelEmptyState(props: {
589589 <div
590590 tabIndex={0}
591591 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"
593593 >
594594 {actionIcon(action, "size-4")}
595595 <span className="min-w-0 flex-1 truncate">{action.label}</span>
......@@ -1114,10 +1114,7 @@ export function RightPanelTabs(props: RightPanelTabsProps) {
11141114 // controls a few pixels higher and the cluster jumps on open.
11151115 props.mode === "inline" && !props.layoutControls ? "pr-28" : "pr-3",
11161116 ownsDesktopTitleBar && "drag-region",
1117 ownsDesktopTitleBar &&
1118 (props.layoutControls
1119 ? "wco:pr-[var(--workspace-native-controls-inset)]"
1120 : "wco:pr-[calc(var(--workspace-native-controls-inset)+6rem)]"),
1117 ownsDesktopTitleBar && "wco:pr-(--workspace-native-controls-inset)",
11211118 props.mode === "inline" && props.maximized && COLLAPSED_SIDEBAR_TITLEBAR_INSET_CLASS,
11221119 )}
11231120 data-right-panel-tabbar
......@@ -1395,6 +1392,10 @@ export function RightPanelTabs(props: RightPanelTabsProps) {
13951392 </div>
13961393 ) : null}
13971394 {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}
13981399 {ownsDesktopTitleBar ? (
13991400 <span
14001401 aria-hidden
apps/web/src/components/Sidebar.tsx+8-8
......@@ -283,7 +283,7 @@ function JumpHintBadge(props: { label: string }) {
283283 return (
284284 <span
285285 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"
287287 >
288288 {props.label}
289289 </span>
......@@ -760,7 +760,7 @@ const SidebarDraftRow = memo(function SidebarDraftRow(props: {
760760 onClick={handleActivate}
761761 onKeyDown={handleKeyDown}
762762 >
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)">
764764 <div className="flex h-5 min-w-0 items-center gap-1.5">
765765 <SquarePenIcon aria-hidden className={draftPenClassName} />
766766 {props.project ? (
......@@ -1408,7 +1408,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {
14081408 // keeps the hover color applied, so both the tint and the solid sidebar
14091409 // color are stacked as background images.
14101410 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",
14121412 );
14131413 // dnd-kit props for the row root. Same bag on both variants: every row in
14141414 // the list translates around the gap as the drag passes it.
......@@ -1433,7 +1433,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {
14331433 sortable?.isDragging && props.dropVerb !== null ? (
14341434 <span
14351435 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"
14371437 >
14381438 {dropVerbBadge[props.dropVerb]}
14391439 </span>
......@@ -1478,7 +1478,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {
14781478 ? "text-muted-foreground"
14791479 : "text-secondary-label/70",
14801480 ),
1481 isRegeneratingTitle && "opacity-[0.55]",
1481 isRegeneratingTitle && "opacity-55",
14821482 )}
14831483 >
14841484 {thread.title}
......@@ -1745,7 +1745,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {
17451745 />
17461746 }
17471747 >
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)">
17491749 <div className="flex h-5 min-w-0 items-center gap-1.5">
17501750 {draftIndicator}
17511751 {props.project ? (
......@@ -1956,7 +1956,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: {
19561956 showBadge={showInstanceBadge}
19571957 // Glyph dims, badge stays saturated; offset matches the composer trigger.
19581958 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"
19601960 />
19611961 </span>
19621962 ) : null}
......@@ -4912,7 +4912,7 @@ export default function Sidebar() {
49124912 <button
49134913 type="button"
49144914 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"
49164916 >
49174917 <PlusIcon className="-mx-0.5 size-3" />
49184918 Add project
apps/web/src/components/SlowRpcRequestToastCoordinator.tsx+1-1
......@@ -22,7 +22,7 @@ function SlowRequestDetails({ requests }: { requests: ReadonlyArray<SlowRpcAckRe
2222 key={request.requestId}
2323 >
2424 <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">
2626 Started {new Date(request.startedAt).toLocaleTimeString()}
2727 </div>
2828 </li>
apps/web/src/components/ThreadStatusIndicators.tsx+2-2
......@@ -328,7 +328,7 @@ export function ThreadPullRequestsMiniList({
328328 {snapshot?.title ?? line.link.repository}
329329 </span>
330330 {line.stack ? (
331 <span className="ml-auto shrink-0 pl-1 text-[10px]">
331 <span className="ml-auto shrink-0 pl-1 text-3xs">
332332 {line.stack.kind === "native" ? "stack" : "chain"} · {line.stack.size}
333333 </span>
334334 ) : null}
......@@ -463,7 +463,7 @@ export function ThreadStatusLabel({
463463 render={
464464 <span
465465 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}`}
467467 />
468468 }
469469 >
apps/web/src/components/ThreadTerminalDrawer.tsx+4-4
......@@ -981,7 +981,7 @@ export function TerminalViewport({
981981 <div
982982 ref={containerRef}
983983 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)"
985985 />
986986 );
987987}
......@@ -1490,7 +1490,7 @@ export default function ThreadTerminalDrawer({
14901490 <div className="min-h-0 w-full flex-1">
14911491 <div
14921492 className={cn(
1493 "flex h-full min-h-0 bg-[var(--terminal-background)]",
1493 "flex h-full min-h-0 bg-(--terminal-background)",
14941494 hasTerminalSidebar && "gap-1.5",
14951495 )}
14961496 >
......@@ -1653,7 +1653,7 @@ export default function ThreadTerminalDrawer({
16531653 {showGroupHeaders && (
16541654 <button
16551655 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 ${
16571657 isGroupActive
16581658 ? "bg-accent/50 text-foreground"
16591659 : "text-muted-foreground hover:bg-accent/40 hover:text-foreground"
......@@ -1662,7 +1662,7 @@ export default function ThreadTerminalDrawer({
16621662 >
16631663 <GroupIcon className="size-3 shrink-0" />
16641664 <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">
16661666 {terminalCount}
16671667 </span>
16681668 </button>
apps/web/src/components/WorkspaceBreadcrumb.tsx+1-1
......@@ -33,7 +33,7 @@ export function WorkspaceBreadcrumbText({ children, className, ...props }: Compo
3333 // Center the capital letters with adjacent icons, not the font's leading.
3434 // Padding preserves accents and descenders when a label is truncated.
3535 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",
3737 className,
3838 )}
3939 {...props}
apps/web/src/components/WorkspacePageHeader.tsx+2-2
......@@ -16,9 +16,9 @@ export function WorkspacePageHeader({
1616 return (
1717 <header
1818 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",
2020 electron && "drag-region",
21 reserveNativeControls && "wco:pr-[var(--workspace-native-controls-inset)]",
21 reserveNativeControls && "wco:pr-(--workspace-native-controls-inset)",
2222 COLLAPSED_SIDEBAR_TITLEBAR_INSET_CLASS,
2323 className,
2424 )}
apps/web/src/components/auth/AuthSurfaceShell.tsx+1-1
......@@ -27,7 +27,7 @@ export function AuthSurfaceShell({ children }: { readonly children: ReactNode })
2727 )}
2828 <div className="absolute inset-0 bg-[linear-gradient(to_bottom,transparent_20%,rgba(7,18,55,0.46)_100%)]" />
2929 <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">
3131 {APP_DISPLAY_NAME}
3232 </p>
3333 </div>
apps/web/src/components/chat/AssistantCitationChip.tsx+2-2
......@@ -110,7 +110,7 @@ export function AssistantCitationChip({
110110 const composerSourceLink = (
111111 <Link
112112 {...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"
114114 aria-label={`View cited assistant text: ${label}`}
115115 >
116116 <QuoteIcon aria-hidden="true" />
......@@ -120,7 +120,7 @@ export function AssistantCitationChip({
120120 const chatSourceLink = (
121121 <Link
122122 {...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"
124124 aria-label={`View cited assistant text: ${label}`}
125125 >
126126 <QuoteIcon aria-hidden="true" />
apps/web/src/components/chat/ChangedFilesTree.tsx+4-4
......@@ -54,7 +54,7 @@ export const ChangedFilesCard = memo(function ChangedFilesCard(props: {
5454 >
5555 <div
5656 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"
5858 >
5959 <div className="flex min-w-0 flex-wrap items-center gap-x-3 gap-y-1 text-xs font-medium text-foreground">
6060 <span>
......@@ -206,11 +206,11 @@ export const ChangedFilesTree = memo(function ChangedFilesTree(props: {
206206 ) : (
207207 <FolderClosedIcon className="size-3.5 shrink-0 text-muted-foreground/75" />
208208 )}
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">
210210 {node.name}
211211 </span>
212212 {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">
214214 <DiffStatLabel additions={node.stat.additions} deletions={node.stat.deletions} />
215215 </span>
216216 )}
......@@ -251,7 +251,7 @@ export const ChangedFilesTree = memo(function ChangedFilesTree(props: {
251251 <MiddleTruncate value={node.name} />
252252 </span>
253253 {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">
255255 <DiffStatLabel additions={node.stat.additions} deletions={node.stat.deletions} />
256256 </span>
257257 )}
apps/web/src/components/chat/ChatComposer.tsx+8-8
......@@ -381,7 +381,7 @@ function SnapShotAttachmentFrame({
381381 className={cn(
382382 animateArrival &&
383383 !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",
385385 className,
386386 )}
387387 {...props}
......@@ -6365,7 +6365,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
63656365 data-chat-composer-surface="true"
63666366 data-chat-composer-mobile-collapsed={isComposerCollapsedMobile ? "true" : "false"}
63676367 className={cn(
6368 "rounded-[20px] transition-[background-color] duration-200",
6368 "rounded-3xl transition-[background-color] duration-200",
63696369 isDragOverComposer ? "bg-accent/45 ring-1 ring-primary/70" : null,
63706370 projectSelectionRequired ? "opacity-75" : null,
63716371 composerProviderState.composerSurfaceClassName,
......@@ -6377,7 +6377,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
63776377 type="button"
63786378 data-chat-composer-transition-prompt="true"
63796379 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",
63816381 (activePendingProgress ? activePendingProgress.customAnswer : prompt.trim())
63826382 ? "text-foreground"
63836383 : "text-placeholder",
......@@ -6477,7 +6477,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
64776477 "mb-3 flex max-w-full gap-2",
64786478 pendingSnapShotIds.length > 0 ||
64796479 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"
64816481 : "flex-wrap",
64826482 )}
64836483 >
......@@ -6532,14 +6532,14 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
65326532 alt={image.name}
65336533 className="h-full w-full object-cover"
65346534 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">
65366536 {image.name}
65376537 </span>
65386538 }
65396539 />
65406540 </button>
65416541 ) : (
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">
65436543 {image.name}
65446544 </div>
65456545 )}
......@@ -6572,7 +6572,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
65726572 </Tooltip>
65736573 )}
65746574 {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">
65766576 {formatAttachmentUploadProgress(upload.progress)}
65776577 </span>
65786578 )}
......@@ -6671,7 +6671,7 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
66716671 <PlayIcon className="relative z-10 size-4 fill-current drop-shadow-md" />
66726672 </button>
66736673 {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">
66756675 {formatAttachmentUploadProgress(upload.progress)}
66766676 </span>
66776677 )}
apps/web/src/components/chat/ChatHeader.tsx+2-2
......@@ -494,8 +494,8 @@ export const ChatHeader = memo(function ChatHeader({
494494 "flex shrink-0 items-center justify-end gap-2 @3xl/header-actions:gap-3",
495495 // Reserve two panel toggles plus their 4px gaps and 1px edge inset.
496496 // 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)]",
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",
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:duration-(--panel-animation-duration) [[data-panel-animations=true]_&]:motion-safe:ease-out",
499499 )}
500500 >
501501 <Menu open={actionsCollapsed && actionsOpen} onOpenChange={setActionsOpen}>
apps/web/src/components/chat/ComposerBanner.tsx+14-22
......@@ -51,17 +51,17 @@ function Surface({
5151 surfaceColors,
5252 "relative isolate border-0 bg-transparent shadow-none [--chat-composer-attached-tint:transparent]",
5353 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.
5458 placement === "attached"
55 ? "[--chat-composer-attachment-overlap:calc(1rem+1px)] before:rounded-t-[16px]"
56 : "[--chat-composer-attachment-overlap:0px] before:rounded-[1rem]",
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"
60 : "[--chat-composer-attachment-overlap:0px] before:rounded-2xl",
5761 "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)",
59 // The mask cut-off bleeds one pixel past the seam: Chromium drops the last
60 // device-pixel row of a filtered backdrop when the cut-off lands off the
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))]",
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)",
63 "before:shadow-composer dark:before:shadow-composer-dark",
64 "dark:supports-[(backdrop-filter:blur(1px))_or_(-webkit-backdrop-filter:blur(1px))]:before:bg-composer-seam-above",
6565 "not-supports-[((backdrop-filter:blur(1px))_or_(-webkit-backdrop-filter:blur(1px)))]:before:bg-(--chat-composer-attached-surface)",
6666 className,
6767 )}
......@@ -91,8 +91,8 @@ function Peek({
9191 className={cn(
9292 surfaceColors,
9393 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%)]",
95 "bg-[color-mix(in_srgb,var(--chat-composer-attached-surface)_var(--glass-opacity),transparent)] backdrop-blur-(--glass-blur) backdrop-saturate-(--glass-saturation)",
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-(--chat-composer-attached-surface)/(--glass-opacity) backdrop-blur-(--glass-blur) backdrop-saturate-(--glass-saturation)",
9696 "not-supports-[((backdrop-filter:blur(1px))_or_(-webkit-backdrop-filter:blur(1px)))]:bg-(--chat-composer-attached-surface)",
9797 "transition-opacity duration-150 ease-out focus-visible:outline-2 focus-visible:outline-ring",
9898 peekBorder[variant],
......@@ -161,7 +161,7 @@ function Root({
161161 return (
162162 <Surface
163163 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)]",
165165 density === "comfortable" && "[--composer-banner-padding-block:--spacing(1.25)]",
166166 density === "spacious" && "px-3 [--composer-banner-padding-block:--spacing(3)]",
167167 width === "content" ? "w-fit max-w-full flex-none" : "@container",
......@@ -189,7 +189,7 @@ function Row({
189189 className: cn(
190190 "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",
191191 "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",
193193 layout === "wrap-actions" &&
194194 "@max-[400px]:*:data-[slot=composer-banner-content]:min-h-(--composer-banner-icon-column)",
195195 layout === "wrap-actions-narrow" &&
......@@ -306,15 +306,7 @@ function Count({ className, ...props }: ComponentProps<"span">) {
306306}
307307
308308function Body({ className, ...props }: ComponentProps<"div">) {
309 return (
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 );
309 return <div className={cn("min-w-0 ps-8 sm:ps-7", className)} {...props} />;
318310}
319311
320312function Dot({ className, ...props }: ComponentProps<"span">) {
apps/web/src/components/chat/ComposerBannerStack.tsx+2-2
......@@ -123,7 +123,7 @@ export function ComposerBannerStack({ className, items }: ComposerBannerStackPro
123123 <div
124124 key={frontItem.id}
125125 className={cn(
126 "relative z-10 transition-[translate,opacity] duration-220 ease-in",
126 "relative z-10 transition-[opacity,translate] duration-220 ease-in",
127127 exitingItemId === frontItem.id
128128 ? "pointer-events-none translate-y-16 opacity-0"
129129 : "opacity-100",
......@@ -218,7 +218,7 @@ export function ComposerBannerStack({ className, items }: ComposerBannerStackPro
218218 <div
219219 key={item.id}
220220 className={cn(
221 "transition-[translate,opacity] duration-220 ease-in",
221 "transition-[opacity,translate] duration-220 ease-in",
222222 exitingItemId === item.id
223223 ? "pointer-events-none translate-y-28 opacity-0"
224224 : "opacity-100",
apps/web/src/components/chat/ComposerControl.tsx+3-3
......@@ -16,10 +16,10 @@ export type ComposerControlSize = "sm" | "xs";
1616 */
1717function composerControlClassName(size: ComposerControlSize, className?: string) {
1818 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",
2020 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"
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",
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 [&_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",
2323 "aria-pressed:bg-accent aria-pressed:text-accent-foreground aria-pressed:hover:bg-accent/80",
2424 className,
2525 );
apps/web/src/components/chat/ComposerPendingApprovalPanel.tsx+1-1
......@@ -41,7 +41,7 @@ export const ComposerPendingApprovalPanel = memo(function ComposerPendingApprova
4141 className={cn("flex min-w-0 flex-1 flex-col items-start gap-1", className)}
4242 role="group"
4343 >
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">
4545 <span className="shrink-0 font-medium text-warning">{fallbackLabel}</span>
4646 {approval.appName ? <span className="min-w-0 truncate">{approval.appName}</span> : null}
4747 {pendingCount > 1 ? (
apps/web/src/components/chat/ComposerPendingUserInputPanel.tsx+3-5
......@@ -198,7 +198,7 @@ const ComposerPendingUserInputCard = memo(function ComposerPendingUserInputCard(
198198 </ComposerBanner.Content>
199199 <ComposerBanner.Actions>
200200 {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">
202202 {questionIndex + 1}/{prompt.questions.length}
203203 </span>
204204 ) : null}
......@@ -257,9 +257,7 @@ const ComposerPendingUserInputCard = memo(function ComposerPendingUserInputCard(
257257 <div className="min-w-0 flex-1 flex flex-col gap-0.5">
258258 <span className="text-sm font-medium">{option.label}</span>
259259 {option.description && option.description !== option.label ? (
260 <span className="text-secondary-label text-[11px]">
261 {option.description}
262 </span>
260 <span className="text-secondary-label text-2xs">{option.description}</span>
263261 ) : null}
264262 </div>
265263 {isSelected ? (
......@@ -267,7 +265,7 @@ const ComposerPendingUserInputCard = memo(function ComposerPendingUserInputCard(
267265 ) : shortcutKey !== null ? (
268266 <kbd
269267 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",
271269 )}
272270 >
273271 {shortcutKey}
apps/web/src/components/chat/ComposerPrimaryActions.tsx+2-2
......@@ -91,7 +91,7 @@ export const ComposerPrimaryActions = memo(function ComposerPrimaryActions({
9191 <button
9292 type="button"
9393 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",
9595 insidePendingAction
9696 ? "size-8 sm:size-7"
9797 : hasSendableContent
......@@ -215,7 +215,7 @@ export const ComposerPrimaryActions = memo(function ComposerPrimaryActions({
215215 <button
216216 type="submit"
217217 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",
219219 stageBackdropVariant
220220 ? "bg-transparent text-white enabled:shadow-black/24 enabled:hover:brightness-110"
221221 : "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: {
2525 key={props.pulseKey}
2626 className={cn(
2727 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"
2929 : "text-muted-foreground",
3030 )}
3131 >
apps/web/src/components/chat/ComposerSurface.tsx+10-10
......@@ -19,7 +19,7 @@ function Shell({
1919 "[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)]",
2020 "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))]",
2121 "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)",
2323 "not-supports-[((backdrop-filter:blur(1px))_or_(-webkit-backdrop-filter:blur(1px)))]:before:bg-(--chat-composer-glass-surface)",
2424 "has-data-[composer-banner-surface=attached]:before:hidden",
2525 contextStrip && [
......@@ -37,7 +37,7 @@ function Shell({
3737}
3838
3939const 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)";
4141
4242// The bottom strip continues the outline, so leave the seam between its corners open.
4343const contextSeamClasses =
......@@ -48,7 +48,7 @@ function Host({ className, ...props }: ComponentProps<"div">) {
4848 <div
4949 data-slot="composer-host"
5050 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",
5252 outlineClasses,
5353 contextSeamClasses,
5454 "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">) {
6464 <div
6565 data-chat-composer-main-surface="true"
6666 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",
6868 outlineClasses,
6969 contextSeamClasses,
7070 "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)",
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",
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-composer dark:group-has-data-[composer-banner-surface=attached]/composer-surface:shadow-none",
7373 "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)",
7474 "group-has-data-[composer-banner-surface=attached]/composer-surface:**:data-[chat-composer-mobile-collapsed=true]:min-h-[calc(1rem+1px)]",
7575 className,
......@@ -85,10 +85,10 @@ function ContextStrip({ className, ...props }: ComponentProps<"div">) {
8585 data-slot="composer-context-strip"
8686 className={cn(
8787 "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%)]",
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%)]",
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)",
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)",
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-composer-seam-below dark:before:shadow-composer-dark",
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-(--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)",
9292 className,
9393 )}
9494 {...props}
apps/web/src/components/chat/ComposerTasksBadge.tsx+1-1
......@@ -200,7 +200,7 @@ export const ComposerTasksContent = memo(function ComposerTasksContent({
200200 </ComposerBanner.Content>
201201 <ComposerBanner.Actions>
202202 <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"
204204 data-composer-task-duration="true"
205205 >
206206 {step.durationMs !== undefined
apps/web/src/components/chat/ContextWindowMeter.tsx+6-6
......@@ -92,11 +92,11 @@ export function ContextWindowMeter(props: {
9292 width="sm"
9393 className="text-left whitespace-normal"
9494 >
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)">
9696 <div className="flex items-center justify-between gap-3">
9797 <div className="font-medium text-muted-foreground text-xs">Context Window</div>
9898 {usage.maxTokens !== null && usedPercentage ? (
99 <div className="text-secondary-label text-[11px] tabular-nums">
99 <div className="text-secondary-label text-2xs tabular-nums">
100100 <span>{usedPercentage}</span>
101101 <span className="mx-1">·</span>
102102 <span>
......@@ -105,7 +105,7 @@ export function ContextWindowMeter(props: {
105105 </span>
106106 </div>
107107 ) : (
108 <div className="text-secondary-label text-[11px] tabular-nums">
108 <div className="text-secondary-label text-2xs tabular-nums">
109109 {formatContextWindowTokens(usage.usedTokens)}
110110 </div>
111111 )}
......@@ -126,7 +126,7 @@ export function ContextWindowMeter(props: {
126126 </div>
127127 ) : null}
128128 {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">
130130 <span className="text-secondary-label">Total processed</span>
131131 <span className="font-medium tabular-nums text-secondary-label">
132132 {formatContextWindowTokens(totalProcessedTokens)}
......@@ -134,7 +134,7 @@ export function ContextWindowMeter(props: {
134134 </div>
135135 ) : null}
136136 {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">
138138 {formatContextWindowCompactionMessage(modelDisplayName, usage.autoCompactThreshold)}
139139 </div>
140140 ) : null}
......@@ -151,7 +151,7 @@ export function ContextWindowMeter(props: {
151151 Compact context
152152 </Button>
153153 {compactDisabled && compactDisabledReason ? (
154 <div className="text-pretty text-secondary-label text-[11px]">
154 <div className="text-pretty text-secondary-label text-2xs">
155155 {compactDisabledReason}
156156 </div>
157157 ) : null}
apps/web/src/components/chat/ExpandedImageDialog.tsx+1-1
......@@ -219,7 +219,7 @@ export const ExpandedImageDialog = memo(function ExpandedImageDialog({
219219 accessibilityDetails ? (
220220 <SnapShotAccessibilityData
221221 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"
223223 />
224224 ) : null
225225 ) : item.src === null || failedImageSrc === item.src ? (
apps/web/src/components/chat/MessagesTimeline.tsx+22-22
......@@ -344,7 +344,7 @@ function TimelineLoadEarlierHeader({
344344 fade: boolean;
345345}) {
346346 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"}>
348348 <div className="mx-auto w-full max-w-3xl pb-2">
349349 <button
350350 type="button"
......@@ -1539,7 +1539,7 @@ function TimelineMinimap({
15391539 <span
15401540 aria-hidden="true"
15411541 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",
15431543 activeDistance === 0
15441544 ? "w-6 bg-muted-foreground/75"
15451545 : activeDistance === 1
......@@ -1885,7 +1885,7 @@ function UserVideoAttachment({ file }: { readonly file: ChatFileAttachment }) {
18851885
18861886 if (asset === null && src === null) {
18871887 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">
18891889 {file.name}
18901890 </div>
18911891 );
......@@ -2112,7 +2112,7 @@ function UserTimelineRow({ row }: { row: Extract<TimelineRow, { kind: "message"
21122112 />
21132113 </button>
21142114 ) : (
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">
21162116 {image.name}
21172117 </div>
21182118 )}
......@@ -2756,7 +2756,7 @@ function ReasoningTraceBlock({
27562756 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"
27572757 >
27582758 <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" />
27602760 </span>
27612761 <span
27622762 ref={streaming ? observeVisibleAnimation : undefined}
......@@ -2829,7 +2829,7 @@ const ReasoningTimelineRow = memo(function ReasoningTimelineRow({
28292829 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"
28302830 >
28312831 <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" />
28332833 </span>
28342834 <span className="flex min-w-0 flex-1 items-center gap-1.5">
28352835 <span className="relative min-w-0 flex-1 truncate text-secondary-label text-sm leading-relaxed">
......@@ -3208,7 +3208,7 @@ function LiveActivityContent({
32083208 <ToolActivityIconView
32093209 icon={toolIcon}
32103210 fallbackName={iconName}
3211 className="block size-4 shrink-0 stroke-[1.8]"
3211 className="block size-4 shrink-0 stroke-2"
32123212 muted={!highlighted}
32133213 />
32143214 </span>
......@@ -3329,7 +3329,7 @@ function WorkGroupToggleTimelineRow({
33293329 fallbackName={
33303330 row.summaryToolIcon ?? row.toolSurface ?? toolGroupSummaryIconName(row.summaryKind)
33313331 }
3332 className="size-4 shrink-0 stroke-[1.8]"
3332 className="size-4 shrink-0 stroke-2"
33333333 muted
33343334 />
33353335 </span>
......@@ -3545,7 +3545,7 @@ function UserMessagePreviewAnnotationDetails(props: {
35453545 {props.record.comment}
35463546 </div>
35473547 ) : 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">
35493549 {props.record.targetSummary ? (
35503550 <span className="truncate">{props.record.targetSummary}</span>
35513551 ) : null}
......@@ -3577,7 +3577,7 @@ function UserMessagePreviewAnnotationDetails(props: {
35773577 ) : null}
35783578 </div>
35793579 {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">
35813581 {element.htmlPreview.trim()}
35823582 </pre>
35833583 ) : null}
......@@ -3585,7 +3585,7 @@ function UserMessagePreviewAnnotationDetails(props: {
35853585 );
35863586 })}
35873587 {(props.record.elements?.length ?? 0) > visibleElements.length ? (
3588 <div className="text-secondary-label text-[10px]">
3588 <div className="text-secondary-label text-3xs">
35893589 {(props.record.elements?.length ?? 0) - visibleElements.length} more selected
35903590 elements
35913591 </div>
......@@ -3611,7 +3611,7 @@ function UserMessageElementDetails({
36113611 <div className="truncate text-message-foreground text-xs font-medium">
36123612 {record.pageTitle?.trim() || record.pageUrl}
36133613 </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>
36153615 </div>
36163616 <div className="space-y-2 px-3 py-2.5">
36173617 <div className="flex min-w-0 items-center gap-2 text-xs">
......@@ -4013,7 +4013,7 @@ function UserMessageReviewCommentCard({ comment }: { comment: ReviewCommentConte
40134013 <div className="text-message-foreground text-xs font-medium">
40144014 {formatWorkspaceRelativePath(comment.filePath, ctx.workspaceRoot)}
40154015 </div>
4016 <div className="text-secondary-label text-[11px]">
4016 <div className="text-secondary-label text-2xs">
40174017 {comment.sectionTitle} · {comment.rangeLabel}
40184018 </div>
40194019 </div>
......@@ -4153,7 +4153,7 @@ function ToolActivityIconView(props: {
41534153 muted: boolean;
41544154}) {
41554155 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");
41574157 if (!props.icon) {
41584158 return <WorkEntryIcon name={props.fallbackName} className={fallbackClassName} />;
41594159 }
......@@ -4213,7 +4213,7 @@ function NativeAppToolActivityIcon(props: {
42134213 return (
42144214 <WorkEntryIcon
42154215 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")}
42174217 />
42184218 );
42194219 }
......@@ -4258,14 +4258,14 @@ function ToolActivityImageIcon(props: {
42584258 {displayedSrc === null ? (
42594259 <WorkEntryIcon
42604260 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")}
42624262 />
42634263 ) : null}
42644264 {displayedSrc ? (
42654265 <span
42664266 className={cn(
42674267 props.className,
4268 "inline-block overflow-hidden rounded-[3px] bg-background",
4268 "inline-block overflow-hidden rounded-xs bg-background",
42694269 props.muted && "opacity-70",
42704270 )}
42714271 >
......@@ -4275,7 +4275,7 @@ function ToolActivityImageIcon(props: {
42754275 aria-hidden
42764276 decoding="async"
42774277 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")}
42794279 onError={() => handleLoadError(displayedSrc)}
42804280 />
42814281 </span>
......@@ -4429,7 +4429,7 @@ function buildToolCallExpandedBody(
44294429}
44304430
44314431const 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";
44334433
44344434function workEntryIconName(workEntry: TimelineWorkEntry): WorkEntryIconName {
44354435 if (
......@@ -4640,12 +4640,12 @@ function AgentSpawnMemberRow({
46404640 {agent.title}
46414641 </span>
46424642 {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">
46444644 {role}
46454645 </span>
46464646 ) : null}
46474647 </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">
46494649 {statusLabel}
46504650 </span>
46514651 </div>
......@@ -4821,7 +4821,7 @@ const PlainWorkEntryRow = memo(function PlainWorkEntryRow(props: {
48214821 <ToolActivityIconView
48224822 icon={entryToolIcon}
48234823 fallbackName={entryIconName}
4824 className="block size-4 shrink-0 stroke-[1.8]"
4824 className="block size-4 shrink-0 stroke-2"
48254825 muted
48264826 />
48274827 </span>
apps/web/src/components/chat/ModelListRow.tsx+1-1
......@@ -70,7 +70,7 @@ export const ModelListRow = memo(function ModelListRow(props: {
7070 </div>
7171 {props.showNewBadge ? (
7272 <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"
7474 aria-label="New model"
7575 >
7676 New
apps/web/src/components/chat/ModelPickerSidebar.tsx+3-5
......@@ -123,7 +123,7 @@ export const ModelPickerSidebar = memo(function ModelPickerSidebar(props: {
123123 render={
124124 <Toolbar.Button
125125 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",
127127 )}
128128 onClick={() => handleSelect("favorites")}
129129 type="button"
......@@ -171,7 +171,7 @@ export const ModelPickerSidebar = memo(function ModelPickerSidebar(props: {
171171 const button = (
172172 <Toolbar.Button
173173 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",
175175 isDisabled && "opacity-50 cursor-not-allowed hover:bg-transparent",
176176 )}
177177 data-provider-accent-color={entry.accentColor}
......@@ -210,9 +210,7 @@ export const ModelPickerSidebar = memo(function ModelPickerSidebar(props: {
210210 ? "var(--background)"
211211 : "color-mix(in oklab, var(--muted) 30%, transparent)"
212212 }
213 {...(entry.accentColor
214 ? { badgeClassName: "h-3 min-w-3 px-0.5 text-[7px]" }
215 : {})}
213 {...(entry.accentColor ? { badgeClassName: "h-3 min-w-3 px-0.5 text-3xs" } : {})}
216214 />
217215 {showNewBadge ? (
218216 <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({
7878 {liveAgentCount > 0 ? (
7979 <span
8080 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"
8282 >
8383 {liveAgentCount}
8484 </span>
apps/web/src/components/chat/ProposedPlanCard.tsx+1-1
......@@ -146,7 +146,7 @@ export const ProposedPlanCard = memo(function ProposedPlanCard({
146146 };
147147
148148 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">
150150 <div className="flex flex-wrap items-center justify-between gap-3">
151151 <div className="flex min-w-0 items-center gap-2">
152152 <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: {
3838 {Icon ? (
3939 <Icon className={cn("size-5 shrink-0", props.iconClassName)} aria-hidden />
4040 ) : (
41 <span className={cn("text-[10px] font-semibold leading-none", props.iconClassName)}>
41 <span className={cn("text-3xs font-semibold leading-none", props.iconClassName)}>
4242 {providerInstanceInitials(props.displayName)}
4343 </span>
4444 )}
......@@ -55,9 +55,9 @@ export const ProviderInstanceIcon = memo(function ProviderInstanceIcon(props: {
5555 {props.showBadge ? (
5656 <span
5757 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",
5959 props.accentColor
60 ? "bg-[var(--provider-accent)] text-white"
60 ? "bg-(--provider-accent) text-white"
6161 : "bg-card text-muted-foreground",
6262 props.badgeClassName,
6363 )}
apps/web/src/components/chat/ProviderModelPicker.test.tsx+1-1
......@@ -174,6 +174,6 @@ describe("ProviderModelPicker", () => {
174174 expect(markup).toContain(">CP</span>");
175175 expect(markup).toContain("size-4");
176176 expect(markup).toContain("h-3");
177 expect(markup).toContain("text-[7px]");
177 expect(markup).toContain("text-3xs");
178178 });
179179});
apps/web/src/components/chat/ProviderModelPicker.tsx+3-3
......@@ -229,13 +229,13 @@ export const ProviderModelPicker = memo(function ProviderModelPicker(props: {
229229 driverKind={selection.entry.driverKind}
230230 displayName={selection.entry.displayName}
231231 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))"
233233 iconClassName="size-4"
234234 />
235235 ) : null,
236236 )}
237237 {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))">
239239 +{selectedEntries.length - 3}
240240 </span>
241241 ) : null}
......@@ -250,7 +250,7 @@ export const ProviderModelPicker = memo(function ProviderModelPicker(props: {
250250 iconClassName={cn("size-4", props.activeProviderIconClassName)}
251251 indicatorBackground={props.instanceIndicatorBackground ?? "var(--contrast-input)"}
252252 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",
254254 size === "xs" && "shadow-none",
255255 )}
256256 />
apps/web/src/components/chat/SnapShotAttachmentDetails.tsx+4-4
......@@ -169,7 +169,7 @@ export function SnapShotContentsButton({
169169 {accessibilityDetails ? (
170170 <SnapShotAccessibilityData
171171 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"
173173 />
174174 ) : includesAccessibility ? (
175175 <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({
204204 {source.appIconDataUrl ? (
205205 <img src={source.appIconDataUrl} alt="" className="size-7 shrink-0 rounded-md" />
206206 ) : (
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">
208208 {source.appName.slice(0, 1)}
209209 </div>
210210 )}
211211 <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">
213213 <span className="truncate">{source.appName}</span>
214214 <SnapShotContentsButton source={source} className="pointer-events-auto" />
215215 </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">
217217 {source.windowTitle || "Captured window"}
218218 </div>
219219 </div>
apps/web/src/components/chat/WorktreeSetupCard.tsx+2-2
......@@ -56,7 +56,7 @@ function useNowWhile(active: boolean): number {
5656}
5757
5858function StageIcon({ status }: { status: WorktreeSetupStage["status"] }) {
59 const className = "size-4 shrink-0 stroke-[1.8]";
59 const className = "size-4 shrink-0 stroke-2";
6060 switch (status) {
6161 case "done":
6262 return <CheckIcon aria-hidden className={className} />;
......@@ -240,7 +240,7 @@ function OutputTail({ lines, failed }: { lines: ReadonlyArray<string>; failed: b
240240 return (
241241 <pre
242242 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",
244244 failed
245245 ? "border-destructive/20 bg-error-surface text-destructive-foreground"
246246 : "border-border bg-code text-muted-foreground",
apps/web/src/components/clerk/ClerkUserProfilePage.tsx+2-2
......@@ -22,9 +22,9 @@ export function ClerkUserProfilePage({
2222 <div className={cn("w-full min-w-0 text-foreground", className)}>
2323 <header className="flex flex-col gap-3 pb-4 sm:flex-row sm:items-start sm:justify-between sm:gap-4 sm:pr-8">
2424 <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>
2626 {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">
2828 {description}
2929 </p>
3030 ) : null}
apps/web/src/components/clerk/MobileClientsUserProfilePage.tsx+5-5
......@@ -38,14 +38,14 @@ function MobileClientRow({ device }: { readonly device: RelayClientDeviceRecord
3838 <ClerkUserProfileRow icon={<SmartphoneIcon className="size-4" />}>
3939 <div className="flex flex-col gap-0.5 sm:flex-row sm:items-start sm:justify-between sm:gap-3">
4040 <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">
4242 {device.label}
4343 </h3>
44 <p className="text-xs leading-[1.125rem] text-muted-foreground">
44 <p className="text-xs leading-4.5 text-muted-foreground">
4545 {mobileClientPlatformLabel(device)}
4646 </p>
4747 </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">
4949 {mobileClientUpdatedAtLabel(device.updatedAt)}
5050 </p>
5151 </div>
......@@ -56,7 +56,7 @@ function MobileClientRow({ device }: { readonly device: RelayClientDeviceRecord
5656 />
5757 <MobileClientStatusBadge enabled={device.liveActivities.enabled} label="Live Activities" />
5858 </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">
6060 {mobileClientNotificationDetail(device)}
6161 </p>
6262 </ClerkUserProfileRow>
......@@ -123,7 +123,7 @@ export function MobileClientsUserProfilePage() {
123123 <div>
124124 {devicesState.error ? (
125125 <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"
127127 role="alert"
128128 >
129129 <div>
apps/web/src/components/clerk/T3ConnectUserProfilePage.tsx+7-7
......@@ -51,10 +51,10 @@ export function T3ConnectEnvironmentRow(props: {
5151 <Collapsible open={props.confirmationOpen} onOpenChange={props.onConfirmationChange}>
5252 <div className="flex items-start gap-4">
5353 <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">
5555 {environment.label}
5656 </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">
5858 {linkedAtLabel(environment.linkedAt)} · {endpointLabel(environment)}
5959 </p>
6060 </div>
......@@ -74,13 +74,13 @@ export function T3ConnectEnvironmentRow(props: {
7474 role="group"
7575 aria-label={`Confirm deregistration of ${environment.label}`}
7676 >
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">
7878 Deregister server
7979 </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">
8181 “{environment.label}” will be removed from this account.
8282 </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">
8484 T3 Connect access will be revoked, any managed tunnel will be removed, and a host
8585 space will become available. Local connections on your devices are not changed.
8686 </p>
......@@ -205,7 +205,7 @@ export function T3ConnectUserProfilePage() {
205205 >
206206 <div>
207207 {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">
209209 <p className="font-medium text-destructive-foreground">
210210 Could not load T3 Connect environments
211211 </p>
......@@ -214,7 +214,7 @@ export function T3ConnectUserProfilePage() {
214214 ) : null}
215215
216216 {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">
218218 Loading environments…
219219 </p>
220220 ) : environments.length > 0 ? (
apps/web/src/components/cloud/ConnectCliAuthSurface.tsx+1-3
......@@ -23,9 +23,7 @@ function ConnectCliAuthMessage({
2323 return (
2424 <>
2525 {eyebrow ? (
26 <p className="text-[10px] font-semibold tracking-[0.18em] text-primary uppercase">
27 {eyebrow}
28 </p>
26 <p className="text-3xs font-semibold tracking-widest text-primary uppercase">{eyebrow}</p>
2927 ) : null}
3028 <h1 className="mt-2 text-2xl font-semibold tracking-tight sm:text-3xl">{title}</h1>
3129 <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
269269 <div className="space-y-2 overflow-hidden rounded-lg border border-border/70 bg-background/70 p-3">
270270 <div className="space-y-1">
271271 <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">
273273 {comment.sectionTitle} · {comment.rangeLabel}
274274 </div>
275275 </div>
apps/web/src/components/contextChipParts.tsx+4-4
......@@ -208,8 +208,8 @@ export function ImageChipButton({
208208 <ImageIcon />
209209 )}
210210 <ContextChipLabel className="max-w-72">{middleTruncateAttachmentName(name)}</ContextChipLabel>
211 <span className="shrink-0 text-[10px] text-current">{size}</span>
212 {suffix ? <span className="text-[10px] text-current">{suffix}</span> : null}
211 <span className="shrink-0 text-3xs text-current">{size}</span>
212 {suffix ? <span className="text-3xs text-current">{suffix}</span> : null}
213213 </ContextChip>
214214 );
215215}
......@@ -284,8 +284,8 @@ function FileChipContent(props: {
284284 <ContextChipLabel className="max-w-72">
285285 {middleTruncateAttachmentName(props.name)}
286286 </ContextChipLabel>
287 <span className="shrink-0 text-[10px] text-current">{props.size}</span>
288 {props.suffix ? <span className="text-[10px] text-current">{props.suffix}</span> : null}
287 <span className="shrink-0 text-3xs text-current">{props.size}</span>
288 {props.suffix ? <span className="text-3xs text-current">{props.suffix}</span> : null}
289289 </>
290290 );
291291}
apps/web/src/components/device/DeviceStreamView.tsx+1-1
......@@ -404,7 +404,7 @@ export function DeviceStreamView(props: {
404404 }}
405405 >
406406 {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">
408408 {element.label}
409409 </span>
410410 ) : null}
apps/web/src/components/device/DeviceToolsPanel.tsx+1-1
......@@ -640,7 +640,7 @@ function EventLogSection(props: {
640640 />
641641 </CollapsibleTrigger>
642642 <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">
644644 {entries.length === 0 ? (
645645 <li className="text-muted-foreground">No events yet.</li>
646646 ) : (
apps/web/src/components/diffs/DiffCommentAnnotation.tsx+2-2
......@@ -65,7 +65,7 @@ export function DiffCommentAnnotation({
6565 onPointerDown={(event) => event.stopPropagation()}
6666 >
6767 <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>
6969 {onDelete ? (
7070 <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">
7171 <Button
......@@ -113,7 +113,7 @@ export function DiffCommentAnnotation({
113113 }}
114114 />
115115 <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>
117117 <Button variant="ghost-muted" size="xs" onClick={onCancel}>
118118 Cancel
119119 </Button>
apps/web/src/components/files/FilePreviewPanel.tsx+1-1
......@@ -1172,7 +1172,7 @@ export default function FilePreviewPanel({
11721172 !isMedia &&
11731173 !renderBrowserFile &&
11741174 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">
11761176 Preview limited to the first 1 MB of a {file.data.byteLength.toLocaleString()} byte file.
11771177 </div>
11781178 ) : null}
apps/web/src/components/files/fileSurfaceChrome.tsx+1-1
......@@ -114,7 +114,7 @@ export function FileSurfaceNotice(props: { readonly children: ReactNode }) {
114114 return (
115115 <div
116116 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"
118118 >
119119 {props.children}
120120 </div>
apps/web/src/components/onboarding/WelcomeWizard.tsx+3-5
......@@ -193,7 +193,7 @@ export function WelcomeWizard({
193193 identity={
194194 <div className="flex items-baseline gap-1.5" role="img" aria-label="T3 Code">
195195 <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">
197197 Code
198198 </span>
199199 </div>
......@@ -892,7 +892,7 @@ function AgentInstallTerminal({
892892 className="mt-4 overflow-hidden rounded-lg border border-border/70 bg-background text-foreground"
893893 >
894894 <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">
896896 {setupState === "writeFailed" ? (
897897 <>
898898 Run <code className="rounded bg-muted px-1 font-mono">{command}</code> in this
......@@ -1445,9 +1445,7 @@ function ImportCandidateRow({
14451445 {label}
14461446 </span>
14471447 {secondary !== undefined ? (
1448 <span className="truncate font-mono text-[11px] text-muted-foreground">
1449 {secondary}
1450 </span>
1448 <span className="truncate font-mono text-2xs text-muted-foreground">{secondary}</span>
14511449 ) : null}
14521450 </TooltipTrigger>
14531451 <TooltipPopup variant="code">{candidate.path}</TooltipPopup>
apps/web/src/components/preview/AgentBrowserCursor.tsx+1-1
......@@ -55,7 +55,7 @@ function AgentBrowserCursorEvent(props: {
5555
5656 return (
5757 <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"
5959 style={{
6060 opacity: agentBrowserCursorOpacity(active, controller),
6161 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 }) {
66 <div
77 aria-hidden
88 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",
1010 className,
1111 )}
1212 >
13 <div className="flex gap-[2px]">
13 <div className="flex gap-0.5">
1414 <span className="size-[3px] rounded-full bg-destructive/80" />
1515 <span className="size-[3px] rounded-full bg-warning/80" />
1616 <span className="size-[3px] rounded-full bg-success/80" />
1717 </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">
1919 <span className="h-[2px] w-full rounded-full bg-muted-foreground/30" />
2020 <span className="h-[2px] w-3/5 rounded-full bg-muted-foreground/20" />
2121 </div>
apps/web/src/components/preview/PreviewPanelShell.tsx+1-1
......@@ -126,7 +126,7 @@ export function PreviewPanelShell(props: {
126126 : "shrink-0 border-l border-border"
127127 : "w-full",
128128 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",
130130 collapsible && open && "[[data-panel-animations=true]_&]:starting:w-0!",
131131 collapsible && !open && "pointer-events-none",
132132 )}
apps/web/src/components/pullRequest/PullRequestCodeTab.tsx+2-2
......@@ -828,7 +828,7 @@ function PullRequestCodeTab({
828828 <PullRequestDiffStat
829829 additions={additions}
830830 deletions={deletions}
831 className="font-mono text-[11px]"
831 className="font-mono text-2xs"
832832 />
833833 );
834834 const viewedFiles = filesViewedRef.current;
......@@ -842,7 +842,7 @@ function PullRequestCodeTab({
842842 attribute is what the header's capture listener looks for. */}
843843 <label
844844 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"
846846 onClick={(event) => event.stopPropagation()}
847847 >
848848 <Checkbox
apps/web/src/components/pullRequest/PullRequestComposer.tsx+1-1
......@@ -93,7 +93,7 @@ export function PullRequestComposer({
9393 {pendingComments.length > 0 ? (
9494 <span
9595 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"
9797 >
9898 {pendingComments.length}
9999 </span>
apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx+4-4
......@@ -2260,7 +2260,7 @@ export function PullRequestDetailPanel({
22602260 <span className="shrink-0">{formatRelativeTimeLabel(detail.updatedAt)}</span>
22612261 </span>
22622262 <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">
22642264 {/* An out-of-date base wears the warning on the branch name itself, so the
22652265 name is amber and pointing at either the name or the mark opens the way
22662266 out. Up to date, the name keeps its plain tooltip. */}
......@@ -2322,7 +2322,7 @@ export function PullRequestDetailPanel({
23222322 <TooltipPopup side="top">{detail.headBranch}</TooltipPopup>
23232323 </Tooltip>
23242324 </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">
23262326 <span
23272327 className="inline-flex items-center gap-1 tabular-nums"
23282328 aria-label={`${detail.changedFiles.toLocaleString()} changed ${
......@@ -2335,7 +2335,7 @@ export function PullRequestDetailPanel({
23352335 <PullRequestDiffStat
23362336 additions={detail.additions}
23372337 deletions={detail.deletions}
2338 className="shrink-0 font-mono text-[11px]"
2338 className="shrink-0 font-mono text-2xs"
23392339 />
23402340 </span>
23412341 </div>
......@@ -2609,7 +2609,7 @@ export function PullRequestDetailPanel({
26092609 <div className="ml-auto flex shrink-0 items-center gap-2 text-xs text-muted-foreground">
26102610 <PullRequestMetaLine
26112611 className={cn(
2612 "whitespace-nowrap text-[11px] transition-opacity",
2612 "whitespace-nowrap text-2xs transition-opacity",
26132613 (activityPending || activityError) && "opacity-35",
26142614 )}
26152615 >
apps/web/src/components/pullRequest/PullRequestLinkPreview.tsx+1-1
......@@ -106,7 +106,7 @@ export function PullRequestLinkPreview({
106106 ))
107107 ) : (
108108 <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">
110110 <span className="min-w-0 truncate">{detail.repository}</span>
111111 <span className="shrink-0">#{detail.number}</span>
112112 <span aria-hidden>·</span>
apps/web/src/components/pullRequest/PullRequestListRow.tsx+4-4
......@@ -68,7 +68,7 @@ export function PullRequestRowGlyph({
6868 />
6969 </span>
7070 </span>
71 {below ? <span className="inline-flex text-[11px]">{below}</span> : null}
71 {below ? <span className="inline-flex text-2xs">{below}</span> : null}
7272 </span>
7373 );
7474}
......@@ -100,15 +100,15 @@ export function PullRequestRowLines({
100100 {number}
101101 <span className="min-w-0 truncate text-sm">{title}</span>
102102 {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>
104104 ) : null}
105105 {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>
107107 ) : null}
108108 </span>
109109 <span
110110 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",
112112 metaClassName,
113113 )}
114114 >
apps/web/src/components/pullRequest/PullRequestRow.tsx+1-1
......@@ -204,7 +204,7 @@ function PullRequestRowImpl({
204204 <Tooltip>
205205 <TooltipTrigger
206206 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" />
208208 }
209209 >
210210 <span className="sr-only">matched in the description</span>
apps/web/src/components/pullRequest/PullRequestSummaryTab.tsx+2-2
......@@ -401,7 +401,7 @@ function CommentGroup({
401401 </span>
402402 ))}
403403 {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">
405405 +{authors.length - 3}
406406 </span>
407407 ) : null}
......@@ -412,7 +412,7 @@ function CommentGroup({
412412 >
413413 <span className="min-w-0 flex-1 space-y-1">
414414 <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">
416416 <span>
417417 {authors.length} {authors.length === 1 ? "author" : "authors"}
418418 </span>
apps/web/src/components/pullRequest/PullRequestTimelineTab.tsx+8-10
......@@ -141,7 +141,7 @@ function ActorTimelineMarker({
141141 <PullRequestActorAvatar
142142 actor={actor}
143143 className={cn(
144 "size-7 bg-muted text-[9px] transition-opacity",
144 "size-7 bg-muted text-3xs transition-opacity",
145145 muted && "opacity-45 grayscale",
146146 )}
147147 />
......@@ -156,9 +156,7 @@ function friendlyReviewState(value: string): string {
156156
157157function ReviewStateBadge({ state }: { state: string }) {
158158 return (
159 <span className="text-[10px] font-medium text-muted-foreground">
160 {friendlyReviewState(state)}
161 </span>
159 <span className="text-3xs font-medium text-muted-foreground">{friendlyReviewState(state)}</span>
162160 );
163161}
164162
......@@ -224,7 +222,7 @@ function ConversationCard({
224222 <span className="text-muted-foreground">{event.title}</span>
225223 {event.reviewState ? <ReviewStateBadge state={event.reviewState} /> : null}
226224 </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">
228226 <span>{formatRelativeTimeLabel(event.at)}</span>
229227 {event.path ? (
230228 <span className="inline-flex min-w-0 items-center gap-1">
......@@ -330,7 +328,7 @@ function ConversationGroup({
330328 <span className="block text-xs font-semibold">
331329 {events.length.toLocaleString()} {events.length === 1 ? "comment" : "comments"}
332330 </span>
333 <span className="block truncate text-[10px] text-muted-foreground">
331 <span className="block truncate text-3xs text-muted-foreground">
334332 {actors.length.toLocaleString()} {actors.length === 1 ? "author" : "authors"} ·{" "}
335333 {formatRelativeTimeLabel(first.at)}
336334 </span>
......@@ -391,7 +389,7 @@ function CommitEvent({
391389 <div className="truncate text-xs font-semibold text-foreground transition-colors group-hover:text-primary">
392390 {event.body ?? "Untitled commit"}
393391 </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">
395393 <code className="font-mono">{event.id.slice(0, 7)}</code>
396394 <span>{formatRelativeTimeLabel(event.at)}</span>
397395 </div>
......@@ -400,7 +398,7 @@ function CommitEvent({
400398 <PullRequestDiffStat
401399 additions={event.additions}
402400 deletions={event.deletions}
403 className="ml-auto shrink-0 font-mono text-[10px]"
401 className="ml-auto shrink-0 font-mono text-3xs"
404402 />
405403 ) : null}
406404 </div>
......@@ -433,7 +431,7 @@ function LifecycleEvent({ event }: { event: PullRequestTimelineEvent }) {
433431 {event.actor ? <ActorName actor={event.actor} /> : null}
434432 <span className="font-semibold text-foreground">{presentation.label}</span>
435433 </div>
436 <div className="mt-0.5 text-[11px] text-muted-foreground">
434 <div className="mt-0.5 text-2xs text-muted-foreground">
437435 {formatRelativeTimeLabel(event.at)}
438436 </div>
439437 </div>
......@@ -500,7 +498,7 @@ function ReviewVerdictEvent({
500498 </Tooltip>
501499 </div>
502500 <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">
504502 <span>{formatRelativeTimeLabel(event.at)}</span>
505503 {event.path ? (
506504 <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
308308 ))}
309309 </div>
310310 </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">
312312 <span>
313313 {openCount} open · {links.length} linked
314314 {lastSynced ? ` · synced ${formatRelativeTimeLabel(lastSynced)}` : ""}
apps/web/src/components/pullRequest/pullRequestPresentation.tsx+1-1
......@@ -428,7 +428,7 @@ export function PullRequestActorAvatar({
428428 <span
429429 aria-hidden
430430 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",
432432 className,
433433 )}
434434 >
apps/web/src/components/search/HighlightedSearchLine.tsx+1-1
......@@ -111,7 +111,7 @@ function HighlightedTokens(props: {
111111 .map((segment) =>
112112 segment.isMatch ? (
113113 <mark
114 className="rounded-[2px] bg-primary/25 text-inherit"
114 className="rounded-xs bg-primary/25 text-inherit"
115115 key={`${segment.start}:${segment.end}:match`}
116116 style={tokenStyle(segment.token)}
117117 >
apps/web/src/components/search/ProjectContentSearchDialog.tsx+1-1
......@@ -265,7 +265,7 @@ function OpenContentSearchDialog(props: {
265265 {path.directory}
266266 </span>
267267 ) : 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">
269269 {group.matches.length}
270270 </span>
271271 </div>
apps/web/src/components/settings/AddProviderInstanceDialog.tsx+4-4
......@@ -310,7 +310,7 @@ export function AddProviderInstanceDialog({
310310 value={label}
311311 onChange={(event) => setLabel(event.target.value)}
312312 />
313 <span className="text-[11px] text-muted-foreground">
313 <span className="text-2xs text-muted-foreground">
314314 Shown in the provider list. Optional.
315315 </span>
316316 </label>
......@@ -326,9 +326,9 @@ export function AddProviderInstanceDialog({
326326 aria-invalid={showInstanceIdError}
327327 />
328328 {showInstanceIdError ? (
329 <span className="text-[11px] text-destructive">{instanceIdError}</span>
329 <span className="text-2xs text-destructive">{instanceIdError}</span>
330330 ) : (
331 <span className="text-[11px] text-muted-foreground">
331 <span className="text-2xs text-muted-foreground">
332332 Routing key used by threads and sessions. Letters, digits, '-', or '_'.
333333 </span>
334334 )}
......@@ -374,7 +374,7 @@ export function AddProviderInstanceDialog({
374374 </Button>
375375 ) : null}
376376 </div>
377 <span className="text-[11px] text-muted-foreground">
377 <span className="text-2xs text-muted-foreground">
378378 Optional marker shown in the picker.
379379 </span>
380380 </div>
apps/web/src/components/settings/ConnectionsSettings.tsx+10-10
......@@ -771,11 +771,11 @@ const PairingLinkListRow = memo(function PairingLinkListRow({
771771 <AccessScopeSummary scopes={pairingLink.scopes} label="Pairing link scopes" />
772772 </p>
773773 {!credential ? (
774 <p className="text-[11px] text-muted-foreground/70">
774 <p className="text-2xs text-muted-foreground/70">
775775 Create a new link to share from this client.
776776 </p>
777777 ) : shareablePairingUrl === null ? (
778 <p className="text-[11px] text-muted-foreground/70">
778 <p className="text-2xs text-muted-foreground/70">
779779 Copy the token and pair from another client using this backend&apos;s reachable host.
780780 </p>
781781 ) : null}
......@@ -882,7 +882,7 @@ const PairingLinkListRow = memo(function PairingLinkListRow({
882882 role="radiogroup"
883883 aria-label="Endpoint the pairing QR code and URL use"
884884 >
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>
886886 {endpointCopyOptions.map((option) => {
887887 const isSelected = option.id === selectedQrOption?.id;
888888 return (
......@@ -907,7 +907,7 @@ const PairingLinkListRow = memo(function PairingLinkListRow({
907907 >
908908 {option.label}
909909 </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">
911911 {option.detail}
912912 </span>
913913 </button>
......@@ -919,7 +919,7 @@ const PairingLinkListRow = memo(function PairingLinkListRow({
919919 <Tooltip>
920920 <TooltipTrigger
921921 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">
923923 {qrPairingUrl}
924924 </code>
925925 }
......@@ -951,7 +951,7 @@ const PairingLinkListRow = memo(function PairingLinkListRow({
951951 </div>
952952 ) : (
953953 <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">
955955 No QR for this endpoint. Another device scanning a loopback link would dial itself;
956956 copy the URL for use on this machine instead.
957957 </p>
......@@ -1011,7 +1011,7 @@ const ConnectedClientListRow = memo(function ConnectedClientListRow({
10111011 />
10121012 <h3 className="text-sm font-medium text-foreground">{primaryLabel}</h3>
10131013 {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">
10151015 This device
10161016 </span>
10171017 ) : null}
......@@ -1335,14 +1335,14 @@ const AdvertisedEndpointListRow = memo(function AdvertisedEndpointListRow({
13351335 </Tooltip>
13361336 ) : null}
13371337 {!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">
13391339 Setup required
13401340 </span>
13411341 ) : null}
13421342 </div>
13431343 <div className="ml-auto flex min-h-6 shrink-0 items-center justify-end gap-2">
13441344 {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">
13461346 Default
13471347 </span>
13481348 ) : null}
......@@ -2660,7 +2660,7 @@ export function ConnectionsSettings() {
26602660 </label>
26612661 </div>
26622662 <div>
2663 <span className="mt-1 block text-[11px] text-muted-foreground">
2663 <span className="mt-1 block text-2xs text-muted-foreground">
26642664 Paste a full pairing URL here to fill both fields automatically.
26652665 </span>
26662666 </div>
apps/web/src/components/settings/CustomModelEditor.tsx+2-2
......@@ -169,7 +169,7 @@ export function CustomModelEditor({
169169 className="min-w-0 flex-1"
170170 aria-label="Choice label"
171171 />
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">
173173 <Switch
174174 size="sm"
175175 checked={choice.isDefault}
......@@ -201,7 +201,7 @@ export function CustomModelEditor({
201201 className="flex flex-col gap-2 rounded-md border border-border/60 bg-background/40 p-2.5"
202202 >
203203 <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>
205205 {presets.length > 0 ? (
206206 <Select
207207 value={idSelectValue(descriptor)}
apps/web/src/components/settings/DiagnosticsSettings.tsx+10-10
......@@ -94,7 +94,7 @@ function StatBlock({
9494}) {
9595 return (
9696 <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">
9898 <span className="min-w-0 truncate">{label}</span>
9999 {tooltip ? (
100100 <Tooltip>
......@@ -183,7 +183,7 @@ function DiagnosticsTable({
183183 ))}
184184 </colgroup>
185185 ) : 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">
187187 <tr>
188188 {headers.map((header, index) => (
189189 <th
......@@ -215,7 +215,7 @@ function TraceIdCell({ traceId }: { traceId: string }) {
215215 <Tooltip>
216216 <TooltipTrigger
217217 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">
219219 {shortenTraceId(traceId)}
220220 </span>
221221 }
......@@ -362,7 +362,7 @@ function ProcessDiagnosticsTable({
362362 <col className="w-[11%]" />
363363 <col className="w-[6%]" />
364364 </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">
366366 <tr>
367367 <th className="px-4 py-2 font-semibold sm:pl-5">Name</th>
368368 <th className="px-3 py-2 text-right font-semibold">CPU</th>
......@@ -588,7 +588,7 @@ function ProcessResourceHistoryTable({
588588 <col className="w-[16%]" />
589589 <col className="w-[10%]" />
590590 </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">
592592 <tr>
593593 <th className="px-4 py-2 font-semibold sm:pl-5">Process</th>
594594 <th className="px-3 py-2 text-right font-semibold">CPU Time</th>
......@@ -662,15 +662,15 @@ function DiagnosticsLastChecked({ checkedAt }: { checkedAt: DateTime.Utc | null
662662 const relative = getRelativeTimeState(checkedAt ? DateTime.formatIso(checkedAt) : null);
663663
664664 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>;
666666 }
667667
668668 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>;
670670 }
671671
672672 return (
673 <span className="text-[11px] text-muted-foreground/60">
673 <span className="text-2xs text-muted-foreground/60">
674674 {relative.suffix ? (
675675 <>
676676 Checked <span className="font-mono tabular-nums">{relative.value}</span> {relative.suffix}
......@@ -1222,7 +1222,7 @@ export function DiagnosticsSettingsPanel() {
12221222 <col className="w-[26%]" />
12231223 <col className="w-[30%]" />
12241224 </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">
12261226 <tr>
12271227 <th className="whitespace-nowrap px-4 py-2.5 font-semibold sm:pl-5">Time</th>
12281228 <th className="whitespace-nowrap px-4 py-2.5 font-semibold">Level</th>
......@@ -1241,7 +1241,7 @@ export function DiagnosticsSettingsPanel() {
12411241 {formatRelativeNoWrap(event.seenAt)}
12421242 </td>
12431243 <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">
12451245 {event.level}
12461246 </span>
12471247 </td>
apps/web/src/components/settings/FontFamilyPicker.tsx+1-3
......@@ -173,9 +173,7 @@ export function FontFamilyPicker({
173173 {family}
174174 </span>
175175 <span className="flex shrink-0 items-center gap-1.5">
176 {isDefault ? (
177 <span className="text-[10px] text-muted-foreground/60">default</span>
178 ) : null}
176 {isDefault ? <span className="text-3xs text-muted-foreground/60">default</span> : null}
179177 {item === selectedValue ? (
180178 <CheckIcon className="size-3.5 text-muted-foreground" />
181179 ) : null}
apps/web/src/components/settings/KeybindingsSettings.tsx+8-8
......@@ -255,7 +255,7 @@ function WarningTooltipIcon({
255255 tabIndex={focusable ? 0 : undefined}
256256 aria-label={label}
257257 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",
259259 className,
260260 )}
261261 />
......@@ -668,7 +668,7 @@ function WhenExpressionBuilder({
668668 ) : null}
669669 </InputGroup>
670670 {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">
672672 <CircleXIcon className="size-3.5" />
673673 {parseError}
674674 </div>
......@@ -698,7 +698,7 @@ function WhenExpressionBuilder({
698698 </div>
699699 )}
700700 {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">
702702 Fix the expression above to continue editing visually.
703703 </div>
704704 ) : null}
......@@ -842,7 +842,7 @@ function KeybindingKeyControl({
842842 onClick={() => setDraft({ isRecording: true })}
843843 aria-label={`Edit shortcut for ${commandLabel(row.command)}: ${formatShortcutLabel(row.binding.shortcut)}`}
844844 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",
846846 pillClassName,
847847 )}
848848 >
......@@ -989,7 +989,7 @@ function KeybindingRowWhen({
989989}) {
990990 return (
991991 <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>
993993 <WhenClauseControl
994994 label={commandLabel(row.command)}
995995 expression={editor.whenDraftExpression}
......@@ -1234,7 +1234,7 @@ function NewKeybindingSettingsRow(props: NewKeybindingProps) {
12341234 title="New keybinding"
12351235 description={
12361236 <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>
12381238 <NewKeybindingWhen draft={draft} variables={variables} />
12391239 </span>
12401240 }
......@@ -1312,7 +1312,7 @@ function KeybindingsList(props: KeybindingsListProps) {
13121312/** Shown in the browser build only; the desktop app receives every shortcut. */
13131313function BrowserKeybindingNotice() {
13141314 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">
13161316 <TriangleAlertIcon className="size-3.5 shrink-0 text-warning" aria-hidden />
13171317 <span>
13181318 Some shortcuts may be claimed by the browser before T3 Code sees them. Use the desktop app
......@@ -1488,7 +1488,7 @@ export function KeybindingsSettingsPanel() {
14881488 const cancelAdd = useCallback(() => setIsAddingBinding(false), []);
14891489
14901490 const bindingsCount = (
1491 <span className="text-[11px] text-muted-foreground">
1491 <span className="text-2xs text-muted-foreground">
14921492 {rows.length + (isAddingBinding ? 1 : 0)}{" "}
14931493 {rows.length + (isAddingBinding ? 1 : 0) === 1 ? "binding" : "bindings"}
14941494 </span>
apps/web/src/components/settings/OpenSourceLicenses.tsx+1-1
......@@ -179,7 +179,7 @@ function LicenseManifestError({ message, onRetry }: { message: string; onRetry:
179179 <div className="flex flex-col items-start gap-3 px-3 py-5 sm:px-4">
180180 <div className="flex flex-col gap-1">
181181 <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">
183183 {message}
184184 </p>
185185 </div>
apps/web/src/components/settings/PanelAnimationsPreview.tsx+1-1
......@@ -5,7 +5,7 @@ import { cn } from "~/lib/utils";
55export function PanelAnimationsPreview({ durationMs }: { durationMs: number }) {
66 const [panelsOpen, setPanelsOpen] = useState(true);
77 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";
99
1010 return (
1111 <button
apps/web/src/components/settings/ProjectActionsList.tsx+2-2
......@@ -34,12 +34,12 @@ export function ProjectActionsList({
3434 <ScriptIcon icon={script.icon} className="size-4 shrink-0 text-muted-foreground" />
3535 <span className="min-w-0 truncate">{script.name}</span>
3636 {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">
3838 setup
3939 </span>
4040 ) : null}
4141 {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">
4343 preview · desktop only
4444 </span>
4545 ) : null}
apps/web/src/components/settings/ProviderInstanceCard.test.ts+1-1
......@@ -118,7 +118,7 @@ describe("deriveProviderModelsForDisplay", () => {
118118
119119 expect(markup).toContain("Authenticated as");
120120 expect(markup).toContain('aria-label="Toggle account email visibility"');
121 expect(markup).toContain("blur-[2px]");
121 expect(markup).toContain("blur-xs");
122122 expect(markup).not.toContain("developer@example.com");
123123 });
124124 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({
570570 showBadge={Boolean(accentColor)}
571571 className="size-5"
572572 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"
574574 />
575575 ) : FallbackIconComponent ? (
576576 <span className="inline-flex size-5 shrink-0 items-center justify-center">
......@@ -578,7 +578,7 @@ export function ProviderInstanceCard({
578578 </span>
579579 ) : (
580580 <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"
582582 aria-hidden
583583 >
584584 {providerInstanceInitials(displayName)}
......@@ -655,7 +655,7 @@ export function ProviderInstanceCard({
655655 <span className="flex min-w-0 items-center gap-2">
656656 <span className="truncate text-sm font-medium text-foreground">{displayName}</span>
657657 {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">
659659 {instanceId}
660660 </code>
661661 ) : null}
......@@ -708,7 +708,7 @@ export function ProviderInstanceCard({
708708 )
709709 ) : null}
710710 </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">
712712 {statusDotNode ? (
713713 <span className="flex h-[1.45em] shrink-0 items-center">{statusDotNode}</span>
714714 ) : null}
......@@ -775,7 +775,7 @@ export function ProviderInstanceCard({
775775 <PopoverPopup side="bottom" align="end" width="md">
776776 <div className="grid min-w-0 gap-3">
777777 <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">
779779 {versionAdvisory.title}
780780 </p>
781781 <p
......@@ -807,7 +807,7 @@ export function ProviderInstanceCard({
807807 </Button>
808808 ) : null}
809809 {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">
811811 <span aria-hidden className="h-px flex-1 bg-border" />
812812 or, update manually using
813813 <span aria-hidden className="h-px flex-1 bg-border" />
......@@ -815,7 +815,7 @@ export function ProviderInstanceCard({
815815 ) : null}
816816 {updateCommand ? (
817817 <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">
819819 {updateCommand}
820820 </code>
821821 <Tooltip>
apps/web/src/components/settings/ProviderModelsSection.tsx+4-4
......@@ -470,19 +470,19 @@ export function ProviderModelsSection({
470470 <span className="flex min-w-0 items-baseline gap-2">
471471 <span className={cn(nameClassName, "truncate")}>{model.name}</span>
472472 {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">
474474 {model.slug}
475475 </code>
476476 ) : null}
477477 {model.isCustom ? (
478 <span className="text-[11px] text-muted-foreground/70">custom</span>
478 <span className="text-2xs text-muted-foreground/70">custom</span>
479479 ) : null}
480480 </span>
481481 {/*
482482 Always a grid item so the columns line up across rows; the text
483483 itself drops out on phone widths where it would starve the name.
484484 */}
485 <span className="text-[11px] text-muted-foreground/70">
485 <span className="text-2xs text-muted-foreground/70">
486486 {capLabels.length > 0 ? (
487487 <span className="hidden sm:inline">{capLabels.join(" · ")}</span>
488488 ) : null}
......@@ -494,7 +494,7 @@ export function ProviderModelsSection({
494494 };
495495
496496 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")}>
498498 {label}
499499 </div>
500500 );
apps/web/src/components/settings/ProviderSettingsForm.tsx+1-1
......@@ -240,7 +240,7 @@ function ProviderSettingsFieldRow({
240240 const inputId = `${idPrefix}-${field.key}`;
241241 const descriptionClassName =
242242 variant === "dialog"
243 ? "text-[11px] text-muted-foreground"
243 ? "text-2xs text-muted-foreground"
244244 : "mt-1 block text-xs text-muted-foreground";
245245 const label = <span className="text-xs font-medium text-foreground">{field.label}</span>;
246246 const description = field.description ? (
apps/web/src/components/settings/RedactedSensitiveText.tsx+2-2
......@@ -44,8 +44,8 @@ export function RedactedSensitiveText(props: {
4444 <button
4545 type="button"
4646 className={cn(
47 "min-w-0 cursor-pointer rounded-sm font-mono text-[11px] leading-normal transition hover:text-foreground",
48 revealed ? "text-muted-foreground" : "select-none text-muted-foreground blur-[2px]",
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-xs",
4949 props.className,
5050 )}
5151 onClick={() => setRevealed((current) => !current)}
apps/web/src/components/settings/ResourceTelemetryDiagnostics.tsx+35-35
......@@ -194,7 +194,7 @@ function SourceStatusBadge({
194194 return (
195195 <span
196196 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",
198198 tone === "neutral" && "border-border/70 bg-muted/45 text-muted-foreground",
199199 tone === "default" && "border-success/25 bg-success/10 text-success-foreground",
200200 tone === "warning" && "border-warning/30 bg-warning/10 text-warning-foreground",
......@@ -218,14 +218,14 @@ function SourceStatusBadge({
218218function LastSampleLabel({ sampledAt }: { sampledAt: DateTime.Utc | null }) {
219219 useRelativeTimeTick();
220220 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>;
222222 }
223223 const relative = formatRelativeTime(DateTime.formatIso(sampledAt));
224224 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>;
226226 }
227227 return (
228 <span className="text-[11px] text-muted-foreground/60">
228 <span className="text-2xs text-muted-foreground/60">
229229 Updated <span className="font-mono tabular-nums">{relative.value}</span>
230230 {relative.suffix ? ` ${relative.suffix}` : ""}
231231 </span>
......@@ -247,7 +247,7 @@ function IconStat({
247247}) {
248248 return (
249249 <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">
251251 <span className="text-muted-foreground/55 transition-colors group-hover:text-foreground/65">
252252 {icon}
253253 </span>
......@@ -255,7 +255,7 @@ function IconStat({
255255 </div>
256256 <div
257257 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",
259259 tone === "warning" && "text-warning-foreground",
260260 tone === "danger" && "text-destructive",
261261 )}
......@@ -263,7 +263,7 @@ function IconStat({
263263 {value}
264264 </div>
265265 {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>
267267 ) : null}
268268 </div>
269269 );
......@@ -282,10 +282,10 @@ function AggregateCard({
282282 <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">
283283 <span className={cn("absolute inset-x-5 top-0 h-0.5 rounded-full opacity-75", accentClass)} />
284284 <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">
286286 {label}
287287 </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">
289289 {aggregate.processCount} {aggregate.processCount === 1 ? "process" : "processes"}
290290 </div>
291291 </div>
......@@ -302,7 +302,7 @@ function AggregateCard({
302302function MetricPair({ label, value }: { label: string; value: string }) {
303303 return (
304304 <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">
306306 {label}
307307 </div>
308308 <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
319319 return (
320320 <div className="flex items-start justify-between gap-4 border-t border-border/50 py-3 first:border-t-0">
321321 <div className="min-w-0">
322 <div className="text-[13px] font-medium text-foreground">{label}</div>
323 <div className="mt-1 text-[11px] leading-relaxed text-muted-foreground/65">
322 <div className="text-sm font-medium text-foreground">{label}</div>
323 <div className="mt-1 text-2xs leading-relaxed text-muted-foreground/65">
324324 {expectedInBrowser
325325 ? "Available when this page runs inside the desktop app."
326326 : Option.match(health.lastError, {
......@@ -356,10 +356,10 @@ function DetailRow({
356356}) {
357357 return (
358358 <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>
360360 <span
361361 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",
363363 valueClassName,
364364 )}
365365 >
......@@ -405,7 +405,7 @@ function ResourceHistoryChart({
405405
406406 return (
407407 <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">
409409 <span className="inline-flex items-center gap-1.5">
410410 <span className="h-1.5 w-3 rounded-full bg-foreground/70" /> CPU average
411411 </span>
......@@ -529,7 +529,7 @@ function ProcessActions({
529529 onSignal: (process: ResourceTelemetryProcess, signal: ServerProcessSignal) => void;
530530}) {
531531 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>;
533533 }
534534 const isSignaling = signalingKeys.has(processIdentityKey(process));
535535 return (
......@@ -586,7 +586,7 @@ function ProcessTable({
586586 <col className="w-[6%]" />
587587 <col className="w-[4%]" />
588588 </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">
590590 <tr>
591591 <th className="px-4 py-2 font-semibold sm:pl-5">Process</th>
592592 <th className="px-3 py-2 font-semibold">Category</th>
......@@ -618,7 +618,7 @@ function ProcessTable({
618618 onToggle={toggle}
619619 />
620620 </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">
622622 {categoryLabel(process.category)}
623623 </td>
624624 <td className="px-3 py-2 text-right font-mono tabular-nums">
......@@ -689,7 +689,7 @@ function HistoryProcessTable({
689689 <col className="w-[7%]" />
690690 <col className="w-[5%]" />
691691 </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">
693693 <tr>
694694 <th className="px-4 py-2 font-semibold sm:pl-5">Process</th>
695695 <th className="px-3 py-2 font-semibold">Category</th>
......@@ -726,7 +726,7 @@ function HistoryProcessTable({
726726 </TooltipPopup>
727727 </Tooltip>
728728 </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">
730730 {categoryLabel(process.category)}
731731 </td>
732732 <td className="px-3 py-2 text-right font-mono tabular-nums">
......@@ -771,7 +771,7 @@ function AttributionTable({ entries }: { entries: ReadonlyArray<ResourceAttribut
771771 <col className="w-[10%]" />
772772 <col className="w-[12%]" />
773773 </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">
775775 <tr>
776776 <th className="px-4 py-2 font-semibold sm:pl-5">Component</th>
777777 <th className="px-3 py-2 font-semibold">Operation</th>
......@@ -983,10 +983,10 @@ export function ResourceTelemetryDiagnostics({
983983 </div>
984984 }
985985 >
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">
987987 <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">
988988 <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">
990990 T3 system footprint
991991 </div>
992992 <p className="mt-1 max-w-xl text-xs leading-relaxed text-muted-foreground">
......@@ -994,7 +994,7 @@ export function ResourceTelemetryDiagnostics({
994994 the monitor itself.
995995 </p>
996996 </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">
998998 <span className="size-1.5 rounded-full bg-success" />
999999 Sampling every {snapshot ? formatSampleInterval(snapshot.sampleIntervalMs) : "..."}
10001000 </div>
......@@ -1091,9 +1091,9 @@ export function ResourceTelemetryDiagnostics({
10911091 ) : null
10921092 }
10931093 >
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">
10951095 <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">
10971097 <span className="flex size-6 items-center justify-center rounded-md bg-muted/60">
10981098 <BatteryIcon className="size-3.5" />
10991099 </span>
......@@ -1150,10 +1150,10 @@ export function ResourceTelemetryDiagnostics({
11501150 </>
11511151 ) : (
11521152 <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">
11541154 Desktop host signals not connected
11551155 </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">
11571157 Power, idle, lock, and thermal state are supplied by the desktop host. Process
11581158 telemetry remains fully active in this browser session.
11591159 </p>
......@@ -1161,7 +1161,7 @@ export function ResourceTelemetryDiagnostics({
11611161 )}
11621162 </div>
11631163 <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">
11651165 <span className="flex size-6 items-center justify-center rounded-md bg-muted/60">
11661166 <GaugeIcon className="size-3.5" />
11671167 </span>
......@@ -1228,7 +1228,7 @@ export function ResourceTelemetryDiagnostics({
12281228 </div>
12291229 }
12301230 >
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">
12321232 {history.error ? (
12331233 <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">
12341234 <AlertTriangleIcon className="mt-0.5 size-3.5 shrink-0" />
......@@ -1245,13 +1245,13 @@ export function ResourceTelemetryDiagnostics({
12451245 icon={<CpuIcon className="size-4 text-muted-foreground" />}
12461246 headerAction={
12471247 snapshot ? (
1248 <span className="text-[10px] text-muted-foreground/55">
1248 <span className="text-3xs text-muted-foreground/55">
12491249 Identity: <span className="font-mono">PID + start time</span>
12501250 </span>
12511251 ) : null
12521252 }
12531253 >
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">
12551255 <ProcessTable
12561256 processes={snapshot?.processes ?? []}
12571257 signalingKeys={signalingKeys}
......@@ -1264,11 +1264,11 @@ export function ResourceTelemetryDiagnostics({
12641264 title="Instrumented application I/O"
12651265 icon={<DatabaseIcon className="size-4 text-muted-foreground" />}
12661266 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>
12681268 }
12691269 >
1270 <div className="overflow-hidden rounded-2xl border border-border/70 bg-card shadow-[0_1px_1px_rgb(0_0_0/0.03)]">
1271 <div className="bg-muted/15 px-4 py-3 text-[11px] leading-relaxed text-muted-foreground sm:px-5">
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-2xs leading-relaxed text-muted-foreground sm:px-5">
12721272 Native counters identify which process is reading or writing. These application-level
12731273 counters identify known T3 operations so process spikes can be correlated with specific
12741274 persistence and logging paths.
apps/web/src/components/settings/SettingsPanels.tsx+4-4
......@@ -264,7 +264,7 @@ function AboutVersionTitle() {
264264 return (
265265 <span className="inline-flex items-baseline gap-2">
266266 <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>
268268 </span>
269269 );
270270}
......@@ -1368,8 +1368,8 @@ export function AppearanceSettingsPanel() {
13681368 : "flex shrink-0 gap-1"
13691369 }
13701370 >
1371 <span className="size-2 rounded-full bg-[var(--diff-deletion)]" />
1372 <span className="size-2 rounded-full bg-[var(--diff-addition)]" />
1371 <span className="size-2 rounded-full bg-diff-deletion" />
1372 <span className="size-2 rounded-full bg-diff-addition" />
13731373 </span>
13741374 <SelectValue>
13751375 {settings.diffColorScheme === "blue-orange" ? "Blue & orange" : "Red & green"}
......@@ -2046,7 +2046,7 @@ function LegacyFeaturesSection() {
20462046 <section id="legacy-features" ref={targetRef} tabIndex={-1} className="space-y-2.5">
20472047 <Collapsible open={open} onOpenChange={setOpen}>
20482048 <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">
20502050 Legacy features
20512051 </h2>
20522052 <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 }) {
311311 <span className="block truncate text-sm font-medium text-sidebar-foreground">
312312 {item.title}
313313 </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">
315315 {SETTINGS_SECTION_LABELS[item.to]}
316316 </span>
317317 </span>
apps/web/src/components/settings/SnapShotSetupDialog.tsx+2-6
......@@ -268,9 +268,7 @@ export function SnapShotSetupDialog({
268268 permissions={[
269269 {
270270 id: "screenRecording",
271 icon: (
272 <MacScreenRecordingIcon className="size-8 shrink-0 drop-shadow-[0_1px_1px_#0005]" />
273 ),
271 icon: <MacScreenRecordingIcon className="size-8 shrink-0 drop-shadow-sm" />,
274272 title: "Screen Recording",
275273 description: "Capture the window you're using.",
276274 granted: macPermissions.screenRecording,
......@@ -278,9 +276,7 @@ export function SnapShotSetupDialog({
278276 },
279277 {
280278 id: "accessibility",
281 icon: (
282 <MacAccessibilityIcon className="size-8 shrink-0 drop-shadow-[0_1px_1px_#0005]" />
283 ),
279 icon: <MacAccessibilityIcon className="size-8 shrink-0 drop-shadow-sm" />,
284280 title: "Accessibility",
285281 description: includeAccessibility
286282 ? "Include text and controls from the captured app."
apps/web/src/components/settings/SourceControlSettings.tsx+4-6
......@@ -242,8 +242,8 @@ function itemSummary({
242242 return (
243243 <span>
244244 {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>{" "}
246 tool on the server host to enable change request features.
245 the <code className="rounded bg-muted px-1 py-px text-2xs">{item.executable}</code> tool
246 on the server host to enable change request features.
247247 </span>
248248 );
249249 }
......@@ -294,9 +294,7 @@ function DiscoveryItemRow({
294294 <div className="min-w-0 flex-1 space-y-1">
295295 <div className="flex min-w-0 flex-wrap items-center gap-2">
296296 <SourceControlItemMark item={item} />
297 <span className="truncate text-sm font-medium tracking-[-0.005em] text-foreground">
298 {item.label}
299 </span>
297 <span className="truncate text-sm font-medium text-foreground">{item.label}</span>
300298 {version ? <code className="text-xs text-muted-foreground">{version}</code> : null}
301299 {isVcsNotReady(item) ? (
302300 <Badge variant="warning" size="sm">
......@@ -309,7 +307,7 @@ function DiscoveryItemRow({
309307 </Badge>
310308 ) : null}
311309 </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">
313311 {itemSummary({ item, auth, authAccount })}
314312 </p>
315313 </div>
apps/web/src/components/settings/ThemeColorPicker.tsx+4-4
......@@ -171,7 +171,7 @@ function ThemeColorPickerPanel({
171171 <div className="flex items-center justify-between border-b border-border/70 px-4 py-3">
172172 <div className="min-w-0">
173173 <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>
175175 </div>
176176 <span
177177 className="size-7 shrink-0 rounded-full shadow-sm"
......@@ -193,7 +193,7 @@ function ThemeColorPickerPanel({
193193 />
194194 <div className="grid grid-cols-[1fr_1.2fr] gap-2">
195195 <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">
197197 HEX
198198 </span>
199199 <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({
219219 </span>
220220 </label>
221221 <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">
223223 RGB
224224 </span>
225225 <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({
323323 <div
324324 className={cn(
325325 "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",
327327 )}
328328 data-theme-color-role={role}
329329 >
apps/web/src/components/settings/ThemeImportDialog.tsx+4-4
......@@ -111,12 +111,12 @@ function ThemeJsonEditor({
111111 }, []);
112112
113113 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">
115115 {isPlainText ? null : (
116116 <pre
117117 ref={highlightRef}
118118 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"
120120 >
121121 <code dangerouslySetInnerHTML={{ __html: highlightedJson }} />
122122 </pre>
......@@ -124,7 +124,7 @@ function ThemeJsonEditor({
124124 <textarea
125125 aria-label="Theme JSON"
126126 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",
128128 isPlainText ? "text-foreground" : "text-transparent",
129129 )}
130130 id={id}
......@@ -438,7 +438,7 @@ export function ThemeImportDialog({
438438
439439 <div className="flex items-center gap-3" aria-hidden>
440440 <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">
442442 or import a file
443443 </span>
444444 <div className="h-px flex-1 bg-border" />
apps/web/src/components/settings/ThemeSettings.tsx+5-5
......@@ -231,12 +231,12 @@ function ThemeLibraryCard({
231231 </button>
232232 </ThemeVariantTooltip>
233233 <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"
235235 style={{ marginLeft: rootOffsetX }}
236236 >
237237 <span className="truncate">{selected.option.label}</span>
238238 {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">
240240 +{options.length - 1}
241241 </span>
242242 ) : null}
......@@ -256,7 +256,7 @@ function ThemeLibraryCard({
256256 aria-label={`Use ${option.label} for ${mode} mode${optionIsActive ? ", currently active" : ""}`}
257257 aria-pressed={optionIsActive}
258258 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",
260260 optionIsActive ? "ring-2 ring-ring" : "ring-1 ring-border/70",
261261 )}
262262 style={{
......@@ -884,12 +884,12 @@ export function ThemeLibrary({
884884
885885 return (
886886 <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">
888888 {searchableSetting("color-scheme").title}
889889 </h3>
890890 {renderModeTiles()}
891891 <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">
893893 {searchableSetting("theme").title}
894894 </h3>
895895 <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({
6666
6767 {/* Composer */}
6868 <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"
7070 style={{
7171 backgroundColor: colors.surface,
7272 boxShadow: `inset 0 0 0 1px ${line}`,
......@@ -92,7 +92,7 @@ function ThemeWireframePane({
9292 >
9393 {[0, 1, 2].map((row) => (
9494 <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"
9696 key={row}
9797 style={{ top: `${10 + row * 30}%`, height: "20%" }}
9898 >
apps/web/src/components/settings/settingsLayout.tsx+4-4
......@@ -202,7 +202,7 @@ export function SettingsSection({
202202 className="flex min-h-7 items-start justify-between gap-4 px-3 sm:px-4"
203203 >
204204 <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">
206206 {icon}
207207 {title}
208208 </h2>
......@@ -228,7 +228,7 @@ export function SettingsUnavailableGroup({
228228
229229 return (
230230 <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">
232232 <InfoIcon className="mt-0.5 size-3.5 shrink-0 text-warning" />
233233 <p>{message}</p>
234234 </div>
......@@ -435,7 +435,7 @@ export function SettingsRow({
435435 <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">
436436 <div className="min-w-0 flex-1 space-y-1">
437437 <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>
439439 {renderedInheritance ? (
440440 <span className="inline-flex h-5 w-5 shrink-0 items-center justify-center">
441441 {renderedInheritance}
......@@ -446,7 +446,7 @@ export function SettingsRow({
446446 </span>
447447 </div>
448448 {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">
450450 {description}
451451 </p>
452452 ) : null}
apps/web/src/components/sidebar/SidebarProviderUpdatePill.tsx+2-2
......@@ -125,7 +125,7 @@ export function SidebarProviderUpdatePill() {
125125
126126 return (
127127 <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 ${
129129 PROVIDER_UPDATE_PILL_STYLES[displayedView.tone]
130130 } ${
131131 exitingKey === displayedView.key
......@@ -152,7 +152,7 @@ export function SidebarProviderUpdatePill() {
152152 <div
153153 key={displayedView.key}
154154 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 ${
156156 PROVIDER_UPDATE_PILL_PROGRESS_STYLES[displayedView.tone]
157157 }`}
158158 style={
apps/web/src/components/sidebar/SidebarThreadHeader.tsx+1-1
......@@ -83,7 +83,7 @@ export function SidebarThreadHeader({
8383 ref={searchFieldRef}
8484 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"
8585 >
86 <SearchIcon className="size-4 shrink-0 text-[var(--sidebar-icon-color)]" />
86 <SearchIcon className="size-4 shrink-0 text-(--sidebar-icon-color)" />
8787 <SidebarInput
8888 ref={searchInputRef}
8989 nativeInput
apps/web/src/components/sidebar/SidebarUpdatePill.tsx+1-1
......@@ -311,7 +311,7 @@ function SidebarUpdateControl() {
311311 !isInteractionDisabled && "hover:bg-sidebar-row-hover",
312312 )
313313 : cn(
314 "text-[var(--sidebar-icon-color)]",
314 "text-(--sidebar-icon-color)",
315315 !isInteractionDisabled && "hover:bg-sidebar-row-hover hover:text-sidebar-foreground",
316316 ),
317317 disabled && !showUpdateIconState && "opacity-60",
apps/web/src/components/usage/UsageLimitsPooled.tsx+5-5
......@@ -52,7 +52,7 @@ function AccountChip({ email }: { readonly email: string }) {
5252 <span
5353 role="img"
5454 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"
5656 style={{ backgroundColor: `oklch(0.85 0.08 ${hue})`, color: `oklch(0.35 0.1 ${hue})` }}
5757 >
5858 {accountInitials(email)}
......@@ -269,7 +269,7 @@ function PoolSegment({
269269 ) : null}
270270 <span
271271 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"
273273 >
274274 {index}
275275 </span>
......@@ -277,7 +277,7 @@ function PoolSegment({
277277 <AccountName account={account} className="min-w-0 truncate font-medium text-foreground" />
278278 <span className="shrink-0 font-semibold text-foreground tabular-nums">{remaining}%</span>
279279 {/* 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">
281281 {resetsIn?.replace("resets in ", "↻ ") ?? ""}
282282 {credits ? (
283283 <>
......@@ -348,7 +348,7 @@ function LegendRow({
348348 render={<Button variant="ghost" size="compact" />}
349349 className="min-w-0 @2xl/pool:hidden"
350350 >
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">
352352 <span
353353 aria-hidden
354354 className="absolute inset-0 rounded-sm opacity-35"
......@@ -359,7 +359,7 @@ function LegendRow({
359359 </span>
360360 <AccountName account={account} className="min-w-0 truncate font-medium text-foreground" />
361361 <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">
363363 {resetsIn?.replace("resets in ", "↻ ") ?? ""}
364364 {credits ? (
365365 <>
apps/web/src/components/usage/UsagePage.tsx+1-1
......@@ -428,7 +428,7 @@ export function UsagePage() {
428428 <span className="truncate">
429429 {PROVIDER_PRESENTATION[provider].label}
430430 </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">
432432 {sessionLabel}
433433 </span>
434434 </span>
apps/web/src/components/usage/UsageProviderChart.tsx+2-2
......@@ -322,7 +322,7 @@ export function UsageProviderChart({
322322 {ticks.map((tick) => (
323323 <span
324324 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"
326326 style={{ top: `${(toY(tick) / VIEW_HEIGHT) * 100}%` }}
327327 >
328328 {tick === 0 ? "0" : format(tick)}
......@@ -434,7 +434,7 @@ export function UsageProviderChart({
434434 </div>
435435 </div>
436436
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">
438438 <span>{periods[0] === undefined ? "" : formatPeriod(periods[0])}</span>
439439 <span>
440440 {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
116116 --workspace-titlebar-control-size: 1.75rem;
117117 --workspace-titlebar-control-gap: 0.75rem;
118118 --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 }
119130
120131 @variant dark {
121132 --appearance-contrast-target: white;
......@@ -148,6 +159,41 @@ html[data-mobile-composer-route-transition="true"]::view-transition-old(t3-mobil
148159}
149160
150161@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 );
151197 --color-zinc-25: oklch(99.2% 0 0);
152198 --animate-skeleton: skeleton 2.4s infinite;
153199 /* Duty-cycled indicator animations: long holds with stepped ramps, so the
......@@ -1936,40 +1982,6 @@ code {
19361982 overflow-wrap: anywhere;
19371983}
19381984
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
19731985:root {
19741986 --diff-addition: var(--success);
19751987 --diff-deletion: var(--destructive);
apps/web/src/lib/utils.ts+5-1
......@@ -1,9 +1,13 @@
11import { MessageId, ProjectId, ThreadId } from "@t3tools/contracts";
22import { type CxOptions, cx } from "class-variance-authority";
33import * as Encoding from "effect/Encoding";
4import { twMerge } from "tailwind-merge";
4import { extendTailwindMerge } from "tailwind-merge";
55import { DraftId } from "../composerDraftStore";
66
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.
9const twMerge = extendTailwindMerge({ extend: { theme: { text: ["2xs", "3xs"] } } });
10
711export function cn(...inputs: CxOptions) {
812 return twMerge(cx(inputs));
913}
vite.config.ts+40
......@@ -225,6 +225,41 @@ export default defineConfig({
225225 rules: {
226226 // A className built at runtime on a ui component is one no-restyle cannot read.
227227 "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 ],
228263 "shadcn/no-restyle": [
229264 "error",
230265 {
......@@ -242,6 +277,11 @@ export default defineConfig({
242277 ],
243278 },
244279 },
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 },
245285 {
246286 // Shared client code must not call APIs missing from Hermes. Our ESNext
247287 // TypeScript target accepts them even when they would crash mobile at launch.