refactor(ui): extract font-size and letter-spacing to tokens (Phase 2 batch 2/4)

Replaces hardcoded TYPE values in ui/src/components/** and ui/src/pages/**
with references to new verbatim CSS custom-property tokens in
ui/src/index.css, via a new committed codemod (scripts/codemod-extract-type.mjs).

- 932 sites rewritten across 143 files:
  - 728 arbitrary font-size Tailwind classes (text-[Npx])
  - 202 arbitrary letter-spacing classes (tracking-[N em])
  - 2 inline-style fontSize string literals
  - 0 leading-[...] sites found (none existed)
- 17 new tokens minted, no normalizing: 8 --fs-* (9/10/11/12/13/14/15px +
  0.7rem, kept in its own unit) and 9 --ls-* (0.08-0.24em, 9 distinct
  values) — the micro type-size and letter-spacing clusters TOKEN-AUDIT.md
  flagged are now materialized as tokens, still un-collapsed pending a
  human scale decision.
- 2 sites allowlisted (both already-documented functional/third-party
  fontSize forms: CompanyEnvironments.tsx xterm.js config, CompanySkills.tsx
  computed Math.round() value) — no new allowlist entries needed since
  neither is a class-string or literal-fontSize site the codemod targets.
- Verified: rg gates clean, pnpm build-storybook exit 0, Storybook visual
  suite 510/510 passed (first attempt), pnpm typecheck exit 0, codemod
  re-run confirmed idempotent (0 sites on second pass).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
scotttong 2026-07-06 14:29:51 -07:00
parent a9399a4d21
commit 4b3f087d7f
146 changed files with 1091 additions and 781 deletions

View File

@ -279,3 +279,40 @@ Codemod: `scripts/codemod-extract-colors.mjs` (table-driven, idempotent — see
**Needs human decision (new, from this batch):**
- `components/FileViewerSheet.tsx`'s `--paperclip-code-highlight-bg`/`-border` half-migrated var-with-fallback pattern (allowlist item 7 above) — TOKEN-AUDIT.md section 2 already recommended "this becomes the actual token"; this batch deliberately did NOT act on that recommendation because defining the var changes what `var(--x, fallback)` resolves to structurally (from "always the literal fallback" to "the var if defined, else the fallback") even though the *value* would be identical today — a human should confirm this is the intended direction before Batch 2+ touches it, alongside the sibling `--paperclip-code-bg`/`--paperclip-code-gutter-fg` vars in the same file that use `theme(colors.muted...)` fallbacks (out of scope for colors, relevant to a future spacing/type batch).
- The `#2563EB` reuse (`IssueChatThread.tsx`'s "Liveness blue" chat bubble → `--status-task-in_progress`) is a **semantic coincidence**, not a designed relationship — the original code comment explicitly called it "Liveness blue" independently of the task-status system. Batch 1 reused the token per the exact-match rule, but a human should confirm a chat-bubble liveness color is supposed to be permanently coupled to the task `in_progress` status hue going forward (if a future redesign changes one, does the other move too?).
---
## Phase 2 extraction log — Batch 2 (type)
Codemod: `scripts/codemod-extract-type.mjs`. Unlike Batch 1's hand-audited site table (needed to avoid hex-like false positives such as issue references), this batch's patterns — `text-[Npx]`/`text-[N.Nrem]` Tailwind font-size, `tracking-[N em]` letter-spacing, `leading-[...]` line-height, and `fontSize: "Npx"`/`fontSize: "N.Nrem"` inline-style string literals — are unambiguous, so the codemod does a blanket regex sweep scoped to `ui/src/components/**` and `ui/src/pages/**` (including `*.test.tsx` companions; a full scan found **zero** test files containing any of these patterns, so no test file needed a lockstep update this batch). Verified idempotent (second run: 0 sites, 0 files changed).
**Sites rewritten: 932**, across 143 files.
- Font-size Tailwind class utilities (`text-[Npx]`): 728 sites (matches TOKEN-AUDIT.md section 3.1's count almost exactly — 730 vs. 728, negligible drift from audit-vs-extraction timing). No rem-unit or line-height-suffixed (`text-[N]/[N]`) forms were found in class strings; none existed to convert.
- Letter-spacing (`tracking-[N em]`): 202 sites, matching TOKEN-AUDIT.md section 3.2 exactly (9 distinct values).
- `leading-[...]` line-height brackets: 0 sites found (confirmed via full sweep; TOKEN-AUDIT.md did not call this out as a populated cluster either).
- Inline-style `fontSize` string literals: 2 sites — `components/AsciiArtAnimation.tsx:344` (`fontSize: "11px"`, reused the same `--fs-11` token minted by the class-based sites — no duplicate) and `components/MarkdownBody.tsx:197` (`fontSize: "0.7rem"`, new rem-unit token).
**Tokens minted: 17 new** (0 reused from Batch 1 — font-size/letter-spacing/line-height had no prior tokens to match against).
- 8 `--fs-*` (font-size): `--fs-9`, `--fs-10`, `--fs-11`, `--fs-12`, `--fs-13`, `--fs-14`, `--fs-15` (px, one per distinct value found) + `--fs-0_7rem` (0.7rem, `MarkdownBody.tsx`'s inline style — kept in rem per DESIGN.md "no normalizing/unit-converting" rule, NOT collapsed into the 11px-ish px cluster even though 0.7rem ≈ 11.2px).
- 9 `--ls-*` (letter-spacing): `--ls-0_08`, `--ls-0_1`, `--ls-0_12`, `--ls-0_14`, `--ls-0_16`, `--ls-0_18`, `--ls-0_2`, `--ls-0_22`, `--ls-0_24` — one per distinct em value, matching TOKEN-AUDIT.md 3.2's 9-value cluster exactly.
- 0 `--lh-*` (line-height) — no sites required one; the token-registration code path exists in the codemod (and was exercised in the Step 0 syntax spike) for forward-compatibility but minted nothing this batch.
- All new tokens live in a second non-`@theme` `:root { ... }` block appended to `ui/src/index.css` immediately after Batch 1's color block, headed `/* ── Extracted verbatim TYPE tokens (Phase 2 Batch 2, design/token-extraction) ── */`, per DESIGN.md (runtime-tunable). **No normalizing performed** — 9/10/11/12/13/14/15px and the 9 distinct tracking values all remain distinct tokens; the human scale-collapse decision (TOKEN-AUDIT.md "Needs human decision" #2/#3, PRIOR-ART's draft `.type-*` scale) is explicitly deferred, per mandate.
**Tailwind v4 rewrite forms used** (confirmed via mandatory Step-0 syntax spike — scratch story + `pnpm build-storybook` + grep of emitted CSS, then deleted before the real codemod ran):
- `text-[11px]``text-(length:--fs-11)` — emits `font-size:var(--fs-11)`. The `length:` hint is REQUIRED; a bare `text-(--fs-11)` would be interpreted as a color utility.
- `tracking-[0.18em]``tracking-(--ls-0_18)` — emits `--tw-tracking:var(--ls-0_18);letter-spacing:var(--ls-0_18)`. Unambiguous, no hint needed.
- `leading-[...]` (numeric/unit forms only) → `leading-(--lh-*)` — verified to emit `--tw-leading:var(--lh-*);line-height:var(--lh-*)` in the spike; not exercised on a real site since 0 sites existed.
- All variant/modifier prefixes preserved verbatim by construction (the regex only rewrites the bracket portion): confirmed sites include `sm:text-[11px]` (`components/BlockedReasonChip.tsx`), a compound arbitrary-variant `group-data-[size=xs]/avatar:text-[10px]` (`components/ui/avatar.tsx`), and an `!important`-marked bracket-selector `[&>span:last-child]:!text-[11px]` (`components/ActiveAgentsPanel.tsx`) — all rewrote correctly to `sm:text-(length:--fs-11)`, `group-data-[size=xs]/avatar:text-(length:--fs-10)`, and `[&>span:last-child]:!text-(length:--fs-11)` respectively.
**Sites allowlisted (2 sites, both already covered by Batch 1's allowlist doc-comment structure for their files, no new inline comments needed since neither is a bracket-literal or class-string site):**
1. `pages/CompanyEnvironments.tsx:422``fontSize: 12` inside the xterm.js terminal theme option object (same object Batch 1 allowlisted for its color literals). Numeric, functional third-party config — not a rendered CSS value, not a string literal the codemod's regex targets.
2. `pages/CompanySkills.tsx:580``fontSize: Math.round(size * 0.42)` — computed at runtime from a prop; not a static literal, nothing to extract.
**Verify results:**
- `rg` gates clean in `ui/src/components/**` / `ui/src/pages/**`: zero `text-[Npx]`/`text-[N.Nrem]` arbitrary font-size, zero `tracking-[N em]`, zero numeric `leading-[...]`, zero raw `fontSize: "..."` string literals remain (the only two `fontSize:` string-literal grep hits left are the already-converted `fontSize: "var(--fs-11)"` / `fontSize: "var(--fs-0_7rem)"` sites).
- `pnpm build-storybook` exit 0.
- Storybook visual snapshot suite: **510/510 passed, 0 failed**, first attempt, no retries needed (`npx playwright test --config tests/storybook-visual/playwright.config.ts --reporter=line`).
- `pnpm typecheck` exit 0.
- Codemod re-run confirmed idempotent: second invocation reports 0 sites rewritten, 0 files changed, token block already present.
**Needs human decision:** none new from this batch beyond the already-logged #2 (micro type-size cluster) and #3 (letter-spacing cluster) in section 8 above — this batch's 17 minted tokens are exactly the verbatim inventory those two items describe, now materialized as CSS custom properties ready for a human to collapse into a real scale.

View File

@ -0,0 +1,239 @@
#!/usr/bin/env node
/**
* codemod-extract-type.mjs
*
* Phase 2 (extraction), Batch 2/4 of the design-token audit
* (branch design/token-extraction). Replaces hardcoded TYPE values
* arbitrary Tailwind font-size (`text-[11px]`), letter-spacing
* (`tracking-[0.18em]`), line-height (`leading-[...]`), and raw inline
* `fontSize` style literals in `ui/src/components/**` and
* `ui/src/pages/**` (including their *.test.tsx companions) with
* references to CSS custom-property tokens defined in `ui/src/index.css`.
*
* Unlike Batch 1's color codemod (which used a hand-audited site table to
* avoid false-positiving on non-color hex-like strings such as issue
* references), this batch's patterns are unambiguous: `text-[Npx]`,
* `text-[N.Nrem]`, `tracking-[N em]`, and `leading-[...]` inside Tailwind
* class strings, and `fontSize: "Npx"` / `fontSize: "N.Nrem"` inline-style
* string literals, cannot mean anything other than a type-size/spacing
* value. A blanket regex sweep is therefore safe and is used here, scoped
* to `ui/src/components/**` and `ui/src/pages/**` only. Numeric or
* computed `fontSize` forms (e.g. `fontSize: 12`, `fontSize: Math.round(...)`)
* are functional (third-party config objects / runtime-computed values)
* and are left untouched see ALLOWLIST_NOTES below.
*
* Token naming (verbatim value, no normalizing):
* --fs-<N> font-size, px values, e.g. --fs-11: 11px;
* --fs-0_<N>rem font-size, rem values, e.g. --fs-0_7rem: 0.7rem;
* --ls-0_<N> letter-spacing, em values, e.g. --ls-0_18: 0.18em;
* --lh-<N> line-height (px or unitless none found this batch)
*
* Tailwind v4 paren-shorthand rewrite forms used:
* text-[Npx] -> text-(length:--fs-N) (length hint REQUIRED
* bare text-(--x) means color)
* tracking-[N em] -> tracking-(--ls-0_N) (unambiguous, no hint)
* leading-[...] -> leading-(--lh-N) (unambiguous, no hint)
* All variant/modifier prefixes (`sm:`, `dark:`, `group-hover:`,
* `[&>x]:`, trailing `!important` marker, etc.) are preserved verbatim
* the regex only rewrites the bracket portion itself.
*
* Idempotent: the FIND regex only matches the ORIGINAL bracket-literal
* form (`text-[11px]` etc.); once rewritten to `text-(length:--fs-11)` the
* pattern no longer matches, so re-running is a no-op. The inline-style
* FIND is likewise the literal `fontSize: "11px"` string form.
*
* Usage: node scripts/codemod-extract-type.mjs [--check]
* --check Report what WOULD change without writing files (dry run).
*/
import { readFileSync, writeFileSync, readdirSync, statSync } from "node:fs";
import { resolve, dirname, join, relative } from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const REPO_ROOT = resolve(__dirname, "..");
const UI_SRC = resolve(REPO_ROOT, "ui/src");
const SCAN_DIRS = ["components", "pages"];
const DRY_RUN = process.argv.includes("--check");
// ── Helpers ────────────────────────────────────────────────────────────
function walk(dir, out) {
for (const entry of readdirSync(dir, { withFileTypes: true })) {
const p = join(dir, entry.name);
if (entry.isDirectory()) walk(p, out);
else if (/\.(tsx?|jsx?)$/.test(entry.name)) out.push(p);
}
}
function tokenSuffixForPx(value) {
// "11" -> "11", "0.65" -> "0_65"
return value.replace(".", "_");
}
function tokenSuffixForEm(value) {
// "0.18" -> "0_18"
return value.replace(".", "_");
}
// ── Token registries (populated as sites are discovered) ───────────────
// Map of token name (without --) -> { value, comment, kind }
const fsTokens = new Map(); // font-size
const lsTokens = new Map(); // letter-spacing
const lhTokens = new Map(); // line-height
function registerFsToken(rawValue, unit, sourceNote) {
const name = unit === "px" ? `fs-${tokenSuffixForPx(rawValue)}` : `fs-${tokenSuffixForPx(rawValue)}rem`;
if (!fsTokens.has(name)) {
fsTokens.set(name, { value: `${rawValue}${unit}`, comment: sourceNote });
}
return name;
}
function registerLsToken(rawValue, sourceNote) {
const name = `ls-${tokenSuffixForEm(rawValue)}`;
if (!lsTokens.has(name)) {
lsTokens.set(name, { value: `${rawValue}em`, comment: sourceNote });
}
return name;
}
function registerLhToken(rawValue, sourceNote) {
// rawValue includes unit already stripped by caller; store as given
const safeName = rawValue.replace(/[^a-zA-Z0-9]/g, "_");
const name = `lh-${safeName}`;
if (!lhTokens.has(name)) {
lhTokens.set(name, { value: rawValue, comment: sourceNote });
}
return name;
}
// ── Regexes ──────────────────────────────────────────────────────────
// text-[11px], text-[0.65rem], with optional /[Npx] line-height suffix
// (none found in this codebase, but handled for completeness/future-proofing).
const FS_RE = /text-\[([0-9.]+)(px|rem)\](?:\/\[([0-9.]+)(px|rem)\])?/g;
const LS_RE = /tracking-\[([0-9.]+)em\]/g;
const LEADING_RE = /leading-\[([^\]]+)\]/g;
const FONTSIZE_STYLE_RE = /fontSize:\s*"([0-9.]+)(px|rem)"/g;
function rewriteFile(filePath, relPath) {
const original = readFileSync(filePath, "utf8");
let content = original;
let siteCount = 0;
// -- font-size Tailwind class utilities --
content = content.replace(FS_RE, (match, num, unit, lhNum, lhUnit) => {
const fsName = registerFsToken(num, unit, `Extracted from ${relPath} (text-[${num}${unit}]).`);
let replacement = `text-(length:--${fsName})`;
if (lhNum) {
const lhName = registerLhToken(`${lhNum}${lhUnit}`, `Extracted from ${relPath} (text-[...]/[${lhNum}${lhUnit}] line-height suffix).`);
replacement += `/(--${lhName})`;
}
siteCount++;
return replacement;
});
// -- letter-spacing Tailwind class utilities --
content = content.replace(LS_RE, (match, num) => {
const lsName = registerLsToken(num, `Extracted from ${relPath} (tracking-[${num}em]).`);
siteCount++;
return `tracking-(--${lsName})`;
});
// -- line-height Tailwind class utilities (standalone leading-[...]) --
content = content.replace(LEADING_RE, (match, raw) => {
// Only rewrite numeric/unit literals (px, rem, unitless number). Skip
// keyword forms like leading-[inherit] or var()-based (already tokenized).
if (!/^[0-9.]+(px|rem)?$/.test(raw)) return match;
const lhName = registerLhToken(raw, `Extracted from ${relPath} (leading-[${raw}]).`);
siteCount++;
return `leading-(--${lhName})`;
});
// -- inline style fontSize string literals --
content = content.replace(FONTSIZE_STYLE_RE, (match, num, unit) => {
const fsName = registerFsToken(num, unit, `Extracted from ${relPath} (inline style fontSize: "${num}${unit}").`);
siteCount++;
return `fontSize: "var(--${fsName})"`;
});
if (content !== original && !DRY_RUN) {
writeFileSync(filePath, content, "utf8");
}
return { changed: content !== original, siteCount };
}
function main() {
const files = [];
for (const dir of SCAN_DIRS) walk(resolve(UI_SRC, dir), files);
let totalSites = 0;
let filesChanged = 0;
const changedFiles = [];
for (const filePath of files) {
const relPath = "ui/src/" + relative(UI_SRC, filePath);
const { changed, siteCount } = rewriteFile(filePath, relPath);
if (changed) {
filesChanged++;
changedFiles.push(relPath);
}
totalSites += siteCount;
}
// ── index.css token block ──────────────────────────────────────────
const cssPath = resolve(UI_SRC, "index.css");
const cssOriginal = readFileSync(cssPath, "utf8");
const marker = "/* ── Extracted verbatim TYPE tokens (Phase 2 Batch 2, design/token-extraction) ── */";
let cssNext = cssOriginal;
let cssChanged = false;
if (!cssOriginal.includes(marker) && (fsTokens.size || lsTokens.size || lhTokens.size)) {
const lines = [];
lines.push(marker);
lines.push("/* Batch 2/4: font-size + letter-spacing + line-height literals, verbatim");
lines.push(" (no normalizing — 9/10/11/12/13/14/15px and 0.08-0.24em all stay distinct;");
lines.push(" the human scale-collapse decision comes later per DESIGN.md/TOKEN-AUDIT.md).");
lines.push("");
lines.push(" Allowlist (sites intentionally left as hardcoded / functional literals,");
lines.push(" NOT converted to tokens — each also carries an inline");
lines.push(" `token-extraction: allowlisted` comment at the site):");
lines.push(" - pages/CompanyEnvironments.tsx (fontSize: 12) — xterm.js terminal theme");
lines.push(" config; functional third-party numeric option, not a rendered CSS value.");
lines.push(" Same allowlisted object as Batch 1's color entry for this file.");
lines.push(" - pages/CompanySkills.tsx (fontSize: Math.round(size * 0.42)) — computed at");
lines.push(" runtime from a prop; not a static literal, nothing to extract.");
lines.push("*/");
lines.push(":root {");
for (const [name, { value, comment }] of fsTokens) {
lines.push(` --${name}: ${value}; /* ${comment} */`);
}
for (const [name, { value, comment }] of lsTokens) {
lines.push(` --${name}: ${value}; /* ${comment} */`);
}
for (const [name, { value, comment }] of lhTokens) {
lines.push(` --${name}: ${value}; /* ${comment} */`);
}
lines.push("}");
const block = "\n" + lines.join("\n") + "\n";
cssNext = cssOriginal + block;
cssChanged = true;
}
if (cssChanged && !DRY_RUN) writeFileSync(cssPath, cssNext, "utf8");
// ── Summary ─────────────────────────────────────────────────────────
console.log(`\n${DRY_RUN ? "[DRY RUN] " : ""}codemod-extract-type summary`);
console.log(` Sites rewritten: ${totalSites}`);
console.log(` Files changed: ${filesChanged}`);
console.log(` New --fs-* tokens: ${fsTokens.size}`);
console.log(` New --ls-* tokens: ${lsTokens.size}`);
console.log(` New --lh-* tokens: ${lhTokens.size}`);
console.log(` index.css token block: ${cssChanged ? "added" : "already present or nothing to add (idempotent no-op)"}`);
if (changedFiles.length) {
console.log(`\n Changed files:`);
for (const f of changedFiles) console.log(` - ${f}`);
}
}
main();

View File

@ -30,7 +30,7 @@ export function AccountingModelCard() {
<Card className="relative overflow-hidden border-border/70">
<div className="absolute inset-0 bg-(image:--gradient-extract-3)" />
<CardHeader className="relative px-5 pt-5 pb-2">
<CardTitle className="text-sm font-semibold uppercase tracking-[0.22em] text-muted-foreground">
<CardTitle className="text-sm font-semibold uppercase tracking-(--ls-0_22) text-muted-foreground">
Accounting model
</CardTitle>
<CardDescription className="max-w-2xl text-sm leading-6">

View File

@ -29,7 +29,7 @@ function RunCardRecoveryChip({ action }: { action: IssueRecoveryAction }) {
aria-label={tone.label}
title={`${tone.label} — open the source task to act.`}
className={cn(
"inline-flex shrink-0 items-center gap-0.5 rounded-full border px-1.5 py-0.5 text-[10px] font-medium",
"inline-flex shrink-0 items-center gap-0.5 rounded-full border px-1.5 py-0.5 text-(length:--fs-10) font-medium",
tone.className,
)}
>
@ -188,16 +188,16 @@ const AgentRunCard = memo(function AgentRunCard({
) : (
<span className="inline-flex h-2.5 w-2.5 rounded-full bg-muted-foreground/35" />
)}
<Identity name={run.agentName} size="sm" className="[&>span:last-child]:!text-[11px]" />
<Identity name={run.agentName} size="sm" className="[&>span:last-child]:!text-(length:--fs-11)" />
</div>
<div className="mt-2 flex items-center gap-2 text-[11px] text-muted-foreground">
<div className="mt-2 flex items-center gap-2 text-(length:--fs-11) text-muted-foreground">
<span>{isActive ? "Live now" : run.finishedAt ? `Finished ${relativeTime(run.finishedAt)}` : `Started ${relativeTime(run.createdAt)}`}</span>
</div>
</div>
<Link
to={`/agents/${run.agentId}/runs/${run.id}`}
className="inline-flex items-center gap-1 rounded-full border border-border/70 bg-background/70 px-2 py-1 text-[10px] text-muted-foreground transition-colors hover:text-foreground"
className="inline-flex items-center gap-1 rounded-full border border-border/70 bg-background/70 px-2 py-1 text-(length:--fs-10) text-muted-foreground transition-colors hover:text-foreground"
>
<ExternalLink className="h-2.5 w-2.5" />
</Link>

View File

@ -23,7 +23,7 @@ function DateLabels({ days }: { days: string[] }) {
{days.map((day, i) => (
<div key={day} className="flex-1 text-center">
{(i === 0 || i === 6 || i === 13) ? (
<span className="text-[9px] text-muted-foreground tabular-nums">{formatDayLabel(day)}</span>
<span className="text-(length:--fs-9) text-muted-foreground tabular-nums">{formatDayLabel(day)}</span>
) : null}
</div>
))}
@ -35,7 +35,7 @@ function ChartLegend({ items }: { items: { color: string; label: string }[] }) {
return (
<div className="flex flex-wrap gap-x-2.5 gap-y-0.5 mt-2">
{items.map(item => (
<span key={item.label} className="flex items-center gap-1 text-[9px] text-muted-foreground">
<span key={item.label} className="flex items-center gap-1 text-(length:--fs-9) text-muted-foreground">
<span className="h-1.5 w-1.5 rounded-full shrink-0" style={{ backgroundColor: item.color }} />
{item.label}
</span>
@ -49,7 +49,7 @@ export function ChartCard({ title, subtitle, children }: { title: string; subtit
<div className="border border-border rounded-lg p-4 space-y-3">
<div>
<h3 className="text-xs font-medium text-muted-foreground">{title}</h3>
{subtitle && <span className="text-[10px] text-muted-foreground/60">{subtitle}</span>}
{subtitle && <span className="text-(length:--fs-10) text-muted-foreground/60">{subtitle}</span>}
</div>
{children}
</div>

View File

@ -470,7 +470,7 @@ export function ActivityFeed({ className }: ActivityFeedProps) {
separator = (
<div className="flex items-center gap-2 px-4 py-1.5" key={`sep-${index}`}>
<div className="h-px flex-1 bg-border" />
<span className="text-[10px] font-medium text-muted-foreground uppercase tracking-wider">
<span className="text-(length:--fs-10) font-medium text-muted-foreground uppercase tracking-wider">
Earlier
</span>
<div className="h-px flex-1 bg-border" />

View File

@ -109,7 +109,7 @@ export function AgentBubbleActionRow({
<TooltipTrigger asChild>
<a
href={anchorHref}
className="text-[11px] text-muted-foreground hover:text-foreground hover:underline"
className="text-(length:--fs-11) text-muted-foreground hover:text-foreground hover:underline"
>
{dateLabel}
</a>

View File

@ -1247,7 +1247,7 @@ export function AgentConfigForm(props: AgentConfigFormProps) {
</Field>
{supportsModelProfiles && (
<div className="text-[11px] uppercase tracking-wide text-muted-foreground">Primary model</div>
<div className="text-(length:--fs-11) uppercase tracking-wide text-muted-foreground">Primary model</div>
)}
<ModelDropdown
models={models}
@ -1578,13 +1578,13 @@ export function AdapterEnvironmentResult({ result }: { result: AdapterEnvironmen
<div className={`rounded-md border px-3 py-2 text-xs ${statusClass}`}>
<div className="flex items-center justify-between gap-2">
<span className="font-medium">{statusLabel}</span>
<span className="text-[11px] opacity-80">
<span className="text-(length:--fs-11) opacity-80">
{new Date(result.testedAt).toLocaleTimeString()}
</span>
</div>
<div className="mt-2 space-y-1.5">
{result.checks.map((check, idx) => (
<div key={`${check.code}-${idx}`} className="text-[11px] leading-relaxed break-words">
<div key={`${check.code}-${idx}`} className="text-(length:--fs-11) leading-relaxed break-words">
<span className="font-medium uppercase tracking-wide opacity-80">
{check.level}
</span>
@ -1657,7 +1657,7 @@ function AdapterTypeDropdown({
{item.experimental && <ExperimentalBadge />}
</span>
{item.comingSoon && (
<span className="text-[10px] text-muted-foreground">Coming soon</span>
<span className="text-(length:--fs-10) text-muted-foreground">Coming soon</span>
)}
</button>
))}
@ -1668,7 +1668,7 @@ function AdapterTypeDropdown({
function ExperimentalBadge() {
return (
<span className="shrink-0 rounded border border-amber-500/30 bg-amber-500/10 px-1.5 py-0.5 text-[10px] font-medium leading-none text-amber-700 dark:text-amber-200">
<span className="shrink-0 rounded border border-amber-500/30 bg-amber-500/10 px-1.5 py-0.5 text-(length:--fs-10) font-medium leading-none text-amber-700 dark:text-amber-200">
Experimental
</span>
);
@ -1871,7 +1871,7 @@ function ModelDropdown({
<span className="block w-full text-left truncate font-mono text-xs" title={value}>
{models.find((m) => m.id === value)?.label ?? value}
</span>
<span className="shrink-0 ml-auto text-[9px] font-medium px-1.5 py-0.5 rounded-full bg-green-500/15 text-green-400 border border-green-500/20">
<span className="shrink-0 ml-auto text-(length:--fs-9) font-medium px-1.5 py-0.5 rounded-full bg-green-500/15 text-green-400 border border-green-500/20">
current
</span>
</button>
@ -1890,7 +1890,7 @@ function ModelDropdown({
<span className="block w-full text-left truncate font-mono text-xs" title={detectedModel}>
{models.find((m) => m.id === detectedModel)?.label ?? detectedModel}
</span>
<span className="shrink-0 ml-auto text-[9px] font-medium px-1.5 py-0.5 rounded-full bg-blue-500/15 text-blue-400 border border-blue-500/20">
<span className="shrink-0 ml-auto text-(length:--fs-9) font-medium px-1.5 py-0.5 rounded-full bg-blue-500/15 text-blue-400 border border-blue-500/20">
detected
</span>
</button>
@ -1914,7 +1914,7 @@ function ModelDropdown({
<span className="block w-full text-left truncate font-mono text-xs" title={candidate}>
{entry?.label ?? candidate}
</span>
<span className="shrink-0 ml-auto text-[9px] font-medium px-1.5 py-0.5 rounded-full bg-sky-500/15 text-sky-400 border border-sky-500/20">
<span className="shrink-0 ml-auto text-(length:--fs-9) font-medium px-1.5 py-0.5 rounded-full bg-sky-500/15 text-sky-400 border border-sky-500/20">
config
</span>
</button>
@ -1953,7 +1953,7 @@ function ModelDropdown({
{groupedModels.map((group) => (
<div key={group.provider} className="mb-1 last:mb-0">
{groupByProvider && (
<div className="px-2 py-1 text-[10px] uppercase tracking-wide text-muted-foreground">
<div className="px-2 py-1 text-(length:--fs-10) uppercase tracking-wide text-muted-foreground">
{group.provider} ({group.entries.length})
</div>
)}
@ -2021,7 +2021,7 @@ function CheapModelSection({
<div className="rounded-md border border-border/70 bg-muted/20 p-3 space-y-3">
<div className="flex items-center justify-between gap-3">
<div className="min-w-0">
<div className="text-[11px] uppercase tracking-wide text-muted-foreground">Cheap model</div>
<div className="text-(length:--fs-11) uppercase tracking-wide text-muted-foreground">Cheap model</div>
<p className="text-xs text-muted-foreground">
Used when a run requests the cheap profile (e.g. routine summaries). The primary model stays unchanged.
</p>
@ -2046,12 +2046,12 @@ function CheapModelSection({
/>
) : null}
{enabled && !model && adapterDefaultModel ? (
<p className="text-[11px] text-muted-foreground">
<p className="text-(length:--fs-11) text-muted-foreground">
No explicit cheap model selected runtime falls back to <code>{adapterDefaultModel}</code>.
</p>
) : null}
{enabled && !model && !adapterDefaultModel ? (
<p className="text-[11px] text-amber-500">
<p className="text-(length:--fs-11) text-amber-500">
No cheap model selected and the adapter has no default. Cheap-lane runs will continue on the primary model with a fallback note.
</p>
) : null}

View File

@ -63,7 +63,7 @@ export function ApprovalCard({
<div className="flex flex-wrap items-center gap-2">
<Badge
variant="outline"
className="border-border/70 bg-background/70 px-2 py-0.5 text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground"
className="border-border/70 bg-background/70 px-2 py-0.5 text-(length:--fs-11) font-medium uppercase tracking-(--ls-0_08) text-muted-foreground"
>
{kindLabel}
</Badge>

View File

@ -70,7 +70,7 @@ function SkillList({ values }: { values: unknown }) {
{items.map((item) => (
<span
key={item}
className="rounded bg-muted px-1.5 py-0.5 font-mono text-[11px] text-muted-foreground"
className="rounded bg-muted px-1.5 py-0.5 font-mono text-(length:--fs-11) text-muted-foreground"
>
{item}
</span>
@ -178,19 +178,19 @@ function BoardApprovalPayloadContent({ payload }: { payload: Record<string, unkn
<div className="mt-4 space-y-3.5 text-sm">
{title && (
<div className="space-y-1">
<p className="text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground">Title</p>
<p className="text-(length:--fs-11) font-medium uppercase tracking-(--ls-0_08) text-muted-foreground">Title</p>
<p className="font-medium leading-6 text-foreground">{title}</p>
</div>
)}
{summary && (
<div className="space-y-1">
<p className="text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground">Summary</p>
<p className="text-(length:--fs-11) font-medium uppercase tracking-(--ls-0_08) text-muted-foreground">Summary</p>
<p className="leading-6 text-foreground/90">{summary}</p>
</div>
)}
{recommendedAction && (
<div className="rounded-lg border border-amber-500/20 bg-amber-500/10 px-3.5 py-3">
<p className="text-[11px] font-medium uppercase tracking-[0.08em] text-amber-700 dark:text-amber-300">
<p className="text-(length:--fs-11) font-medium uppercase tracking-(--ls-0_08) text-amber-700 dark:text-amber-300">
Recommended action
</p>
<p className="mt-1 leading-6 text-foreground">{recommendedAction}</p>
@ -198,13 +198,13 @@ function BoardApprovalPayloadContent({ payload }: { payload: Record<string, unkn
)}
{nextActionOnApproval && (
<div className="rounded-lg border border-border/60 bg-background/60 px-3.5 py-3">
<p className="text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground">On approval</p>
<p className="text-(length:--fs-11) font-medium uppercase tracking-(--ls-0_08) text-muted-foreground">On approval</p>
<p className="mt-1 leading-6 text-foreground">{nextActionOnApproval}</p>
</div>
)}
{risks.length > 0 && (
<div className="space-y-1.5">
<p className="text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground">Risks</p>
<p className="text-(length:--fs-11) font-medium uppercase tracking-(--ls-0_08) text-muted-foreground">Risks</p>
<ul className="space-y-1 text-sm text-muted-foreground">
{risks.map((risk) => (
<li key={risk} className="flex items-start gap-2">
@ -217,7 +217,7 @@ function BoardApprovalPayloadContent({ payload }: { payload: Record<string, unkn
)}
{proposedComment && (
<div className="space-y-1.5">
<p className="text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground">
<p className="text-(length:--fs-11) font-medium uppercase tracking-(--ls-0_08) text-muted-foreground">
Proposed comment
</p>
<pre className="max-h-48 overflow-auto rounded-lg border border-border/60 bg-muted/50 px-3.5 py-3 font-mono text-xs leading-5 text-muted-foreground whitespace-pre-wrap">

View File

@ -139,7 +139,7 @@ export function ArtifactsPanel({ taskId, isAgentWorking, openDocKey, openDocTitl
<button
key={f.value}
className={cn(
"rounded-full px-2.5 py-0.5 text-[11px] font-medium transition-colors",
"rounded-full px-2.5 py-0.5 text-(length:--fs-11) font-medium transition-colors",
filter === f.value
? "bg-foreground text-background"
: "text-muted-foreground hover:text-foreground hover:bg-accent/50",
@ -208,22 +208,22 @@ export function ArtifactsPanel({ taskId, isAgentWorking, openDocKey, openDocTitl
)}
</div>
<div className="flex items-center gap-2 mt-1">
<span className="text-[10px] text-muted-foreground capitalize">
<span className="text-(length:--fs-10) text-muted-foreground capitalize">
{wp.type.replace(/_/g, " ")}
</span>
{showGenerating ? (
<span className="inline-flex items-center gap-1 text-[10px] font-medium px-1.5 py-0.5 rounded-full bg-cyan-500/10 text-cyan-600 dark:text-cyan-400">
<span className="inline-flex items-center gap-1 text-(length:--fs-10) font-medium px-1.5 py-0.5 rounded-full bg-cyan-500/10 text-cyan-600 dark:text-cyan-400">
<Loader2 className="h-2.5 w-2.5 animate-spin" />
Generating...
</span>
) : (
<span className={cn("text-[10px] font-medium px-1.5 py-0.5 rounded-full", badge.className)}>
<span className={cn("text-(length:--fs-10) font-medium px-1.5 py-0.5 rounded-full", badge.className)}>
{badge.label}
</span>
)}
</div>
{wp.summary && (
<p className="text-[11px] text-muted-foreground mt-1 line-clamp-2">
<p className="text-(length:--fs-11) text-muted-foreground mt-1 line-clamp-2">
{wp.summary}
</p>
)}
@ -298,7 +298,7 @@ function DocumentViewer({
{/* Sticky action footer */}
{needsAction && (
<div className="border-t border-border px-4 py-3 bg-background shrink-0">
<p className="text-[11px] text-muted-foreground mb-2">This document needs your review.</p>
<p className="text-(length:--fs-11) text-muted-foreground mb-2">This document needs your review.</p>
<div className="flex items-center gap-3">
<Button size="lg" className="h-11 px-8 text-base font-semibold flex-1 rounded-lg bg-green-700 hover:bg-green-800 text-white border-0" onClick={onApprove}>
Approve
@ -316,7 +316,7 @@ function DocumentViewer({
<div className="border-t border-green-500/30 bg-green-500/5 px-4 py-3 shrink-0">
<div className="flex items-center gap-2">
<CheckCircle2 className="h-4 w-4 text-green-500" />
<p className="text-[13px] font-medium text-green-700 dark:text-green-400">
<p className="text-(length:--fs-13) font-medium text-green-700 dark:text-green-400">
Approved hire tasks created
</p>
</div>
@ -326,7 +326,7 @@ function DocumentViewer({
<div className="border-t border-orange-500/30 bg-orange-500/5 px-4 py-3 shrink-0">
<div className="flex items-center gap-2">
<XCircle className="h-4 w-4 text-orange-500" />
<p className="text-[13px] font-medium text-orange-700 dark:text-orange-400">
<p className="text-(length:--fs-13) font-medium text-orange-700 dark:text-orange-400">
Changes requested CEO is revising
</p>
</div>

View File

@ -341,7 +341,7 @@ export function AsciiArtAnimation() {
<pre
ref={preRef}
className="w-full h-full m-0 p-0 overflow-hidden text-muted-foreground/60 select-none leading-none"
style={{ fontSize: "11px", fontFamily: "monospace" }}
style={{ fontSize: "var(--fs-11)", fontFamily: "monospace" }}
aria-hidden="true"
/>
);

View File

@ -64,7 +64,7 @@ export function BlockedReasonChip({
data-severity={severity}
aria-label={`Reason: ${label}, severity ${severity}`}
className={cn(
"inline-flex shrink-0 items-center gap-1 rounded-md border px-2 py-0.5 text-[10px] font-medium leading-tight sm:text-[11px]",
"inline-flex shrink-0 items-center gap-1 rounded-md border px-2 py-0.5 text-(length:--fs-10) font-medium leading-tight sm:text-(length:--fs-11)",
VARIANT_STYLES[variant],
className,
)}

View File

@ -48,7 +48,7 @@ export function BudgetIncidentCard({
<div className="flex items-start justify-between gap-3">
<div>
<div className="flex flex-wrap items-center gap-2">
<div className="text-[11px] uppercase tracking-[0.22em] text-red-200/80">
<div className="text-(length:--fs-11) uppercase tracking-(--ls-0_22) text-red-200/80">
{incident.scopeType} hard stop
</div>
<Badge variant={incident.status === "resolved" ? "outline" : "secondary"}>
@ -76,7 +76,7 @@ export function BudgetIncidentCard({
</div>
<div className="rounded-xl border border-border/60 bg-background/60 p-3">
<label className="text-[11px] uppercase tracking-[0.18em] text-muted-foreground">
<label className="text-(length:--fs-11) uppercase tracking-(--ls-0_18) text-muted-foreground">
New budget (USD)
</label>
<div className="mt-2 flex flex-col gap-3 sm:flex-row">

View File

@ -56,14 +56,14 @@ export function BudgetPolicyCard({
const observedBudgetGrid = isPlain ? (
<div className="grid gap-6 sm:grid-cols-2">
<div>
<div className="text-[11px] uppercase tracking-[0.18em] text-muted-foreground">Observed</div>
<div className="text-(length:--fs-11) uppercase tracking-(--ls-0_18) text-muted-foreground">Observed</div>
<div className="mt-2 text-xl font-semibold tabular-nums">{formatCents(summary.observedAmount)}</div>
<div className="mt-1 text-xs text-muted-foreground">
{summary.amount > 0 ? `${summary.utilizationPercent}% of limit` : "No cap configured"}
</div>
</div>
<div>
<div className="text-[11px] uppercase tracking-[0.18em] text-muted-foreground">Budget</div>
<div className="text-(length:--fs-11) uppercase tracking-(--ls-0_18) text-muted-foreground">Budget</div>
<div className="mt-2 text-xl font-semibold tabular-nums">
{summary.amount > 0 ? formatCents(summary.amount) : "Disabled"}
</div>
@ -75,14 +75,14 @@ export function BudgetPolicyCard({
) : (
<div className="grid gap-3 sm:grid-cols-2">
<div className="rounded-xl border border-border/70 bg-black/[0.18] px-4 py-3">
<div className="text-[11px] uppercase tracking-[0.18em] text-muted-foreground">Observed</div>
<div className="text-(length:--fs-11) uppercase tracking-(--ls-0_18) text-muted-foreground">Observed</div>
<div className="mt-2 text-xl font-semibold tabular-nums">{formatCents(summary.observedAmount)}</div>
<div className="mt-1 text-xs text-muted-foreground">
{summary.amount > 0 ? `${summary.utilizationPercent}% of limit` : "No cap configured"}
</div>
</div>
<div className="rounded-xl border border-border/70 bg-black/[0.18] px-4 py-3">
<div className="text-[11px] uppercase tracking-[0.18em] text-muted-foreground">Budget</div>
<div className="text-(length:--fs-11) uppercase tracking-(--ls-0_18) text-muted-foreground">Budget</div>
<div className="mt-2 text-xl font-semibold tabular-nums">
{summary.amount > 0 ? formatCents(summary.amount) : "Disabled"}
</div>
@ -129,7 +129,7 @@ export function BudgetPolicyCard({
const saveSection = onSave ? (
<div className={cn("flex flex-col gap-3 sm:flex-row sm:items-end", isPlain ? "" : "rounded-xl border border-border/70 bg-background/50 p-3")}>
<div className="min-w-0 flex-1">
<label className="text-[11px] uppercase tracking-[0.18em] text-muted-foreground">
<label className="text-(length:--fs-11) uppercase tracking-(--ls-0_18) text-muted-foreground">
Budget (USD)
</label>
<Input
@ -156,7 +156,7 @@ export function BudgetPolicyCard({
<div className="space-y-6">
<div className="flex items-start justify-between gap-6">
<div>
<div className="text-[11px] uppercase tracking-[0.22em] text-muted-foreground">
<div className="text-(length:--fs-11) uppercase tracking-(--ls-0_22) text-muted-foreground">
{summary.scopeType}
</div>
<div className="mt-2 text-xl font-semibold">{summary.scopeName}</div>
@ -164,7 +164,7 @@ export function BudgetPolicyCard({
</div>
<div
className={cn(
"inline-flex items-center gap-2 text-[11px] uppercase tracking-[0.18em]",
"inline-flex items-center gap-2 text-(length:--fs-11) uppercase tracking-(--ls-0_18)",
summary.status === "hard_stop"
? "text-red-300"
: summary.status === "warning"
@ -193,13 +193,13 @@ export function BudgetPolicyCard({
<CardHeader className={cn("gap-3", compact ? "px-4 pt-4 pb-2" : "px-5 pt-5 pb-3")}>
<div className="flex items-start justify-between gap-3">
<div>
<div className="text-[11px] uppercase tracking-[0.22em] text-muted-foreground">
<div className="text-(length:--fs-11) uppercase tracking-(--ls-0_22) text-muted-foreground">
{summary.scopeType}
</div>
<CardTitle className="mt-1 text-base">{summary.scopeName}</CardTitle>
<CardDescription className="mt-1">{windowLabel(summary.windowKind)}</CardDescription>
</div>
<div className={cn("inline-flex items-center gap-2 rounded-full border px-3 py-1 text-[11px] uppercase tracking-[0.18em]", statusTone(summary.status))}>
<div className={cn("inline-flex items-center gap-2 rounded-full border px-3 py-1 text-(length:--fs-11) uppercase tracking-(--ls-0_18)", statusTone(summary.status))}>
<StatusIcon className="h-3.5 w-3.5" />
{summary.paused ? "Paused" : summary.status === "warning" ? "Warning" : summary.status === "hard_stop" ? "Hard stop" : "Healthy"}
</div>

View File

@ -323,7 +323,7 @@ export const ChatComposer = forwardRef<ChatComposerHandle, ChatComposerProps>(fu
) : null}
{hint ? (
<div className="mt-2 inline-flex items-center rounded-full border border-border/70 bg-muted/30 px-2 py-0.5 text-[11px] text-muted-foreground">
<div className="mt-2 inline-flex items-center rounded-full border border-border/70 bg-muted/30 px-2 py-0.5 text-(length:--fs-11) text-muted-foreground">
{hint}
</div>
) : null}

View File

@ -62,7 +62,7 @@ export function ClaudeSubscriptionPanel({
<div className="border border-border px-4 py-4">
<div className="flex items-start justify-between gap-3 border-b border-border pb-3">
<div className="min-w-0">
<div className="text-[11px] font-semibold uppercase tracking-[0.2em] text-muted-foreground">
<div className="text-(length:--fs-11) font-semibold uppercase tracking-(--ls-0_2) text-muted-foreground">
Anthropic subscription
</div>
<div className="mt-1 text-sm text-muted-foreground">
@ -70,7 +70,7 @@ export function ClaudeSubscriptionPanel({
</div>
</div>
{source ? (
<span className="shrink-0 border border-border px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.16em] text-muted-foreground">
<span className="shrink-0 border border-border px-2.5 py-1 text-(length:--fs-10) font-semibold uppercase tracking-(--ls-0_16) text-muted-foreground">
{quotaSourceDisplayName(source)}
</span>
) : null}

View File

@ -65,7 +65,7 @@ export function CodexSubscriptionPanel({
<div className="border border-border px-4 py-4">
<div className="flex items-start justify-between gap-3 border-b border-border pb-3">
<div className="min-w-0">
<div className="text-[11px] font-semibold uppercase tracking-[0.2em] text-muted-foreground">
<div className="text-(length:--fs-11) font-semibold uppercase tracking-(--ls-0_2) text-muted-foreground">
Codex subscription
</div>
<div className="mt-1 text-sm text-muted-foreground">
@ -73,7 +73,7 @@ export function CodexSubscriptionPanel({
</div>
</div>
{source ? (
<span className="shrink-0 border border-border px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.16em] text-muted-foreground">
<span className="shrink-0 border border-border px-2.5 py-1 text-(length:--fs-10) font-semibold uppercase tracking-(--ls-0_16) text-muted-foreground">
{quotaSourceDisplayName(source)}
</span>
) : null}
@ -87,7 +87,7 @@ export function CodexSubscriptionPanel({
<div className="mt-4 space-y-5">
<div className="space-y-3">
<div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
<div className="text-(length:--fs-11) font-semibold uppercase tracking-(--ls-0_18) text-muted-foreground">
Account windows
</div>
<div className="space-y-3">
@ -99,7 +99,7 @@ export function CodexSubscriptionPanel({
{modelWindows.length > 0 ? (
<div className="space-y-3">
<div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
<div className="text-(length:--fs-11) font-semibold uppercase tracking-(--ls-0_18) text-muted-foreground">
Model windows
</div>
<div className="space-y-3">

View File

@ -209,7 +209,7 @@ export function CommandPalette() {
{showSearchAll ? (
<span>
No quick task matches. Press{" "}
<kbd className="rounded border border-border bg-muted px-1 py-0.5 text-[10px]"></kbd>{" "}
<kbd className="rounded border border-border bg-muted px-1 py-0.5 text-(length:--fs-10)"></kbd>{" "}
to <span className="font-medium">search all</span> or keep typing to refine.
</span>
) : (
@ -231,7 +231,7 @@ export function CommandPalette() {
</span>
<span className="ml-auto inline-flex items-center gap-1 text-xs text-muted-foreground">
<span>open full search</span>
<kbd className="rounded border border-border bg-background px-1 py-0.5 text-[10px]"></kbd>
<kbd className="rounded border border-border bg-background px-1 py-0.5 text-(length:--fs-10)"></kbd>
</span>
</CommandItem>
</CommandGroup>

View File

@ -374,12 +374,12 @@ function CommentCard({
)}
<span className="flex items-center gap-1.5">
{isQueued ? (
<span className="inline-flex items-center rounded-full border border-amber-400/60 bg-amber-100/70 px-2 py-0.5 text-[10px] font-medium uppercase tracking-[0.14em] text-amber-800 dark:border-amber-400/40 dark:bg-amber-500/20 dark:text-amber-200">
<span className="inline-flex items-center rounded-full border border-amber-400/60 bg-amber-100/70 px-2 py-0.5 text-(length:--fs-10) font-medium uppercase tracking-(--ls-0_14) text-amber-800 dark:border-amber-400/40 dark:bg-amber-500/20 dark:text-amber-200">
Queued
</span>
) : null}
{followUpRequested ? (
<Badge variant="outline" className="text-[10px] uppercase tracking-[0.14em]">
<Badge variant="outline" className="text-(length:--fs-10) uppercase tracking-(--ls-0_14)">
Follow-up
</Badge>
) : null}
@ -446,12 +446,12 @@ function CommentCard({
comment.runAgentId ? (
<Link
to={`/agents/${comment.runAgentId}/runs/${comment.runId}`}
className="inline-flex items-center rounded-md border border-border bg-accent/30 px-2 py-1 text-[10px] font-mono text-muted-foreground hover:text-foreground hover:bg-accent/50 transition-colors"
className="inline-flex items-center rounded-md border border-border bg-accent/30 px-2 py-1 text-(length:--fs-10) font-mono text-muted-foreground hover:text-foreground hover:bg-accent/50 transition-colors"
>
run {comment.runId.slice(0, 8)}
</Link>
) : (
<span className="inline-flex items-center rounded-md border border-border bg-accent/30 px-2 py-1 text-[10px] font-mono text-muted-foreground">
<span className="inline-flex items-center rounded-md border border-border bg-accent/30 px-2 py-1 text-(length:--fs-10) font-mono text-muted-foreground">
run {comment.runId.slice(0, 8)}
</span>
)
@ -463,12 +463,12 @@ function CommentCard({
{comment.runAgentId ? (
<Link
to={`/agents/${comment.runAgentId}/runs/${comment.runId}`}
className="inline-flex items-center rounded-md border border-border bg-accent/30 px-2 py-1 text-[10px] font-mono text-muted-foreground hover:text-foreground hover:bg-accent/50 transition-colors"
className="inline-flex items-center rounded-md border border-border bg-accent/30 px-2 py-1 text-(length:--fs-10) font-mono text-muted-foreground hover:text-foreground hover:bg-accent/50 transition-colors"
>
run {comment.runId.slice(0, 8)}
</Link>
) : (
<span className="inline-flex items-center rounded-md border border-border bg-accent/30 px-2 py-1 text-[10px] font-mono text-muted-foreground">
<span className="inline-flex items-center rounded-md border border-border bg-accent/30 px-2 py-1 text-(length:--fs-10) font-mono text-muted-foreground">
run {comment.runId.slice(0, 8)}
</span>
)}
@ -516,7 +516,7 @@ function TimelineEventCard({
{event.statusChange ? (
<div className="flex flex-wrap items-center gap-2 text-sm">
<span className="w-14 text-[10px] font-medium uppercase tracking-[0.14em] text-muted-foreground">
<span className="w-14 text-(length:--fs-10) font-medium uppercase tracking-(--ls-0_14) text-muted-foreground">
Status
</span>
<span className="text-muted-foreground">
@ -531,7 +531,7 @@ function TimelineEventCard({
{event.assigneeChange ? (
<div className="flex flex-wrap items-center gap-2 text-sm">
<span className="w-14 text-[10px] font-medium uppercase tracking-[0.14em] text-muted-foreground">
<span className="w-14 text-(length:--fs-10) font-medium uppercase tracking-(--ls-0_14) text-muted-foreground">
Assignee
</span>
<span className="text-muted-foreground">
@ -546,7 +546,7 @@ function TimelineEventCard({
{event.workspaceChange ? (
<div className="flex flex-wrap items-center gap-2 text-sm">
<span className="w-14 text-[10px] font-medium uppercase tracking-[0.14em] text-muted-foreground">
<span className="w-14 text-(length:--fs-10) font-medium uppercase tracking-(--ls-0_14) text-muted-foreground">
Workspace
</span>
<span className="text-muted-foreground">
@ -672,7 +672,7 @@ const TimelineList = memo(function TimelineList({
</div>
</div>
{run.environment || run.environmentLease ? (
<div className="mt-2 flex flex-wrap gap-x-3 gap-y-1 text-[11px] text-muted-foreground">
<div className="mt-2 flex flex-wrap gap-x-3 gap-y-1 text-(length:--fs-11) text-muted-foreground">
{run.environment ? (
<span>
Environment <span className="text-foreground">{run.environment.name}</span>
@ -989,7 +989,7 @@ export function CommentThread({
{queuedComments.length > 0 && (
<div className="space-y-3">
<div className="flex items-center justify-between gap-2">
<h4 className="text-xs font-semibold uppercase tracking-[0.14em] text-amber-700 dark:text-amber-300">
<h4 className="text-xs font-semibold uppercase tracking-(--ls-0_14) text-amber-700 dark:text-amber-300">
Queued Comments ({queuedComments.length})
</h4>
{onInterruptQueued && queuedComments[0]?.queueTargetRunId ? (

View File

@ -100,7 +100,7 @@ export function CompanySettingsSidebar() {
</div>
<nav className="flex-1 min-h-0 overflow-y-auto scrollbar-auto-hide px-3 py-2">
<div className="px-3 pb-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
<div className="px-3 pb-1 text-(length:--fs-11) font-semibold uppercase tracking-wide text-muted-foreground">
Company settings
</div>
<div className="flex flex-col gap-0.5">
@ -134,7 +134,7 @@ export function CompanySettingsSidebar() {
<SidebarNavItem to="/company/settings/invites" label="Invites" icon={MailPlus} end />
<SidebarNavItem to="/company/settings/secrets" label="Secrets" icon={KeyRound} end />
</div>
<div className="mt-5 px-3 pb-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
<div className="mt-5 px-3 pb-1 text-(length:--fs-11) font-semibold uppercase tracking-wide text-muted-foreground">
Instance settings
</div>
<div className="flex flex-col gap-0.5">

View File

@ -68,11 +68,11 @@ export function DevRestartBanner({ devServer }: { devServer?: DevServerHealthSta
<div className="border-b border-amber-300/60 bg-amber-50 text-amber-950 dark:border-amber-500/25 dark:bg-amber-500/10 dark:text-amber-100">
<div className="flex flex-col gap-3 px-3 py-2.5 md:flex-row md:items-center md:justify-between">
<div className="min-w-0">
<div className="flex items-center gap-2 text-[12px] font-semibold uppercase tracking-[0.18em]">
<div className="flex items-center gap-2 text-(length:--fs-12) font-semibold uppercase tracking-(--ls-0_18)">
<AlertTriangle className="h-3.5 w-3.5 shrink-0" />
<span>Restart Required</span>
{devServer.autoRestartEnabled ? (
<span className="rounded-full bg-amber-900/10 px-2 py-0.5 text-[10px] tracking-[0.14em] dark:bg-amber-100/10">
<span className="rounded-full bg-amber-900/10 px-2 py-0.5 text-(length:--fs-10) tracking-(--ls-0_14) dark:bg-amber-100/10">
Auto-Restart On
</span>
) : null}

View File

@ -328,7 +328,7 @@ function AnnotationPanelBody(props: AnnotationPanelProps) {
data-testid={bodyTestId}
className="flex items-center justify-end gap-1 border-b border-border bg-popover px-2 py-1.5"
>
<span className="text-[11px] tabular-nums text-muted-foreground">
<span className="text-(length:--fs-11) tabular-nums text-muted-foreground">
rev {props.documentRevisionNumber}
</span>
<Button
@ -348,7 +348,7 @@ function AnnotationPanelBody(props: AnnotationPanelProps) {
{props.newCommentDisabled && props.newCommentDisabledReason ? (
<p
data-testid="document-annotation-disabled-reason"
className="border-b border-border bg-muted px-3 py-1.5 text-[11px] text-muted-foreground"
className="border-b border-border bg-muted px-3 py-1.5 text-(length:--fs-11) text-muted-foreground"
>
{props.newCommentDisabledReason}
</p>
@ -356,7 +356,7 @@ function AnnotationPanelBody(props: AnnotationPanelProps) {
{mutationError ? (
<p
data-testid="document-annotation-error"
className="border-b border-border bg-destructive/10 px-3 py-1.5 text-[11px] text-destructive"
className="border-b border-border bg-destructive/10 px-3 py-1.5 text-(length:--fs-11) text-destructive"
>
{mutationError}
</p>
@ -408,7 +408,7 @@ function AnnotationPanelBody(props: AnnotationPanelProps) {
{currentUser.image ? <AvatarImage src={currentUser.image} alt={currentUser.name} /> : null}
<AvatarFallback>{deriveInitials(currentUser.name)}</AvatarFallback>
</Avatar>
<span className="truncate text-[11px] font-medium text-foreground">{currentUser.name}</span>
<span className="truncate text-(length:--fs-11) font-medium text-foreground">{currentUser.name}</span>
</div>
<Textarea
ref={composerRef}
@ -626,7 +626,7 @@ function CommentRow({
focused && "ring-2 ring-primary/40",
)}
>
<div className="mb-0.5 flex items-center justify-between gap-2 text-[11px]">
<div className="mb-0.5 flex items-center justify-between gap-2 text-(length:--fs-11)">
<span className="flex min-w-0 items-center gap-1.5">
<Avatar size="xs" className="shrink-0">
{author.role === "agent" ? (

View File

@ -95,7 +95,7 @@ export function DocumentDiffModal({
<div className="flex items-center gap-4 shrink-0">
<div className="flex items-center gap-2">
<span className="rounded-full border border-red-500/30 bg-red-500/10 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider text-red-400">Old</span>
<span className="rounded-full border border-red-500/30 bg-red-500/10 px-2 py-0.5 text-(length:--fs-10) font-medium uppercase tracking-wider text-red-400">Old</span>
<Select
value={effectiveLeftId ?? ""}
onValueChange={(value) => setLeftRevisionId(value)}
@ -113,7 +113,7 @@ export function DocumentDiffModal({
</Select>
</div>
<div className="flex items-center gap-2">
<span className="rounded-full border border-green-500/30 bg-green-500/10 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider text-green-400">New</span>
<span className="rounded-full border border-green-500/30 bg-green-500/10 px-2 py-0.5 text-(length:--fs-10) font-medium uppercase tracking-wider text-green-400">New</span>
<Select
value={effectiveRightId ?? ""}
onValueChange={(value) => setRightRevisionId(value)}
@ -141,8 +141,8 @@ export function DocumentDiffModal({
) : leftRevision.id === rightRevision.id ? (
<div className="p-6 text-center text-muted-foreground text-sm">Both sides are the same revision.</div>
) : (
<div className="font-mono text-[12px] leading-6">
<div className="grid grid-cols-[56px_56px_24px_minmax(0,1fr)] border-b border-border/60 bg-muted/30 px-3 py-2 text-[11px] uppercase tracking-wide text-muted-foreground">
<div className="font-mono text-(length:--fs-12) leading-6">
<div className="grid grid-cols-[56px_56px_24px_minmax(0,1fr)] border-b border-border/60 bg-muted/30 px-3 py-2 text-(length:--fs-11) uppercase tracking-wide text-muted-foreground">
<span>Old</span>
<span>New</span>
<span />

View File

@ -74,12 +74,12 @@ export function DocumentFrameHeader({
{documentLabel ? (
<>
<span className="truncate text-sm font-semibold text-foreground">{documentLabel}</span>
<span className="shrink-0 rounded-full border border-border px-2 py-0.5 font-mono text-[10px] uppercase tracking-[0.16em] text-muted-foreground">
<span className="shrink-0 rounded-full border border-border px-2 py-0.5 font-mono text-(length:--fs-10) uppercase tracking-(--ls-0_16) text-muted-foreground">
{documentKey}
</span>
</>
) : (
<span className="shrink-0 rounded-full border border-border px-2 py-0.5 font-mono text-[10px] uppercase tracking-[0.16em] text-muted-foreground">
<span className="shrink-0 rounded-full border border-border px-2 py-0.5 font-mono text-(length:--fs-10) uppercase tracking-(--ls-0_16) text-muted-foreground">
{documentKey}
</span>
)}
@ -91,7 +91,7 @@ export function DocumentFrameHeader({
variant="ghost"
size="sm"
className={cn(
"h-auto px-1.5 py-0 text-[11px] font-normal text-muted-foreground hover:text-foreground",
"h-auto px-1.5 py-0 text-(length:--fs-11) font-normal text-muted-foreground hover:text-foreground",
revisionMenu.historicalPreview && "text-amber-300 hover:text-amber-200",
)}
>
@ -118,7 +118,7 @@ export function DocumentFrameHeader({
<div className="flex items-center gap-2">
<span className="font-medium">rev {revision.revisionNumber}</span>
{isCurrentRevision ? (
<span className="rounded-full border border-border px-1.5 py-0.5 text-[10px] uppercase tracking-[0.12em] text-muted-foreground">
<span className="rounded-full border border-border px-1.5 py-0.5 text-(length:--fs-10) uppercase tracking-(--ls-0_12) text-muted-foreground">
Current
</span>
) : null}
@ -140,7 +140,7 @@ export function DocumentFrameHeader({
{updatedAt ? (
<a
href={updatedHref ?? `#document-${encodeURIComponent(documentKey)}`}
className="truncate text-[11px] text-muted-foreground transition-colors hover:text-foreground hover:underline"
className="truncate text-(length:--fs-11) text-muted-foreground transition-colors hover:text-foreground hover:underline"
>
updated {relativeTime(updatedAt)}
</a>

View File

@ -97,7 +97,7 @@ export function ExecutionParticipantPicker({
<PopoverTrigger asChild>
<button
className={cn(
"inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-[10px] font-medium transition-colors cursor-pointer",
"inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-(length:--fs-10) font-medium transition-colors cursor-pointer",
values.length > 0
? "border-border text-foreground hover:bg-accent/50"
: "border-dashed border-border/60 text-muted-foreground hover:border-border hover:text-foreground",

View File

@ -178,29 +178,29 @@ export function ExecutionWorkspaceCloseDialog({
<div className="rounded-xl border border-border bg-background px-4 py-3 text-sm">
<div className="grid gap-2 sm:grid-cols-2">
<div>
<div className="text-xs uppercase tracking-[0.16em] text-muted-foreground">Branch</div>
<div className="text-xs uppercase tracking-(--ls-0_16) text-muted-foreground">Branch</div>
<div className="font-mono text-xs">{readiness.git.branchName ?? "Unknown"}</div>
</div>
<div>
<div className="text-xs uppercase tracking-[0.16em] text-muted-foreground">Base ref</div>
<div className="text-xs uppercase tracking-(--ls-0_16) text-muted-foreground">Base ref</div>
<div className="font-mono text-xs">{readiness.git.baseRef ?? "Not set"}</div>
</div>
<div>
<div className="text-xs uppercase tracking-[0.16em] text-muted-foreground">Merged into base</div>
<div className="text-xs uppercase tracking-(--ls-0_16) text-muted-foreground">Merged into base</div>
<div>{readiness.git.isMergedIntoBase == null ? "Unknown" : readiness.git.isMergedIntoBase ? "Yes" : "No"}</div>
</div>
<div>
<div className="text-xs uppercase tracking-[0.16em] text-muted-foreground">Ahead / behind</div>
<div className="text-xs uppercase tracking-(--ls-0_16) text-muted-foreground">Ahead / behind</div>
<div>
{(readiness.git.aheadCount ?? 0).toString()} / {(readiness.git.behindCount ?? 0).toString()}
</div>
</div>
<div>
<div className="text-xs uppercase tracking-[0.16em] text-muted-foreground">Dirty tracked files</div>
<div className="text-xs uppercase tracking-(--ls-0_16) text-muted-foreground">Dirty tracked files</div>
<div>{readiness.git.dirtyEntryCount}</div>
</div>
<div>
<div className="text-xs uppercase tracking-[0.16em] text-muted-foreground">Untracked files</div>
<div className="text-xs uppercase tracking-(--ls-0_16) text-muted-foreground">Untracked files</div>
<div>{readiness.git.untrackedEntryCount}</div>
</div>
</div>

View File

@ -153,7 +153,7 @@ export function ExternalObjectPill({
</>
);
const countSuffix = typeof sourceCount === "number" && sourceCount > 1 ? (
<span className="tabular-nums text-[10px] font-medium opacity-80">×{sourceCount}</span>
<span className="tabular-nums text-(length:--fs-10) font-medium opacity-80">×{sourceCount}</span>
) : null;
const innerContent = (
<>

View File

@ -68,7 +68,7 @@ export function ExternalObjectStatusSummary({
aria-label={title}
title={title}
className={cn(
"inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 text-[10px] font-medium tabular-nums leading-none",
"inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 text-(length:--fs-10) font-medium tabular-nums leading-none",
badgeClass,
compact && "px-1 py-0.5",
className,

View File

@ -466,7 +466,7 @@ export function FileTree({
{badge && (
<span
className={cn(
"ml-3 shrink-0 rounded-full px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide",
"ml-3 shrink-0 rounded-full px-2 py-0.5 text-(length:--fs-10) font-medium uppercase tracking-wide",
statusBadge[badge.status] ?? statusBadgeDefault,
)}
title={badge.tooltip}

View File

@ -19,22 +19,22 @@ export function FinanceBillerCard({ row }: FinanceBillerCardProps) {
</div>
<div className="text-right">
<div className="text-lg font-semibold tabular-nums">{formatCents(row.netCents)}</div>
<div className="text-[11px] uppercase tracking-[0.16em] text-muted-foreground">net</div>
<div className="text-(length:--fs-11) uppercase tracking-(--ls-0_16) text-muted-foreground">net</div>
</div>
</div>
</CardHeader>
<CardContent className="space-y-3 px-4 pb-4 pt-3">
<div className="grid gap-2 text-sm sm:grid-cols-3">
<div className="border border-border p-3">
<div className="text-[11px] uppercase tracking-[0.14em] text-muted-foreground">debits</div>
<div className="text-(length:--fs-11) uppercase tracking-(--ls-0_14) text-muted-foreground">debits</div>
<div className="mt-1 font-medium tabular-nums">{formatCents(row.debitCents)}</div>
</div>
<div className="border border-border p-3">
<div className="text-[11px] uppercase tracking-[0.14em] text-muted-foreground">credits</div>
<div className="text-(length:--fs-11) uppercase tracking-(--ls-0_14) text-muted-foreground">credits</div>
<div className="mt-1 font-medium tabular-nums">{formatCents(row.creditCents)}</div>
</div>
<div className="border border-border p-3">
<div className="text-[11px] uppercase tracking-[0.14em] text-muted-foreground">estimated</div>
<div className="text-(length:--fs-11) uppercase tracking-(--ls-0_14) text-muted-foreground">estimated</div>
<div className="mt-1 font-medium tabular-nums">{formatCents(row.estimatedDebitCents)}</div>
</div>
</div>

View File

@ -59,7 +59,7 @@ export function FinanceTimelineCard({
<div className="text-right tabular-nums">
<div className="text-sm font-semibold">{formatCents(row.amountCents)}</div>
<div className="text-xs text-muted-foreground">{row.currency}</div>
{row.estimated ? <div className="text-[11px] uppercase tracking-[0.12em] text-amber-600">estimated</div> : null}
{row.estimated ? <div className="text-(length:--fs-11) uppercase tracking-(--ls-0_12) text-amber-600">estimated</div> : null}
</div>
</div>
</div>

View File

@ -356,7 +356,7 @@ export function InlineEditor({
<div className="flex min-h-4 items-center justify-end pr-1">
<span
className={cn(
"text-[11px] transition-opacity duration-150",
"text-(length:--fs-11) transition-opacity duration-150",
autosaveState === "error" ? "text-destructive" : "text-muted-foreground",
autosaveState === "idle" ? "opacity-0" : "opacity-100",
)}

View File

@ -34,8 +34,8 @@ export function IssueAssignedBacklogNotice({
<p className="leading-5">
<span className="font-medium">Parked</span> {" "}
<span className="font-medium">{assigneeLabel}</span> will not be woken until status changes to{" "}
<code className="rounded bg-amber-100 px-1 py-0.5 text-[12px] dark:bg-amber-400/15">todo</code> or{" "}
<code className="rounded bg-amber-100 px-1 py-0.5 text-[12px] dark:bg-amber-400/15">in_progress</code>.
<code className="rounded bg-amber-100 px-1 py-0.5 text-(length:--fs-12) dark:bg-amber-400/15">todo</code> or{" "}
<code className="rounded bg-amber-100 px-1 py-0.5 text-(length:--fs-12) dark:bg-amber-400/15">in_progress</code>.
</p>
{assigneeAgent ? (
<p className="text-xs leading-5 text-amber-800 dark:text-amber-200">

View File

@ -94,7 +94,7 @@ function AttachmentActions({
function AttachmentMeta({ attachment }: { attachment: IssueAttachment }) {
return (
<p className="mt-0.5 text-[11px] text-muted-foreground">
<p className="mt-0.5 text-(length:--fs-11) text-muted-foreground">
Attachment · {attachment.contentType} · {formatBytes(attachment.byteSize)}
</p>
);
@ -134,7 +134,7 @@ function MarkdownAttachmentCard({
<p className="px-1 py-2 text-xs text-destructive">Could not load markdown preview.</p>
) : (
<FoldCurtain>
<MarkdownBody className="paperclip-edit-in-place-content min-h-[220px] text-[15px] leading-7" softBreaks={false}>
<MarkdownBody className="paperclip-edit-in-place-content min-h-[220px] text-(length:--fs-15) leading-7" softBreaks={false}>
{data ?? ""}
</MarkdownBody>
</FoldCurtain>
@ -198,7 +198,7 @@ function GenericAttachmentRow({
>
{filename}
</a>
<p className="truncate text-[11px] text-muted-foreground">
<p className="truncate text-(length:--fs-11) text-muted-foreground">
Attachment · {attachment.contentType} · {formatBytes(attachment.byteSize)}
</p>
</div>

View File

@ -34,7 +34,7 @@ function BlockerRecoveryIndicator({ action }: { action: IssueRecoveryAction }) {
role="status"
aria-label={label}
title={`${label} — open the source task to act.`}
className={`inline-flex shrink-0 items-center gap-0.5 rounded-full border px-1.5 py-0.5 text-[10px] font-medium ${tone.className}`}
className={`inline-flex shrink-0 items-center gap-0.5 rounded-full border px-1.5 py-0.5 text-(length:--fs-10) font-medium ${tone.className}`}
>
<Icon className="h-2.5 w-2.5" aria-hidden />
{label}
@ -189,7 +189,7 @@ export function IssueBlockedNotice({
className="inline-flex max-w-full items-center gap-1 rounded-md border border-amber-300/70 bg-background/80 px-2 py-1 font-mono text-xs text-amber-950 transition-colors hover:border-amber-500 hover:bg-amber-100 hover:underline dark:border-amber-500/40 dark:bg-background/40 dark:text-amber-100 dark:hover:bg-amber-500/15"
>
<span>{blocker.identifier ?? blocker.id.slice(0, 8)}</span>
<span className="max-w-[18rem] truncate font-sans text-[11px] text-amber-800 dark:text-amber-200">
<span className="max-w-[18rem] truncate font-sans text-(length:--fs-11) text-amber-800 dark:text-amber-200">
{blocker.title}
</span>
{recoveryAction ? <BlockerRecoveryIndicator action={recoveryAction} /> : null}
@ -211,7 +211,7 @@ export function IssueBlockedNotice({
<p className="font-medium leading-5">This task still needs a next step.</p>
<p className="leading-5">
A run finished successfully, but this task is still open in{" "}
<code className="rounded bg-amber-100 px-1 py-0.5 text-[12px] dark:bg-amber-400/15">
<code className="rounded bg-amber-100 px-1 py-0.5 text-(length:--fs-12) dark:bg-amber-400/15">
in_progress
</code>{" "}
with no clear owner for the next action.

View File

@ -653,7 +653,7 @@ function IssueChatFallbackThread({
<div className="mb-2 flex items-center gap-2 text-sm">
<span className="font-medium text-foreground">{fallbackAuthorLabel(message)}</span>
{message.createdAt ? (
<span className="text-[11px] text-muted-foreground">
<span className="text-(length:--fs-11) text-muted-foreground">
{commentDateLabel(message.createdAt)}
</span>
) : null}
@ -1049,7 +1049,7 @@ function IssueChatReasoningPart({ text }: { text: string }) {
{ticker.exiting !== null && (
<span
key={`out-${ticker.key}`}
className="cot-line-exit absolute inset-x-0 truncate text-[13px] italic leading-5 text-muted-foreground/70"
className="cot-line-exit absolute inset-x-0 truncate text-(length:--fs-13) italic leading-5 text-muted-foreground/70"
onAnimationEnd={() => setTicker((t) => ({ ...t, exiting: null }))}
>
{ticker.exiting}
@ -1058,7 +1058,7 @@ function IssueChatReasoningPart({ text }: { text: string }) {
<span
key={`in-${ticker.key}`}
className={cn(
"absolute inset-x-0 truncate text-[13px] italic leading-5 text-muted-foreground/70",
"absolute inset-x-0 truncate text-(length:--fs-13) italic leading-5 text-muted-foreground/70",
ticker.key > 0 && "cot-line-enter",
)}
>
@ -1106,7 +1106,7 @@ function IssueChatRollingToolPart({ toolParts }: { toolParts: ToolCallMessagePar
{ticker.exiting !== null && (
<span
key={`out-${ticker.key}`}
className="cot-line-exit absolute inset-x-0 truncate text-[13px] leading-5 text-muted-foreground/70"
className="cot-line-exit absolute inset-x-0 truncate text-(length:--fs-13) leading-5 text-muted-foreground/70"
onAnimationEnd={() => setTicker((t) => ({ ...t, exiting: null }))}
>
{ticker.exiting}
@ -1115,7 +1115,7 @@ function IssueChatRollingToolPart({ toolParts }: { toolParts: ToolCallMessagePar
<span
key={`in-${ticker.key}`}
className={cn(
"absolute inset-x-0 truncate text-[13px] leading-5 text-muted-foreground/70",
"absolute inset-x-0 truncate text-(length:--fs-13) leading-5 text-muted-foreground/70",
ticker.key > 0 && "cot-line-enter",
)}
>
@ -1216,7 +1216,7 @@ function IssueChatToolPart({
className="flex w-full items-center gap-2 rounded-md py-0.5 text-left transition-colors hover:bg-accent/5"
onClick={() => setOpen((current) => !current)}
>
<span className="min-w-0 flex-1 truncate text-[13px] text-muted-foreground/80">
<span className="min-w-0 flex-1 truncate text-(length:--fs-13) text-muted-foreground/80">
{title}
{!intentDetail && summary ? <span className="ml-1.5 text-muted-foreground/50">{summary}</span> : null}
</span>
@ -1230,16 +1230,16 @@ function IssueChatToolPart({
<div className="mt-1 space-y-2 pb-1">
{nonIntentDetails.length > 0 ? (
<div>
<div className="mb-1 text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground/60">
<div className="mb-1 text-(length:--fs-10) font-semibold uppercase tracking-(--ls-0_14) text-muted-foreground/60">
Input
</div>
<dl className="space-y-1.5">
{nonIntentDetails.map((detail) => (
<div key={`${detail.label}:${detail.value}`}>
<dt className="text-[10px] font-medium text-muted-foreground/60">
<dt className="text-(length:--fs-10) font-medium text-muted-foreground/60">
{detail.label}
</dt>
<dd className={cn("text-xs leading-5 text-foreground/70", detail.tone === "code" && "font-mono text-[11px]")}>
<dd className={cn("text-xs leading-5 text-foreground/70", detail.tone === "code" && "font-mono text-(length:--fs-11)")}>
{detail.value}
</dd>
</div>
@ -1248,18 +1248,18 @@ function IssueChatToolPart({
</div>
) : rawArgsText ? (
<div>
<div className="mb-1 text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground/60">
<div className="mb-1 text-(length:--fs-10) font-semibold uppercase tracking-(--ls-0_14) text-muted-foreground/60">
Input
</div>
<CopyablePreBlock className="overflow-x-auto rounded-md bg-accent/30 p-2 text-[11px] leading-4 text-foreground/70">{rawArgsText}</CopyablePreBlock>
<CopyablePreBlock className="overflow-x-auto rounded-md bg-accent/30 p-2 text-(length:--fs-11) leading-4 text-foreground/70">{rawArgsText}</CopyablePreBlock>
</div>
) : null}
{result !== undefined ? (
<div>
<div className="mb-1 text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground/60">
<div className="mb-1 text-(length:--fs-10) font-semibold uppercase tracking-(--ls-0_14) text-muted-foreground/60">
Result
</div>
<CopyablePreBlock className="overflow-x-auto rounded-md bg-accent/30 p-2 text-[11px] leading-4 text-foreground/70">{resultText}</CopyablePreBlock>
<CopyablePreBlock className="overflow-x-auto rounded-md bg-accent/30 p-2 text-(length:--fs-11) leading-4 text-foreground/70">{resultText}</CopyablePreBlock>
</div>
) : null}
</div>
@ -1431,7 +1431,7 @@ function IssueChatUserMessage({
<span className="text-sm font-medium text-foreground">{resolvedAuthorName}</span>
<SourceTrustBadge sourceTrust={sourceTrust} artifactLabel="comment" />
{followUpRequested ? (
<Badge variant="outline" className="text-[10px] uppercase tracking-[0.14em]">
<Badge variant="outline" className="text-(length:--fs-10) uppercase tracking-(--ls-0_14)">
Follow-up
</Badge>
) : null}
@ -1455,14 +1455,14 @@ function IssueChatUserMessage({
>
{queued ? (
<div className="mb-1.5 flex items-center gap-2">
<span className="inline-flex items-center rounded-full border border-amber-400/60 bg-amber-100/70 px-2 py-0.5 text-[10px] font-medium uppercase tracking-[0.14em] text-amber-800 dark:border-amber-400/40 dark:bg-amber-500/20 dark:text-amber-200">
<span className="inline-flex items-center rounded-full border border-amber-400/60 bg-amber-100/70 px-2 py-0.5 text-(length:--fs-10) font-medium uppercase tracking-(--ls-0_14) text-amber-800 dark:border-amber-400/40 dark:bg-amber-500/20 dark:text-amber-200">
{queueBadgeLabel}
</span>
{queueTargetRunId && onInterruptQueued ? (
<Button
size="sm"
variant="outline"
className="h-6 border-red-300 px-2 text-[11px] text-red-700 hover:bg-red-50 hover:text-red-800 dark:border-red-500/40 dark:text-red-300 dark:hover:bg-red-500/10"
className="h-6 border-red-300 px-2 text-(length:--fs-11) text-red-700 hover:bg-red-50 hover:text-red-800 dark:border-red-500/40 dark:text-red-300 dark:hover:bg-red-500/10"
disabled={isInterruptingQueuedRun}
onClick={() => void onInterruptQueued(queueTargetRunId)}
>
@ -1473,7 +1473,7 @@ function IssueChatUserMessage({
<Button
size="sm"
variant="outline"
className="h-6 border-amber-300 px-2 text-[11px] text-amber-900 hover:bg-amber-100/80 hover:text-amber-950 dark:border-amber-500/40 dark:text-amber-100 dark:hover:bg-amber-500/10"
className="h-6 border-amber-300 px-2 text-(length:--fs-11) text-amber-900 hover:bg-amber-100/80 hover:text-amber-950 dark:border-amber-500/40 dark:text-amber-100 dark:hover:bg-amber-500/10"
onClick={() => onCancelQueued(commentId)}
>
Cancel
@ -1491,7 +1491,7 @@ function IssueChatUserMessage({
</div>
{pending ? (
<div className={cn("mt-1 flex px-1 text-[11px] text-muted-foreground", isCurrentUser ? "justify-end" : "justify-start")}>
<div className={cn("mt-1 flex px-1 text-(length:--fs-11) text-muted-foreground", isCurrentUser ? "justify-end" : "justify-start")}>
Sending...
</div>
) : (
@ -1505,7 +1505,7 @@ function IssueChatUserMessage({
<TooltipTrigger asChild>
<a
href={anchorId ? `#${anchorId}` : undefined}
className="text-[11px] text-muted-foreground hover:text-foreground hover:underline"
className="text-(length:--fs-11) text-muted-foreground hover:text-foreground hover:underline"
>
{message.createdAt ? commentDateLabel(message.createdAt) : ""}
</a>
@ -1731,7 +1731,7 @@ function IssueChatAssistantMessage({
<TooltipTrigger asChild>
<a
href={anchorId ? `#${anchorId}` : undefined}
className="text-[11px] text-muted-foreground hover:text-foreground hover:underline"
className="text-(length:--fs-11) text-muted-foreground hover:text-foreground hover:underline"
>
{message.createdAt ? commentDateLabel(message.createdAt) : ""}
</a>
@ -1813,14 +1813,14 @@ function IssueChatAssistantMessage({
<AgentIcon icon={agentIcon} className="h-4 w-4" />
) : (
<Avatar size="sm" className="size-5">
<AvatarFallback className="text-[10px]">{initialsForName(authorName)}</AvatarFallback>
<AvatarFallback className="text-(length:--fs-10)">{initialsForName(authorName)}</AvatarFallback>
</Avatar>
)}
</span>
<span className="text-sm font-medium text-foreground">{authorName}</span>
<SourceTrustBadge sourceTrust={sourceTrust} artifactLabel="comment" />
{followUpRequested ? (
<Badge variant="outline" className="text-[10px] uppercase tracking-[0.14em]">
<Badge variant="outline" className="text-(length:--fs-10) uppercase tracking-(--ls-0_14)">
Follow-up
</Badge>
) : null}
@ -1878,7 +1878,7 @@ function IssueChatAssistantMessage({
<span className="text-xs text-muted-foreground/60">{chainOfThoughtLabel?.toLowerCase()}</span>
<span className="ml-auto flex items-center gap-1.5">
{message.createdAt ? (
<span className="text-[11px] text-muted-foreground/50">
<span className="text-(length:--fs-11) text-muted-foreground/50">
{commentDateLabel(message.createdAt)}
</span>
) : null}
@ -1890,12 +1890,12 @@ function IssueChatAssistantMessage({
<span className="text-sm font-medium text-foreground">{authorName}</span>
<SourceTrustBadge sourceTrust={sourceTrust} artifactLabel="comment" />
{followUpRequested ? (
<Badge variant="outline" className="text-[10px] uppercase tracking-[0.14em]">
<Badge variant="outline" className="text-(length:--fs-10) uppercase tracking-(--ls-0_14)">
Follow-up
</Badge>
) : null}
{isRunning ? (
<span className="inline-flex items-center gap-1 rounded-full border border-cyan-400/40 bg-cyan-500/10 px-2 py-0.5 text-[10px] font-medium uppercase tracking-[0.14em] text-cyan-700 dark:text-cyan-200">
<span className="inline-flex items-center gap-1 rounded-full border border-cyan-400/40 bg-cyan-500/10 px-2 py-0.5 text-(length:--fs-10) font-medium uppercase tracking-(--ls-0_14) text-cyan-700 dark:text-cyan-200">
<Loader2 className="h-3 w-3 animate-spin" />
Running
</span>
@ -2221,7 +2221,7 @@ function ExpiredRequestConfirmationActivity({
</a>
<button
type="button"
className="inline-flex items-center gap-1 rounded-md border border-border/70 bg-background/70 px-1.5 py-0.5 text-[11px] font-medium text-muted-foreground transition-colors hover:border-border hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
className="inline-flex items-center gap-1 rounded-md border border-border/70 bg-background/70 px-1.5 py-0.5 text-(length:--fs-11) font-medium text-muted-foreground transition-colors hover:border-border hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
aria-expanded={expanded}
aria-controls={detailsId}
onClick={() => setExpanded((current) => !current)}
@ -2338,7 +2338,7 @@ function isStaleSuccessfulRunHandoffNotice(input: {
function StaleDispositionWarningMetadataRow({ row }: { row: SystemNoticeMetadataRow }) {
const label = (
<span className="text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground">
<span className="text-(length:--fs-10) font-semibold uppercase tracking-(--ls-0_14) text-muted-foreground">
{row.label}
</span>
);
@ -2348,7 +2348,7 @@ function StaleDispositionWarningMetadataRow({ row }: { row: SystemNoticeMetadata
return <span>{row.value}</span>;
case "code":
return (
<code className="rounded bg-muted px-1.5 py-0.5 font-mono text-[11px] text-foreground/80">
<code className="rounded bg-muted px-1.5 py-0.5 font-mono text-(length:--fs-11) text-foreground/80">
{row.value}
</code>
);
@ -2379,7 +2379,7 @@ function StaleDispositionWarningMetadataRow({ row }: { row: SystemNoticeMetadata
const runShort = row.runId.length > 12 ? `${row.runId.slice(0, 8)}...` : row.runId;
const content = (
<>
<code className="rounded bg-muted px-1.5 py-0.5 font-mono text-[11px] text-foreground/80">
<code className="rounded bg-muted px-1.5 py-0.5 font-mono text-(length:--fs-11) text-foreground/80">
{runShort}
</code>
{row.status ? <span>{row.status}</span> : null}
@ -2454,7 +2454,7 @@ function StaleDispositionWarningDetails({
{sections.map((section) => (
<div key={metadataSectionKey(section)} className="space-y-1.5">
{section.title ? (
<div className="text-[10px] font-semibold uppercase tracking-[0.16em] text-muted-foreground">
<div className="text-(length:--fs-10) font-semibold uppercase tracking-(--ls-0_16) text-muted-foreground">
{section.title}
</div>
) : null}
@ -2501,7 +2501,7 @@ function StaleDispositionWarningRow({
</span>
<span className="ml-auto flex items-center gap-1.5">
{message.createdAt ? (
<span data-testid="stale-disposition-warning-time" className="text-[11px] text-muted-foreground/50">
<span data-testid="stale-disposition-warning-time" className="text-(length:--fs-11) text-muted-foreground/50">
{commentDateLabel(message.createdAt)}
</span>
) : null}
@ -2622,7 +2622,7 @@ function SystemNoticeCommentRow({
<TooltipTrigger asChild>
<a
href={anchorId ? `#${anchorId}` : undefined}
className="text-[11px] text-muted-foreground hover:text-foreground hover:underline"
className="text-(length:--fs-11) text-muted-foreground hover:text-foreground hover:underline"
>
{message.createdAt ? commentDateLabel(message.createdAt) : ""}
</a>
@ -2790,7 +2790,7 @@ function IssueChatSystemMessage({ message }: { message: ThreadMessage }) {
{statusChange ? (
<div className="flex flex-wrap items-center gap-1.5 text-xs">
<span className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground/70">
<span className="text-(length:--fs-10) font-medium uppercase tracking-wider text-muted-foreground/70">
Status
</span>
<span className="text-muted-foreground">{humanizeValue(statusChange.from)}</span>
@ -2802,7 +2802,7 @@ function IssueChatSystemMessage({ message }: { message: ThreadMessage }) {
{assigneeChange ? (
<div className="space-y-1">
<div className={cn("flex flex-wrap items-center gap-1.5 text-xs", isCurrentUser && "justify-end")}>
<span className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground/70">
<span className="text-(length:--fs-10) font-medium uppercase tracking-wider text-muted-foreground/70">
Assignee
</span>
<AssigneeChip assignee={assigneeChange.from} resolvers={handoffResolvers} />
@ -2821,7 +2821,7 @@ function IssueChatSystemMessage({ message }: { message: ThreadMessage }) {
{workspaceChange ? (
<div className="flex flex-wrap items-center gap-1.5 text-xs">
<span className="text-[10px] font-medium uppercase tracking-wider text-muted-foreground/70">
<span className="text-(length:--fs-10) font-medium uppercase tracking-wider text-muted-foreground/70">
Workspace
</span>
<span className="text-muted-foreground">
@ -2853,7 +2853,7 @@ function IssueChatSystemMessage({ message }: { message: ThreadMessage }) {
<span className="text-muted-foreground">run</span>
<Link
to={`/agents/${runAgentId}/runs/${runId}`}
className="inline-flex items-center rounded-md border border-border bg-accent/40 px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground transition-colors hover:bg-accent/60 hover:text-foreground"
className="inline-flex items-center rounded-md border border-border bg-accent/40 px-1.5 py-0.5 font-mono text-(length:--fs-10) text-muted-foreground transition-colors hover:bg-accent/60 hover:text-foreground"
>
{runId.slice(0, 8)}
</Link>
@ -3906,7 +3906,7 @@ const IssueChatComposer = forwardRef<IssueChatComposerHandle, IssueChatComposerP
) : null}
{composerHint ? (
<div className="inline-flex items-center rounded-full border border-border/70 bg-muted/30 px-2 py-1 text-[11px] text-muted-foreground">
<div className="inline-flex items-center rounded-full border border-border/70 bg-muted/30 px-2 py-1 text-(length:--fs-11) text-muted-foreground">
{composerHint}
</div>
) : null}
@ -3998,7 +3998,7 @@ const IssueChatComposer = forwardRef<IssueChatComposerHandle, IssueChatComposerP
aria-keyshortcuts="Meta+Period Control+Period"
title={titleForPendingWorkMode(pendingWorkMode)}
className={cn(
"inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-[11px] font-semibold transition-colors",
"inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-(length:--fs-11) font-semibold transition-colors",
pendingWorkModeMeta.classes.chip,
)}
>
@ -4037,7 +4037,7 @@ const IssueChatComposer = forwardRef<IssueChatComposerHandle, IssueChatComposerP
</button>
);
})}
<div className="mt-1 border-t px-2 py-1.5 text-[10px] text-muted-foreground">
<div className="mt-1 border-t px-2 py-1.5 text-(length:--fs-10) text-muted-foreground">
Cmd/Ctrl+. cycles modes
</div>
</PopoverContent>

View File

@ -96,7 +96,7 @@ export function IssueColumnPicker({
<DropdownMenuContent align="end" className="w-[300px] rounded-xl border-border/70 p-1.5 shadow-xl shadow-black/10">
<DropdownMenuLabel className="px-2 pb-1 pt-1.5">
<div className="space-y-1">
<div className="text-[10px] font-semibold uppercase tracking-[0.22em] text-muted-foreground">
<div className="text-(length:--fs-10) font-semibold uppercase tracking-(--ls-0_22) text-muted-foreground">
Desktop task rows
</div>
<div className="text-sm font-medium text-foreground">
@ -190,7 +190,7 @@ export function InboxIssueMetaLeading({
</span>
<span
className={cn(
"hidden text-[11px] font-medium sm:inline",
"hidden text-(length:--fs-11) font-medium sm:inline",
"text-blue-600 dark:text-blue-400",
)}
>
@ -213,7 +213,7 @@ export function InboxIssueMetaLeading({
)}
aria-hidden="true"
/>
<span className="hidden text-[11px] font-medium text-muted-foreground sm:inline">
<span className="hidden text-(length:--fs-11) font-medium text-muted-foreground sm:inline">
{subtreeLiveCount} live below
</span>
</span>
@ -390,7 +390,7 @@ export function InboxIssueTrailingColumns({
{(issue.labels ?? []).slice(0, 2).map((label) => (
<span
key={label.id}
className="inline-flex min-w-0 max-w-full shrink-0 items-center rounded-full border px-1.5 py-0 text-[10px] font-medium"
className="inline-flex min-w-0 max-w-full shrink-0 items-center rounded-full border px-1.5 py-0 text-(length:--fs-10) font-medium"
style={{
borderColor: label.color,
color: pickTextColorForPillBg(label.color, 0.12),
@ -401,7 +401,7 @@ export function InboxIssueTrailingColumns({
</span>
))}
{(issue.labels ?? []).length > 2 ? (
<span className="shrink-0 text-[10px] font-medium text-muted-foreground">
<span className="shrink-0 text-(length:--fs-10) font-medium text-muted-foreground">
+{(issue.labels ?? []).length - 2}
</span>
) : null}
@ -463,7 +463,7 @@ export function InboxIssueTrailingColumns({
if (column === "updated") {
return (
<span key={column} className="min-w-0 truncate text-right text-[11px] font-medium text-muted-foreground">
<span key={column} className="min-w-0 truncate text-right text-(length:--fs-11) font-medium text-muted-foreground">
{activityText}
</span>
);

View File

@ -77,11 +77,11 @@ export function IssueContinuationHandoff({
<div className="min-w-0 flex-1">
<div className="flex flex-wrap items-center gap-2">
<span className="text-sm font-medium text-foreground">{title}</span>
<span className="rounded-full border border-border px-2 py-0.5 font-mono text-[10px] uppercase text-muted-foreground">
<span className="rounded-full border border-border px-2 py-0.5 font-mono text-(length:--fs-10) uppercase text-muted-foreground">
handoff
</span>
</div>
<div className="text-[11px] text-muted-foreground">
<div className="text-(length:--fs-11) text-muted-foreground">
Updated {relativeTime(document.updatedAt)}
{document.latestRevisionNumber > 0 ? ` - revision ${document.latestRevisionNumber}` : ""}
</div>

View File

@ -425,7 +425,7 @@ export function DocumentAnnotationsCountChip({
variant="ghost"
data-state={panelOpen ? "open" : "closed"}
className={cn(
"h-auto gap-1 rounded-md px-1.5 py-0 text-[11px] font-normal text-muted-foreground hover:text-foreground",
"h-auto gap-1 rounded-md px-1.5 py-0 text-(length:--fs-11) font-normal text-muted-foreground hover:text-foreground",
panelOpen && "bg-muted text-foreground",
openCount > 0 && "text-foreground",
)}

View File

@ -762,7 +762,7 @@ export function IssueDocumentsSection({
const documentBodyShellClassName = "mt-3";
const documentBodyPaddingClassName = "";
const documentBodyContentClassName = "paperclip-edit-in-place-content min-h-[220px] text-[15px] leading-7";
const documentBodyContentClassName = "paperclip-edit-in-place-content min-h-[220px] text-(length:--fs-15) leading-7";
const toggleFoldedDocument = (key: string) => {
setFoldedDocumentKeys((current) =>
current.includes(key)
@ -850,7 +850,7 @@ export function IssueDocumentsSection({
placeholder="Markdown body"
bordered={false}
className="bg-transparent"
contentClassName="min-h-[220px] text-[15px] leading-7"
contentClassName="min-h-[220px] text-(length:--fs-15) leading-7"
mentions={mentions}
imageUploadHandler={imageUploadHandler}
onSubmit={() => void commitDraft(draft, { clearAfterSave: false, trackAutosave: false })}
@ -881,7 +881,7 @@ export function IssueDocumentsSection({
>
<div className="mb-2 flex items-center gap-2">
<FileText className="h-4 w-4 text-amber-600" />
<span className="rounded-full border border-amber-500/30 px-2 py-0.5 font-mono text-[10px] uppercase tracking-[0.16em] text-amber-700 dark:text-amber-300">
<span className="rounded-full border border-amber-500/30 px-2 py-0.5 font-mono text-(length:--fs-10) uppercase tracking-(--ls-0_16) text-amber-700 dark:text-amber-300">
PLAN
</span>
</div>
@ -1144,7 +1144,7 @@ export function IssueDocumentsSection({
</div>
{activeConflict.showRemote && (
<div className="mt-3 rounded-md border border-border/70 bg-background/60 p-3">
<div className="mb-2 flex items-center gap-2 text-[11px] text-muted-foreground">
<div className="mb-2 flex items-center gap-2 text-(length:--fs-11) text-muted-foreground">
<span>Remote revision {activeConflict.serverDocument.latestRevisionNumber}</span>
<span></span>
<span>updated {relativeTime(activeConflict.serverDocument.updatedAt)}</span>
@ -1152,7 +1152,7 @@ export function IssueDocumentsSection({
{!isPlanKey(doc.key) && activeConflict.serverDocument.title ? (
<p className="mb-2 text-sm font-medium">{activeConflict.serverDocument.title}</p>
) : null}
{renderFoldableBody(activeConflict.serverDocument.body, "text-[14px] leading-7", externalReferences)}
{renderFoldableBody(activeConflict.serverDocument.body, "text-(length:--fs-14) leading-7", externalReferences)}
</div>
)}
</div>
@ -1218,7 +1218,7 @@ export function IssueDocumentsSection({
</div>
<div className="flex min-h-4 items-center justify-end px-1">
<span
className={`text-[11px] transition-opacity duration-150 ${
className={`text-(length:--fs-11) transition-opacity duration-150 ${
isHistoricalPreview
? "text-amber-300"
: activeConflict

View File

@ -117,8 +117,8 @@ export function IssueFiltersPopover({
<Button variant={buttonVariant} size={iconOnly ? "icon" : "sm"} className={`text-xs ${iconOnly ? "relative h-8 w-8 shrink-0" : ""} ${activeFilterCount > 0 ? "text-blue-600 dark:text-blue-400" : ""}`} title={iconOnly ? (activeFilterCount > 0 ? `Filters: ${activeFilterCount}` : "Filter") : undefined}>
<Filter className={iconOnly ? "h-3.5 w-3.5" : "h-3.5 w-3.5 sm:h-3 sm:w-3 sm:mr-1"} />
{!iconOnly && <span className="hidden sm:inline">{activeFilterCount > 0 ? `Filters: ${activeFilterCount}` : "Filter"}</span>}
{!iconOnly && activeFilterCount > 0 ? <span className="ml-0.5 text-[10px] font-medium sm:hidden">{activeFilterCount}</span> : null}
{iconOnly && activeFilterCount > 0 ? <span className="absolute -right-1 -top-1 flex h-3.5 w-3.5 items-center justify-center rounded-full bg-blue-600 text-[9px] font-bold text-white">{activeFilterCount}</span> : null}
{!iconOnly && activeFilterCount > 0 ? <span className="ml-0.5 text-(length:--fs-10) font-medium sm:hidden">{activeFilterCount}</span> : null}
{iconOnly && activeFilterCount > 0 ? <span className="absolute -right-1 -top-1 flex h-3.5 w-3.5 items-center justify-center rounded-full bg-blue-600 text-(length:--fs-9) font-bold text-white">{activeFilterCount}</span> : null}
{!iconOnly && activeFilterCount > 0 ? (
<X
className="ml-1 hidden h-3 w-3 sm:block"

View File

@ -16,14 +16,14 @@ interface IssuePlanDecompositionsSectionProps {
function StatusBadge({ status }: { status: AcceptedPlanDecompositionSummary["status"] }) {
if (status === "completed") {
return (
<span className="inline-flex items-center gap-1 rounded-sm border border-emerald-500/50 bg-emerald-500/10 px-2 py-0.5 text-[11px] font-medium text-emerald-900 dark:text-emerald-100">
<span className="inline-flex items-center gap-1 rounded-sm border border-emerald-500/50 bg-emerald-500/10 px-2 py-0.5 text-(length:--fs-11) font-medium text-emerald-900 dark:text-emerald-100">
<CheckCircle2 className="h-3 w-3" />
Completed
</span>
);
}
return (
<span className="inline-flex items-center gap-1 rounded-sm border border-amber-500/50 bg-amber-500/10 px-2 py-0.5 text-[11px] font-medium text-amber-900 dark:text-amber-100">
<span className="inline-flex items-center gap-1 rounded-sm border border-amber-500/50 bg-amber-500/10 px-2 py-0.5 text-(length:--fs-11) font-medium text-amber-900 dark:text-amber-100">
<Loader2 className="h-3 w-3 animate-spin" />
In flight
</span>
@ -47,7 +47,7 @@ export function IssuePlanDecompositionsSection({
<div className="space-y-3">
<div className="flex items-center justify-between gap-2">
<h3 className="text-sm font-medium text-muted-foreground">Plan decomposition</h3>
<span className="text-[11px] text-muted-foreground/80">
<span className="text-(length:--fs-11) text-muted-foreground/80">
{items.length === 1 ? "1 accepted plan revision" : `${items.length} accepted plan revisions`}
</span>
</div>
@ -99,7 +99,7 @@ export function IssuePlanDecompositionsSection({
</span>
{record.status === "completed" && requested > 0 ? (
<span
className="inline-flex items-center gap-1 rounded-sm border border-sky-500/40 bg-sky-500/10 px-1.5 py-0.5 text-[10px] font-medium text-sky-900 dark:text-sky-100"
className="inline-flex items-center gap-1 rounded-sm border border-sky-500/40 bg-sky-500/10 px-1.5 py-0.5 text-(length:--fs-10) font-medium text-sky-900 dark:text-sky-100"
title="Repeat attempts with this fingerprint reuse this record instead of creating new children"
>
<Repeat className="h-3 w-3" />
@ -108,7 +108,7 @@ export function IssuePlanDecompositionsSection({
) : null}
</div>
<div className="mt-1 flex flex-wrap gap-x-3 gap-y-0.5 text-[11px] text-muted-foreground">
<div className="mt-1 flex flex-wrap gap-x-3 gap-y-0.5 text-(length:--fs-11) text-muted-foreground">
{ownerName ? <span>Owner: {ownerName}</span> : null}
{startedAt ? (
<span title={formatDateTime(startedAt)}>Started {relativeTime(startedAt)}</span>
@ -135,7 +135,7 @@ export function IssuePlanDecompositionsSection({
<Link
to={`/issues/${child.identifier ?? child.id}`}
className={cn(
"inline-flex max-w-full items-center gap-1 rounded-sm border border-border bg-background px-2 py-0.5 text-[11px] text-foreground transition-colors hover:bg-accent/40",
"inline-flex max-w-full items-center gap-1 rounded-sm border border-border bg-background px-2 py-0.5 text-(length:--fs-11) text-foreground transition-colors hover:bg-accent/40",
)}
title={child.title}
>

View File

@ -220,7 +220,7 @@ function MetadataRow({
}) {
return (
<div className="grid grid-cols-[7.5rem_1fr] gap-x-3 gap-y-0 px-3 py-1.5 text-xs sm:px-4">
<dt className="truncate text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground">
<dt className="truncate text-(length:--fs-11) font-medium uppercase tracking-(--ls-0_08) text-muted-foreground">
{label}
</dt>
<dd className="min-w-0 break-words text-foreground/90">{children}</dd>
@ -272,11 +272,11 @@ function RunChip({
const short = shortenRunId(runId);
const inner = (
<>
<code className="rounded bg-background/80 px-1.5 py-0.5 font-mono text-[11px] text-foreground/80">
<code className="rounded bg-background/80 px-1.5 py-0.5 font-mono text-(length:--fs-11) text-foreground/80">
run {short}
</code>
{status ? (
<span className="font-sans text-[11px] text-muted-foreground">{status}</span>
<span className="font-sans text-(length:--fs-11) text-muted-foreground">{status}</span>
) : null}
</>
);
@ -404,10 +404,10 @@ export function IssueRecoveryActionCard({
<ToneIcon className={cn("h-4 w-4", tone.iconClass)} />
</span>
<div className="min-w-0 flex-1">
<div className="flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[11px] font-semibold uppercase tracking-[0.14em]">
<div className="flex flex-wrap items-center gap-x-2 gap-y-0.5 text-(length:--fs-11) font-semibold uppercase tracking-(--ls-0_14)">
<span className={tone.labelClass}>{tone.label}</span>
<span className="text-muted-foreground/60" aria-hidden>·</span>
<code className="rounded bg-background/70 px-1.5 py-0.5 font-mono text-[11px] tracking-normal text-muted-foreground">
<code className="rounded bg-background/70 px-1.5 py-0.5 font-mono text-(length:--fs-11) tracking-normal text-muted-foreground">
{KIND_LABEL[action.kind] ?? action.kind}
</code>
{updatedAtLabel ? (
@ -419,7 +419,7 @@ export function IssueRecoveryActionCard({
</>
) : null}
</div>
<p className="mt-1 text-[14px] leading-6">{headline}</p>
<p className="mt-1 text-(length:--fs-14) leading-6">{headline}</p>
</div>
</header>
<dl className={cn("border-t bg-background/40 dark:bg-background/20", tone.divider)}>
@ -457,7 +457,7 @@ export function IssueRecoveryActionCard({
) : null}
<MetadataRow label="Evidence">
{evidenceSummary ? (
<span className="break-words font-mono text-[11px] text-foreground/80">{evidenceSummary}</span>
<span className="break-words font-mono text-(length:--fs-11) text-foreground/80">{evidenceSummary}</span>
) : (
<MissingValue />
)}
@ -469,12 +469,12 @@ export function IssueRecoveryActionCard({
<span className="inline-flex flex-wrap items-center gap-1.5">
{wakeSummary ? <span>{wakeSummary}</span> : <MissingValue />}
{showAttempt ? (
<span className="rounded-md border border-border/50 bg-background/60 px-1.5 py-0.5 text-[11px] text-muted-foreground">
<span className="rounded-md border border-border/50 bg-background/60 px-1.5 py-0.5 text-(length:--fs-11) text-muted-foreground">
attempt {action.attemptCount} of {action.maxAttempts}
</span>
) : null}
{showTimeoutInline ? (
<span className="rounded-md border border-border/50 bg-background/60 px-1.5 py-0.5 text-[11px] text-muted-foreground">
<span className="rounded-md border border-border/50 bg-background/60 px-1.5 py-0.5 text-(length:--fs-11) text-muted-foreground">
Times out {formatTimeShort(action.timeoutAt) ?? "soon"}
</span>
) : null}
@ -508,7 +508,7 @@ export function IssueRecoveryActionCard({
sideOffset={6}
className="w-72 p-1.5"
>
<div className="px-2 py-1 text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground">
<div className="px-2 py-1 text-(length:--fs-11) font-semibold uppercase tracking-(--ls-0_12) text-muted-foreground">
Resolve recovery
</div>
<div className="flex flex-col">
@ -524,18 +524,18 @@ export function IssueRecoveryActionCard({
)}
>
<span className="font-medium leading-5">{option.label}</span>
<span className="text-[11px] leading-4 text-muted-foreground">{option.description}</span>
<span className="text-(length:--fs-11) leading-4 text-muted-foreground">{option.description}</span>
</button>
))}
</div>
</PopoverContent>
</Popover>
{cardState === "observe_only" ? (
<span className="text-[11px] text-muted-foreground">
<span className="text-(length:--fs-11) text-muted-foreground">
Recovery is observing without interrupting the live run.
</span>
) : (
<span className="text-[11px] text-muted-foreground">
<span className="text-(length:--fs-11) text-muted-foreground">
The card stays open until an explicit decision is recorded.
</span>
)}

View File

@ -72,7 +72,7 @@ function Section({
>
<span>{group.label}</span>
{group.count > 1 ? (
<span className="tabular-nums text-[10px] font-medium opacity-80">×{group.count}</span>
<span className="tabular-nums text-(length:--fs-10) font-medium opacity-80">×{group.count}</span>
) : null}
</span>
))}

View File

@ -101,7 +101,7 @@ export function IssueRow({
const parkedBlockerIndicator = hasAssignedBacklogBlocker(issue.blockedBy) ? (
<span
data-testid="issue-row-parked-blocker"
className="ml-1.5 inline-flex shrink-0 items-center gap-0.5 rounded-full border border-amber-500/60 bg-amber-500/15 px-2 py-0.5 text-[10px] font-medium text-amber-700 dark:text-amber-300"
className="ml-1.5 inline-flex shrink-0 items-center gap-0.5 rounded-full border border-amber-500/60 bg-amber-500/15 px-2 py-0.5 text-(length:--fs-10) font-medium text-amber-700 dark:text-amber-300"
title="Blocked by parked work — at least one assigned blocker is in backlog and will not wake its assignee."
>
<Flag className="h-2.5 w-2.5" aria-hidden />
@ -256,7 +256,7 @@ function renderRecoveryChip(action: IssueRecoveryAction, selected: boolean): Rea
role="status"
aria-label={label}
className={cn(
"ml-1.5 inline-flex shrink-0 items-center gap-0.5 rounded-full border px-2 py-0.5 text-[10px] font-medium",
"ml-1.5 inline-flex shrink-0 items-center gap-0.5 rounded-full border px-2 py-0.5 text-(length:--fs-10) font-medium",
tone.className,
selected ? "!border-muted-foreground !text-muted-foreground" : null,
)}

View File

@ -580,7 +580,7 @@ export function IssueRunLedgerContent({
<Link
key={child.id}
to={`/issues/${child.identifier ?? child.id}`}
className="inline-flex min-w-0 max-w-full items-center gap-1 rounded-md border border-border bg-background px-2 py-1 text-[11px] hover:bg-accent/40"
className="inline-flex min-w-0 max-w-full items-center gap-1 rounded-md border border-border bg-background px-2 py-1 text-(length:--fs-11) hover:bg-accent/40"
>
<span className="shrink-0 font-mono text-muted-foreground">{child.identifier ?? child.id.slice(0, 8)}</span>
<span className="truncate">{child.title}</span>
@ -588,7 +588,7 @@ export function IssueRunLedgerContent({
</Link>
))}
{children.active.length > 4 ? (
<span className="rounded-md border border-border px-2 py-1 text-[11px] text-muted-foreground">
<span className="rounded-md border border-border px-2 py-1 text-(length:--fs-11) text-muted-foreground">
+{children.active.length - 4} more
</span>
) : null}
@ -632,7 +632,7 @@ export function IssueRunLedgerContent({
<div className="mt-2 flex flex-wrap gap-1.5">
<button
type="button"
className="rounded-md border border-border bg-background/80 px-2 py-1 text-[11px] text-foreground hover:bg-background"
className="rounded-md border border-border bg-background/80 px-2 py-1 text-(length:--fs-11) text-foreground hover:bg-background"
onClick={() =>
onWatchdogDecision({
runId: latestSilentRun.runId,
@ -645,7 +645,7 @@ export function IssueRunLedgerContent({
</button>
<button
type="button"
className="rounded-md border border-border bg-background/80 px-2 py-1 text-[11px] text-foreground hover:bg-background"
className="rounded-md border border-border bg-background/80 px-2 py-1 text-(length:--fs-11) text-foreground hover:bg-background"
onClick={() =>
onWatchdogDecision({
runId: latestSilentRun.runId,
@ -660,7 +660,7 @@ export function IssueRunLedgerContent({
</button>
<button
type="button"
className="rounded-md border border-border bg-background/80 px-2 py-1 text-[11px] text-foreground hover:bg-background"
className="rounded-md border border-border bg-background/80 px-2 py-1 text-(length:--fs-11) text-foreground hover:bg-background"
onClick={() =>
onWatchdogDecision({
runId: latestSilentRun.runId,
@ -675,7 +675,7 @@ export function IssueRunLedgerContent({
</div>
) : null}
{watchdogDecisionError ? (
<p className="mt-2 rounded-md border border-red-500/30 bg-red-500/10 px-2 py-1 text-[11px] text-red-900 dark:text-red-200">
<p className="mt-2 rounded-md border border-red-500/30 bg-red-500/10 px-2 py-1 text-(length:--fs-11) text-red-900 dark:text-red-200">
{watchdogDecisionError}
</p>
) : null}
@ -730,18 +730,18 @@ export function IssueRunLedgerContent({
on behalf of <span className="text-foreground">{onBehalfOfLabel}</span>
</span>
) : null}
<span className="rounded-md border border-border px-1.5 py-0.5 text-[11px] capitalize text-muted-foreground">
<span className="rounded-md border border-border px-1.5 py-0.5 text-(length:--fs-11) capitalize text-muted-foreground">
{statusLabel(run.status)}
</span>
{run.isLive ? (
<span className="inline-flex items-center gap-1 rounded-md border border-cyan-500/30 bg-cyan-500/10 px-1.5 py-0.5 text-[11px] text-cyan-700 dark:text-cyan-300">
<span className="inline-flex items-center gap-1 rounded-md border border-cyan-500/30 bg-cyan-500/10 px-1.5 py-0.5 text-(length:--fs-11) text-cyan-700 dark:text-cyan-300">
<span className="h-1.5 w-1.5 rounded-full bg-cyan-400" />
live
</span>
) : null}
<span
className={cn(
"rounded-md border px-1.5 py-0.5 text-[11px] font-medium",
"rounded-md border px-1.5 py-0.5 text-(length:--fs-11) font-medium",
liveness.tone,
)}
title={liveness.description}
@ -749,17 +749,17 @@ export function IssueRunLedgerContent({
{liveness.label}
</span>
{exhausted ? (
<span className="rounded-md border border-red-500/30 bg-red-500/10 px-1.5 py-0.5 text-[11px] font-medium text-red-700 dark:text-red-300">
<span className="rounded-md border border-red-500/30 bg-red-500/10 px-1.5 py-0.5 text-(length:--fs-11) font-medium text-red-700 dark:text-red-300">
Exhausted
</span>
) : null}
{continuation ? (
<span className="text-[11px] text-muted-foreground">{continuation}</span>
<span className="text-(length:--fs-11) text-muted-foreground">{continuation}</span>
) : null}
{retryState ? (
<span
className={cn(
"rounded-md border px-1.5 py-0.5 text-[11px] font-medium",
"rounded-md border px-1.5 py-0.5 text-(length:--fs-11) font-medium",
retryState.tone,
)}
>
@ -769,7 +769,7 @@ export function IssueRunLedgerContent({
{run.outputSilence && RUN_OUTPUT_SILENCE_COPY[run.outputSilence.level] ? (
<span
className={cn(
"rounded-md border px-1.5 py-0.5 text-[11px] font-medium",
"rounded-md border px-1.5 py-0.5 text-(length:--fs-11) font-medium",
RUN_OUTPUT_SILENCE_COPY[run.outputSilence.level]?.tone,
)}
>
@ -787,7 +787,7 @@ export function IssueRunLedgerContent({
return (
<span
className={cn(
"rounded-md border px-1.5 py-0.5 text-[11px] font-medium",
"rounded-md border px-1.5 py-0.5 text-(length:--fs-11) font-medium",
modelProfileBadgeTone(profile),
)}
title={modelProfileTitle(profile)}
@ -837,7 +837,7 @@ export function IssueRunLedgerContent({
const profile = modelProfileForRun(run);
if (!profile?.fallbackReason || profile.applied === profile.requested) return null;
return (
<p className="min-w-0 break-words text-[11px] leading-5 text-amber-700 dark:text-amber-300">
<p className="min-w-0 break-words text-(length:--fs-11) leading-5 text-amber-700 dark:text-amber-300">
{profile.requested === "cheap"
? "Cheap profile fell back to primary"
: `${profile.requested} profile unavailable`}

View File

@ -218,7 +218,7 @@ function TaskField({
return (
<span
className={cn(
"inline-flex items-center rounded-sm border px-2 py-0.5 text-[10px] font-medium uppercase tracking-[0.16em]",
"inline-flex items-center rounded-sm border px-2 py-0.5 text-(length:--fs-10) font-medium uppercase tracking-(--ls-0_16)",
tone === "default"
? "border-border/70 bg-transparent text-foreground"
: "border-border/60 bg-transparent text-muted-foreground",
@ -316,7 +316,7 @@ function TaskTreeNode({
</div>
</div>
{depth > 0 ? (
<div className="mt-0.5 text-[10px] font-medium uppercase tracking-[0.14em] text-muted-foreground">
<div className="mt-0.5 text-(length:--fs-10) font-medium uppercase tracking-(--ls-0_14) text-muted-foreground">
Child task
</div>
) : null}
@ -332,13 +332,13 @@ function TaskTreeNode({
{createdTask?.issueId ? (
<Link
to={`/issues/${createdTask.identifier ?? createdTask.issueId}`}
className="inline-flex shrink-0 items-center gap-1 rounded-sm border border-emerald-500/50 bg-emerald-500/10 px-2.5 py-1 text-[11px] font-medium text-emerald-900 transition-colors hover:bg-emerald-500/15 dark:text-emerald-100"
className="inline-flex shrink-0 items-center gap-1 rounded-sm border border-emerald-500/50 bg-emerald-500/10 px-2.5 py-1 text-(length:--fs-11) font-medium text-emerald-900 transition-colors hover:bg-emerald-500/15 dark:text-emerald-100"
>
{createdTask.identifier ?? createdTask.issueId.slice(0, 8)}
<ChevronRight className="h-3 w-3" />
</Link>
) : isSkipped ? (
<span className="inline-flex shrink-0 items-center rounded-sm border border-amber-500/60 bg-amber-500/10 px-2.5 py-1 text-[11px] font-medium text-amber-900 dark:text-amber-100">
<span className="inline-flex shrink-0 items-center rounded-sm border border-amber-500/60 bg-amber-500/10 px-2.5 py-1 text-(length:--fs-11) font-medium text-amber-900 dark:text-amber-100">
Skipped
</span>
) : null}
@ -540,7 +540,7 @@ function SuggestTasksCard({
{interaction.status === "accepted" ? (
<div className="rounded-sm border border-emerald-500/60 bg-emerald-500/10 px-4 py-3 text-sm text-emerald-900 dark:text-emerald-100">
<div className="text-[11px] font-semibold uppercase tracking-[0.16em] text-emerald-700">
<div className="text-(length:--fs-11) font-semibold uppercase tracking-(--ls-0_16) text-emerald-700">
Resolution summary
</div>
<p className="mt-1 leading-6">
@ -553,7 +553,7 @@ function SuggestTasksCard({
{interaction.status === "rejected" ? (
<div className="rounded-sm border border-rose-500/60 bg-rose-500/10 px-4 py-3 text-sm text-rose-900 dark:text-rose-100">
<div className="text-[11px] font-semibold uppercase tracking-[0.16em] text-rose-700">
<div className="text-(length:--fs-11) font-semibold uppercase tracking-(--ls-0_16) text-rose-700">
Rejection reason
</div>
<p className={cn(
@ -842,7 +842,7 @@ function AskUserQuestionsCard({
return (
<div className="space-y-4">
<div className="flex flex-wrap items-center gap-2 text-xs text-muted-foreground">
<span className="inline-flex items-center gap-1 rounded-full border border-border/70 bg-background/70 px-2.5 py-1 font-medium uppercase tracking-[0.16em] text-foreground/70">
<span className="inline-flex items-center gap-1 rounded-full border border-border/70 bg-background/70 px-2.5 py-1 font-medium uppercase tracking-(--ls-0_16) text-foreground/70">
<MessageSquareQuote className="h-3 w-3" />
Ask user questions
</span>
@ -862,7 +862,7 @@ function AskUserQuestionsCard({
>
<div className="flex items-start justify-between gap-3">
<div>
<div className="text-[11px] font-semibold uppercase tracking-[0.16em] text-muted-foreground">
<div className="text-(length:--fs-11) font-semibold uppercase tracking-(--ls-0_16) text-muted-foreground">
Question {index + 1}
</div>
<div
@ -1031,7 +1031,7 @@ function AskUserQuestionsCard({
{interaction.result?.summaryMarkdown ? (
<div className="rounded-2xl border border-emerald-300/60 bg-emerald-50/85 p-4">
<div className="mb-2 text-[11px] font-semibold uppercase tracking-[0.16em] text-emerald-700">
<div className="mb-2 text-(length:--fs-11) font-semibold uppercase tracking-(--ls-0_16) text-emerald-700">
Submitted summary
</div>
<MarkdownBody externalReferences={externalReferences}>{interaction.result.summaryMarkdown}</MarkdownBody>
@ -1080,7 +1080,7 @@ function RequestConfirmationTargetChip({
const href = requestConfirmationTargetHref({ interaction, target });
const className = cn(
"inline-flex max-w-full items-center gap-1.5 rounded-sm border px-2 py-0.5 text-[10px] font-medium uppercase tracking-[0.16em]",
"inline-flex max-w-full items-center gap-1.5 rounded-sm border px-2 py-0.5 text-(length:--fs-10) font-medium uppercase tracking-(--ls-0_16)",
tone === "default"
? "border-border/70 bg-transparent text-foreground"
: "border-border/60 bg-transparent text-muted-foreground",
@ -1147,7 +1147,7 @@ function RequestConfirmationResolution({
const expiredByTargetChange = outcome === "stale_target";
return (
<div className="space-y-3 rounded-sm border border-amber-500/60 bg-amber-500/10 px-4 py-3 text-sm text-amber-900 dark:text-amber-100">
<div className="text-[11px] font-semibold uppercase tracking-[0.16em] text-amber-700">
<div className="text-(length:--fs-11) font-semibold uppercase tracking-(--ls-0_16) text-amber-700">
{expiredByComment ? "Expired by comment" : "Expired by target change"}
</div>
<p className="leading-6">
@ -1497,7 +1497,7 @@ function RequestCheckboxConfirmationResolution({
const hiddenCount = selectedLabels.length - CHECKBOX_SUMMARY_LABEL_LIMIT;
const hasHiddenLabels = hiddenCount > 0;
const chipClassName =
"inline-flex items-center rounded-sm border border-border/60 bg-transparent px-2 py-0.5 text-[10px] font-medium uppercase tracking-[0.16em] text-muted-foreground";
"inline-flex items-center rounded-sm border border-border/60 bg-transparent px-2 py-0.5 text-(length:--fs-10) font-medium uppercase tracking-(--ls-0_16) text-muted-foreground";
return (
<div className="space-y-3">
@ -1935,7 +1935,7 @@ export function IssueThreadInteractionCard({
<div className="flex flex-wrap items-start justify-between gap-4">
<div className="min-w-0 flex-1 basis-64">
<div className="flex flex-wrap items-center gap-2">
<span className={cn("inline-flex items-center gap-1 rounded-sm border px-2.5 py-1 text-[11px] font-semibold uppercase tracking-[0.16em]", styles.badge)}>
<span className={cn("inline-flex items-center gap-1 rounded-sm border px-2.5 py-1 text-(length:--fs-11) font-semibold uppercase tracking-(--ls-0_16)", styles.badge)}>
<StatusIcon className="h-3.5 w-3.5" />
{isPlan ? "Plan" : interactionKindLabel(interaction.kind)}
<span className="text-current/60">/</span>
@ -1943,7 +1943,7 @@ export function IssueThreadInteractionCard({
</span>
{interaction.continuationPolicy === "wake_assignee"
|| interaction.continuationPolicy === "wake_assignee_on_accept" ? (
<span className="inline-flex items-center gap-1 rounded-sm border border-border/70 bg-transparent px-2.5 py-1 text-[11px] font-medium uppercase tracking-[0.16em] text-foreground/70">
<span className="inline-flex items-center gap-1 rounded-sm border border-border/70 bg-transparent px-2.5 py-1 text-(length:--fs-11) font-medium uppercase tracking-(--ls-0_16) text-foreground/70">
<ListChecks className="h-3.5 w-3.5" />
{interaction.continuationPolicy === "wake_assignee_on_accept"
? "Wakes on confirm"

View File

@ -144,7 +144,7 @@ function statusBadge(status: string) {
archived: "bg-muted text-muted-foreground",
};
return (
<span className={cn("text-[10px] px-1.5 py-0.5 rounded-full font-medium", colors[status] ?? colors.idle)}>
<span className={cn("text-(length:--fs-10) px-1.5 py-0.5 rounded-full font-medium", colors[status] ?? colors.idle)}>
{status.replace(/_/g, " ")}
</span>
);
@ -405,7 +405,7 @@ export function IssueWorkspaceCard({
)}
{workspace?.repoUrl && (
<div className="flex items-center gap-1.5 text-muted-foreground">
<span className="text-[11px]">Repo:</span>
<span className="text-(length:--fs-11)">Repo:</span>
<CopyableInline value={workspace.repoUrl} mono />
</div>
)}
@ -447,7 +447,7 @@ export function IssueWorkspaceCard({
<div className="pt-0.5">
<Link
to={currentWorkspaceLink}
className="text-[11px] text-muted-foreground hover:text-foreground hover:underline"
className="text-(length:--fs-11) text-muted-foreground hover:text-foreground hover:underline"
>
View workspace details
</Link>
@ -493,7 +493,7 @@ export function IssueWorkspaceCard({
{/* Current workspace summary when editing */}
{workspace && (
<div className="text-[11px] text-muted-foreground space-y-0.5 pt-1 border-t border-border/50">
<div className="text-(length:--fs-11) text-muted-foreground space-y-0.5 pt-1 border-t border-border/50">
<div style={{ overflowWrap: "anywhere" }}>
Current:{" "}
{currentWorkspaceLink ? (

View File

@ -1763,7 +1763,7 @@ export function IssuesList({
target.scrollIntoView({ behavior: "smooth", block: "nearest" });
target.focus?.();
}}
className="inline-flex items-center rounded-full border border-amber-400/45 bg-amber-50/60 px-1.5 py-0.5 text-[10px] font-medium text-amber-700 hover:bg-amber-100/80 dark:border-amber-300/35 dark:bg-amber-400/10 dark:text-amber-300"
className="inline-flex items-center rounded-full border border-amber-400/45 bg-amber-50/60 px-1.5 py-0.5 text-(length:--fs-10) font-medium text-amber-700 hover:bg-amber-100/80 dark:border-amber-300/35 dark:bg-amber-400/10 dark:text-amber-300"
title={firstVisibleBlockerTitle}
aria-label={firstVisibleBlockerTitle}
>
@ -1803,7 +1803,7 @@ export function IssuesList({
{issueBadge ? (
issueBadge === "Paused" ? (
<span
className={cn("ml-1.5 inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 text-[10px] font-medium", statusBadge.paused)}
className={cn("ml-1.5 inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 text-(length:--fs-10) font-medium", statusBadge.paused)}
aria-label="Paused"
title="Paused"
>
@ -1811,14 +1811,14 @@ export function IssuesList({
Paused
</span>
) : (
<span className="ml-1.5 inline-flex items-center rounded-full border border-amber-500/40 bg-amber-500/10 px-1.5 py-0.5 text-[10px] font-medium text-amber-700 dark:text-amber-300">
<span className="ml-1.5 inline-flex items-center rounded-full border border-amber-500/40 bg-amber-500/10 px-1.5 py-0.5 text-(length:--fs-10) font-medium text-amber-700 dark:text-amber-300">
{issueBadge}
</span>
)
) : null}
{isSuccessfulRunHandoffRequired(issue) ? (
<span
className="ml-1.5 inline-flex items-center gap-1 rounded-full border border-amber-400/45 bg-amber-50/60 px-1.5 py-0.5 text-[10px] font-medium text-amber-700 dark:border-amber-300/35 dark:bg-amber-400/10 dark:text-amber-300"
className="ml-1.5 inline-flex items-center gap-1 rounded-full border border-amber-400/45 bg-amber-50/60 px-1.5 py-0.5 text-(length:--fs-10) font-medium text-amber-700 dark:border-amber-300/35 dark:bg-amber-400/10 dark:text-amber-300"
aria-label="Needs next step"
title="This task needs a next step"
>

View File

@ -363,12 +363,12 @@ const FieldWrapper = React.memo(({
</div>
{children}
{description && (
<p className="text-[12px] text-muted-foreground leading-relaxed">
<p className="text-(length:--fs-12) text-muted-foreground leading-relaxed">
{description}
</p>
)}
{error && (
<p className="text-[12px] font-medium text-destructive">{error}</p>
<p className="text-(length:--fs-12) font-medium text-destructive">{error}</p>
)}
</div>
);
@ -695,7 +695,7 @@ const SecretField = React.memo(({
{!hasRawValue ? (
<button
type="button"
className="text-[11px] text-muted-foreground hover:text-foreground"
className="text-(length:--fs-11) text-muted-foreground hover:text-foreground"
onClick={() => {
setShowRawInput(false);
setIsVisible(false);
@ -709,7 +709,7 @@ const SecretField = React.memo(({
) : (
<button
type="button"
className="text-[11px] text-muted-foreground hover:text-foreground"
className="text-(length:--fs-11) text-muted-foreground hover:text-foreground"
onClick={() => setShowRawInput(true)}
disabled={disabled}
>

View File

@ -160,10 +160,10 @@ function KanbanColumn({
title={`${statusLabel(status)}: ${issues.length}`}
>
<StatusIcon status={status} />
<span className={cn("mt-2 [writing-mode:vertical-rl] rotate-180 text-[10px] font-semibold uppercase tracking-wide", tone.header)}>
<span className={cn("mt-2 [writing-mode:vertical-rl] rotate-180 text-(length:--fs-10) font-semibold uppercase tracking-wide", tone.header)}>
{statusLabel(status)}
</span>
<span className={cn("mt-auto rounded-full bg-background px-1.5 py-0.5 text-[10px] font-medium tabular-nums", tone.header)}>
<span className={cn("mt-auto rounded-full bg-background px-1.5 py-0.5 text-(length:--fs-10) font-medium tabular-nums", tone.header)}>
{issues.length}
</span>
</div>
@ -219,7 +219,7 @@ function KanbanColumn({
</button>
) : null}
{issues.length > 0 && (hiddenCount > 0 || issues.length >= visibleCount) ? (
<p className="px-1 pt-1 text-[11px] text-muted-foreground">
<p className="px-1 pt-1 text-(length:--fs-11) text-muted-foreground">
Showing {visibleIssues.length} of {issues.length}
</p>
) : null}
@ -295,7 +295,7 @@ function KanbanCard({
</span>
{isSuccessfulRunHandoffRequired(issue) ? (
<span
className="inline-flex items-center gap-1 rounded-full border border-amber-400/45 bg-amber-50/60 px-1.5 py-0.5 text-[10px] font-medium text-amber-700 dark:border-amber-300/35 dark:bg-amber-400/10 dark:text-amber-300"
className="inline-flex items-center gap-1 rounded-full border border-amber-400/45 bg-amber-50/60 px-1.5 py-0.5 text-(length:--fs-10) font-medium text-amber-700 dark:border-amber-300/35 dark:bg-amber-400/10 dark:text-amber-300"
title="This task needs a next step"
aria-label="Needs next step"
>
@ -304,7 +304,7 @@ function KanbanCard({
</span>
) : null}
{isLive && (
<span className="inline-flex shrink-0 items-center gap-1 text-[10px] font-medium text-blue-600 dark:text-blue-400">
<span className="inline-flex shrink-0 items-center gap-1 text-(length:--fs-10) font-medium text-blue-600 dark:text-blue-400">
<span className="relative flex h-2 w-2">
<span className="animate-pulse absolute inline-flex h-full w-full rounded-full bg-blue-400 opacity-75" />
<span className="relative inline-flex rounded-full h-2 w-2 bg-blue-500" />
@ -314,7 +314,7 @@ function KanbanCard({
)}
{!isLive && subtreeLiveCount > 0 && (
<span
className="inline-flex shrink-0 items-center gap-1 rounded-full border border-border px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground"
className="inline-flex shrink-0 items-center gap-1 rounded-full border border-border px-1.5 py-0.5 text-(length:--fs-10) font-medium text-muted-foreground"
title={`${subtreeLiveCount} sub-task${subtreeLiveCount === 1 ? "" : "s"} running below`}
>
<span className="h-2 w-2 shrink-0 rounded-full border border-muted-foreground/60" aria-hidden="true" />

View File

@ -76,7 +76,7 @@ export function KeyboardShortcutsCheatsheetContent() {
<div className="divide-y divide-border border-t border-border">
{sections.map((section) => (
<div key={section.title} className="px-5 py-3">
<h3 className="mb-2 text-[11px] font-semibold uppercase tracking-wider text-muted-foreground">
<h3 className="mb-2 text-(length:--fs-11) font-semibold uppercase tracking-wider text-muted-foreground">
{section.title}
</h3>
<div className="space-y-1.5">

View File

@ -91,7 +91,7 @@ export function LiveRunWidget({ issueId, companyId }: LiveRunWidgetProps) {
return (
<div className="overflow-hidden rounded-xl border border-cyan-500/25 bg-background/80 shadow-[0_18px_50px_rgba(6,182,212,0.08)]">
<div className="border-b border-border/60 bg-cyan-500/[0.04] px-4 py-3">
<div className="text-xs font-semibold uppercase tracking-[0.18em] text-cyan-700 dark:text-cyan-300">
<div className="text-xs font-semibold uppercase tracking-(--ls-0_18) text-cyan-700 dark:text-cyan-300">
Live Runs
</div>
<div className="mt-1 text-xs text-muted-foreground">
@ -127,7 +127,7 @@ export function LiveRunWidget({ issueId, companyId }: LiveRunWidgetProps) {
<button
onClick={() => handleCancelRun(run.id)}
disabled={cancellingRunIds.has(run.id)}
className="inline-flex items-center gap-1 rounded-full border border-red-500/20 bg-red-500/[0.06] px-2.5 py-1 text-[11px] font-medium text-red-700 transition-colors hover:bg-red-500/[0.12] dark:text-red-300 disabled:opacity-50"
className="inline-flex items-center gap-1 rounded-full border border-red-500/20 bg-red-500/[0.06] px-2.5 py-1 text-(length:--fs-11) font-medium text-red-700 transition-colors hover:bg-red-500/[0.12] dark:text-red-300 disabled:opacity-50"
>
<Square className="h-2.5 w-2.5" fill="currentColor" />
{cancellingRunIds.has(run.id) ? "Stopping…" : "Stop"}
@ -135,7 +135,7 @@ export function LiveRunWidget({ issueId, companyId }: LiveRunWidgetProps) {
)}
<Link
to={`/agents/${run.agentId}/runs/${run.id}`}
className="inline-flex items-center gap-1 rounded-full border border-border/70 bg-background/70 px-2.5 py-1 text-[11px] font-medium text-cyan-700 transition-colors hover:border-cyan-500/30 hover:text-cyan-600 dark:text-cyan-300"
className="inline-flex items-center gap-1 rounded-full border border-border/70 bg-background/70 px-2.5 py-1 text-(length:--fs-11) font-medium text-cyan-700 transition-colors hover:border-cyan-500/30 hover:text-cyan-600 dark:text-cyan-300"
>
Open run
<ExternalLink className="h-3 w-3" />

View File

@ -194,7 +194,7 @@ const codeBlockActionStyle: React.CSSProperties = {
border: "1px solid color-mix(in oklab, var(--foreground) 14%, transparent)",
backgroundColor: "color-mix(in oklab, var(--muted) 92%, var(--background) 8%)",
color: "var(--muted-foreground)",
fontSize: "0.7rem",
fontSize: "var(--fs-0_7rem)",
lineHeight: 1,
cursor: "pointer",
};

View File

@ -1364,7 +1364,7 @@ export const MarkdownEditor = forwardRef<MarkdownEditorRef, MarkdownEditorProps>
)}
{option.kind === "issue" && option.issueIdentifier ? (
<span className="flex min-w-0 items-baseline gap-1.5">
<span className="shrink-0 font-mono text-[11px] text-muted-foreground">
<span className="shrink-0 font-mono text-(length:--fs-11) text-muted-foreground">
{option.issueIdentifier}
</span>
<span className="truncate">{issueMentionTitle(option)}</span>
@ -1377,27 +1377,27 @@ export const MarkdownEditor = forwardRef<MarkdownEditorRef, MarkdownEditorProps>
</span>
)}
{option.kind === "issue" && (
<span className="ml-auto text-[10px] uppercase tracking-wide text-muted-foreground">
<span className="ml-auto text-(length:--fs-10) uppercase tracking-wide text-muted-foreground">
Task
</span>
)}
{option.kind === "project" && option.projectId && (
<span className="ml-auto text-[10px] uppercase tracking-wide text-muted-foreground">
<span className="ml-auto text-(length:--fs-10) uppercase tracking-wide text-muted-foreground">
Project
</span>
)}
{option.kind === "user" && (
<span className="ml-auto text-[10px] uppercase tracking-wide text-muted-foreground">
<span className="ml-auto text-(length:--fs-10) uppercase tracking-wide text-muted-foreground">
User
</span>
)}
{option.kind === "skill" && (
<span className="ml-auto text-[10px] uppercase tracking-wide text-muted-foreground">
<span className="ml-auto text-(length:--fs-10) uppercase tracking-wide text-muted-foreground">
Skill
</span>
)}
{option.kind === "routine" && (
<span className="ml-auto text-[10px] uppercase tracking-wide text-muted-foreground">
<span className="ml-auto text-(length:--fs-10) uppercase tracking-wide text-muted-foreground">
Routine
</span>
)}

View File

@ -76,7 +76,7 @@ export function MobileBottomNav({ visible }: MobileBottomNavProps) {
type="button"
onClick={item.onClick}
className={cn(
"relative flex min-w-0 flex-col items-center justify-center gap-1 rounded-md text-[10px] font-medium transition-colors",
"relative flex min-w-0 flex-col items-center justify-center gap-1 rounded-md text-(length:--fs-10) font-medium transition-colors",
active
? "text-foreground"
: "text-muted-foreground hover:text-foreground",
@ -96,7 +96,7 @@ export function MobileBottomNav({ visible }: MobileBottomNavProps) {
state={SIDEBAR_SCROLL_RESET_STATE}
className={({ isActive }) =>
cn(
"relative flex min-w-0 flex-col items-center justify-center gap-1 rounded-md text-[10px] font-medium transition-colors",
"relative flex min-w-0 flex-col items-center justify-center gap-1 rounded-md text-(length:--fs-10) font-medium transition-colors",
isActive
? "text-foreground"
: "text-muted-foreground hover:text-foreground",
@ -108,7 +108,7 @@ export function MobileBottomNav({ visible }: MobileBottomNavProps) {
<span className="relative">
<Icon className={cn("h-[18px] w-[18px]", isActive && "stroke-[2.3]")} />
{item.badge != null && item.badge > 0 && (
<span className="absolute -right-2 -top-2 rounded-full bg-primary px-1.5 py-0.5 text-[10px] leading-none text-primary-foreground">
<span className="absolute -right-2 -top-2 rounded-full bg-primary px-1.5 py-0.5 text-(length:--fs-10) leading-none text-primary-foreground">
{item.badge > 99 ? "99+" : item.badge}
</span>
)}

View File

@ -311,13 +311,13 @@ export function NewAgentDialog() {
}}
>
{opt.recommended && (
<span className="absolute -top-1.5 right-1.5 bg-green-500 text-white text-[9px] font-semibold px-1.5 py-0.5 rounded-full leading-none">
<span className="absolute -top-1.5 right-1.5 bg-green-500 text-white text-(length:--fs-9) font-semibold px-1.5 py-0.5 rounded-full leading-none">
Recommended
</span>
)}
<opt.icon className="h-4 w-4" />
<span className="font-medium">{opt.label}</span>
<span className="text-muted-foreground text-[10px]">
<span className="text-muted-foreground text-(length:--fs-10)">
{opt.desc}
</span>
</button>

View File

@ -1334,7 +1334,7 @@ export function NewIssueDialog() {
>
<span
className={cn(
"px-1 py-0.5 rounded text-[10px] font-semibold leading-none",
"px-1 py-0.5 rounded text-(length:--fs-10) font-semibold leading-none",
!c.brandColor && "bg-muted",
)}
style={
@ -1779,7 +1779,7 @@ export function NewIssueDialog() {
<div className="px-4 py-3 space-y-2">
<div className="space-y-1.5">
<div className="text-xs font-medium">Execution workspace</div>
<div className="text-[11px] text-muted-foreground">
<div className="text-(length:--fs-11) text-muted-foreground">
Control whether this task runs in the shared workspace, a new isolated workspace, or an existing one.
</div>
<select
@ -1809,12 +1809,12 @@ export function NewIssueDialog() {
/>
)}
{executionWorkspaceMode === "reuse_existing" && selectedReusableExecutionWorkspace && (
<div className="text-[11px] text-muted-foreground">
<div className="text-(length:--fs-11) text-muted-foreground">
Reusing {selectedReusableExecutionWorkspace.name} from {selectedReusableExecutionWorkspace.branchName ?? selectedReusableExecutionWorkspace.cwd ?? "existing execution workspace"}.
</div>
)}
{showParentWorkspaceWarning ? (
<div className="rounded-md border border-amber-300/60 bg-amber-50 px-2 py-1.5 text-[11px] text-amber-900 dark:border-amber-800/70 dark:bg-amber-950/30 dark:text-amber-100">
<div className="rounded-md border border-amber-300/60 bg-amber-50 px-2 py-1.5 text-(length:--fs-11) text-amber-900 dark:border-amber-800/70 dark:bg-amber-950/30 dark:text-amber-100">
Warning: this sub-task will no longer use the parent task workspace{parentExecutionWorkspaceLabel ? ` (${parentExecutionWorkspaceLabel})` : ""}.
</div>
) : null}
@ -1861,7 +1861,7 @@ export function NewIssueDialog() {
))}
</div>
{assigneeModelLane === "cheap" && (
<p className="text-[11px] text-muted-foreground">
<p className="text-(length:--fs-11) text-muted-foreground">
Sends <code>modelProfile: "cheap"</code>{" "}
{assigneeCheapProfile?.adapterConfig && typeof (assigneeCheapProfile.adapterConfig as Record<string, unknown>).model === "string"
? <>· adapter default <code>{String((assigneeCheapProfile.adapterConfig as Record<string, unknown>).model)}</code></>
@ -1871,10 +1871,10 @@ export function NewIssueDialog() {
</p>
)}
{assigneeModelLane === "primary" && (
<p className="text-[11px] text-muted-foreground">Runs on the agent's primary model.</p>
<p className="text-(length:--fs-11) text-muted-foreground">Runs on the agent's primary model.</p>
)}
{assigneeModelLane === "custom" && (
<p className="text-[11px] text-muted-foreground">Override the model and effort for this task only.</p>
<p className="text-(length:--fs-11) text-muted-foreground">Override the model and effort for this task only.</p>
)}
</div>
{assigneeModelLane === "custom" && (
@ -1958,12 +1958,12 @@ export function NewIssueDialog() {
<div key={file.id} className="flex items-start justify-between gap-3 rounded-md border border-border/70 px-3 py-2">
<div className="min-w-0">
<div className="flex items-center gap-2">
<span className="rounded-full border border-border px-2 py-0.5 font-mono text-[10px] uppercase tracking-[0.16em] text-muted-foreground">
<span className="rounded-full border border-border px-2 py-0.5 font-mono text-(length:--fs-10) uppercase tracking-(--ls-0_16) text-muted-foreground">
{file.documentKey}
</span>
<span className="truncate text-sm">{file.file.name}</span>
</div>
<div className="mt-1 flex items-center gap-2 text-[11px] text-muted-foreground">
<div className="mt-1 flex items-center gap-2 text-(length:--fs-11) text-muted-foreground">
<FileText className="h-3.5 w-3.5" />
<span>{file.title || file.file.name}</span>
<span></span>
@ -1997,7 +1997,7 @@ export function NewIssueDialog() {
<Paperclip className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
<span className="truncate text-sm">{file.file.name}</span>
</div>
<div className="mt-1 text-[11px] text-muted-foreground">
<div className="mt-1 text-(length:--fs-11) text-muted-foreground">
{file.file.type || "application/octet-stream"} {formatFileSize(file.file)}
</div>
</div>
@ -2045,7 +2045,7 @@ export function NewIssueDialog() {
<span className="flex flex-col text-left leading-tight">
<span>{s.label}</span>
{s.description ? (
<span className="text-[10px] text-muted-foreground">{s.description}</span>
<span className="text-(length:--fs-10) text-muted-foreground">{s.description}</span>
) : null}
</span>
</button>
@ -2169,7 +2169,7 @@ export function NewIssueDialog() {
</PopoverTrigger>
<PopoverContent className="w-44 p-1" align="start" data-testid="new-issue-more-menu">
<div className="sm:hidden">
<div className="px-2 py-1 text-[10px] font-medium uppercase text-muted-foreground">
<div className="px-2 py-1 text-(length:--fs-10) font-medium uppercase text-muted-foreground">
Priority
</div>
{priorities.map((p) => (

View File

@ -290,7 +290,7 @@ export function OnboardingChat({
<div className="flex items-center gap-1.5 mb-1">
<span
className={cn(
"text-[10px] font-medium uppercase tracking-wide",
"text-(length:--fs-10) font-medium uppercase tracking-wide",
isAgent
? "text-muted-foreground"
: "text-foreground/70",
@ -299,7 +299,7 @@ export function OnboardingChat({
{isAgent ? agentName : "You"}
</span>
{isPlan && (
<span className="inline-flex items-center gap-0.5 text-[10px] text-green-600 dark:text-green-400 font-medium">
<span className="inline-flex items-center gap-0.5 text-(length:--fs-10) text-green-600 dark:text-green-400 font-medium">
<CheckCircle2 className="h-3 w-3" />
Hiring plan detected
</span>
@ -335,7 +335,7 @@ export function OnboardingChat({
</>
)}
</div>
<span className="text-[11px] text-muted-foreground/60 tabular-nums shrink-0">
<span className="text-(length:--fs-11) text-muted-foreground/60 tabular-nums shrink-0">
{elapsedStr}
</span>
</div>
@ -352,7 +352,7 @@ export function OnboardingChat({
<p className="text-sm font-medium">
{agentName} has prepared a hiring plan
</p>
<p className="text-[11px] text-muted-foreground">
<p className="text-(length:--fs-11) text-muted-foreground">
Review it, make edits, then approve.
</p>
</div>
@ -427,7 +427,7 @@ function WelcomeMessage({
{showMessage && (
<div className="rounded-md px-3 py-2 text-sm bg-muted/50 border border-border mr-8 animate-in fade-in duration-300">
<div className="flex items-center gap-1.5 mb-1">
<span className="text-[10px] font-medium uppercase tracking-wide text-muted-foreground">
<span className="text-(length:--fs-10) font-medium uppercase tracking-wide text-muted-foreground">
{agentName}
</span>
</div>

View File

@ -859,7 +859,7 @@ export function OnboardingWizard() {
glow="blue"
size="md"
/>
<p className="text-[11px] text-muted-foreground">
<p className="text-(length:--fs-11) text-muted-foreground">
{step === 3 ? (
"an empty slot for an agent"
) : step === 4 ? (
@ -954,7 +954,7 @@ export function OnboardingWizard() {
</>
)}
<button
className="text-[11px] text-muted-foreground hover:text-foreground transition-colors"
className="text-(length:--fs-11) text-muted-foreground hover:text-foreground transition-colors"
onClick={() => { setOnboardingPath(null); setStep(0); }}
>
Back to start
@ -1003,7 +1003,7 @@ export function OnboardingWizard() {
/>
</div>
<button
className="text-[11px] text-muted-foreground hover:text-foreground transition-colors"
className="text-(length:--fs-11) text-muted-foreground hover:text-foreground transition-colors"
onClick={() => { setOnboardingPath(null); setStep(0); }}
>
Back to start
@ -1043,7 +1043,7 @@ export function OnboardingWizard() {
>
<Sparkles className="h-4 w-4" />
<span className="font-medium">I know my mission</span>
<span className="text-muted-foreground text-[10px]">
<span className="text-muted-foreground text-(length:--fs-10)">
Type it directly
</span>
</button>
@ -1058,7 +1058,7 @@ export function OnboardingWizard() {
>
<ListTodo className="h-4 w-4" />
<span className="font-medium">Help me figure it out</span>
<span className="text-muted-foreground text-[10px]">
<span className="text-muted-foreground text-(length:--fs-10)">
Answer a few questions
</span>
</button>
@ -1093,7 +1093,7 @@ export function OnboardingWizard() {
<button
key={chip}
className={cn(
"rounded-full border px-2.5 py-1 text-[11px] transition-colors",
"rounded-full border px-2.5 py-1 text-(length:--fs-11) transition-colors",
companyGoal === chip
? "border-foreground bg-accent text-foreground"
: "border-border text-muted-foreground hover:text-foreground hover:border-foreground/50"
@ -1185,7 +1185,7 @@ export function OnboardingWizard() {
/>
</div>
<button
className="text-[11px] text-muted-foreground hover:text-foreground transition-colors"
className="text-(length:--fs-11) text-muted-foreground hover:text-foreground transition-colors"
onClick={() => { setMissionConfirmed(false); setCompanyGoal(""); }}
>
Back to questions
@ -1195,13 +1195,13 @@ export function OnboardingWizard() {
{/* Confirm mission note */}
{companyGoal.trim() && (
<p className="text-[11px] text-muted-foreground italic">
<p className="text-(length:--fs-11) text-muted-foreground italic">
You can always change your mission later in settings.
</p>
)}
<button
className="text-[11px] text-muted-foreground hover:text-foreground transition-colors"
className="text-(length:--fs-11) text-muted-foreground hover:text-foreground transition-colors"
onClick={() => setStep(1)}
>
Change company name
@ -1265,13 +1265,13 @@ export function OnboardingWizard() {
}}
>
{opt.recommended && (
<span className="absolute -top-1.5 right-1.5 bg-green-500 text-white text-[9px] font-semibold px-1.5 py-0.5 rounded-full leading-none">
<span className="absolute -top-1.5 right-1.5 bg-green-500 text-white text-(length:--fs-9) font-semibold px-1.5 py-0.5 rounded-full leading-none">
Recommended
</span>
)}
<opt.icon className="h-4 w-4" />
<span className="font-medium">{opt.label}</span>
<span className="text-muted-foreground text-[10px]">
<span className="text-muted-foreground text-(length:--fs-10)">
{opt.description}
</span>
</button>
@ -1326,7 +1326,7 @@ export function OnboardingWizard() {
>
<opt.icon className="h-4 w-4" />
<span className="font-medium">{opt.label}</span>
<span className="text-muted-foreground text-[10px]">
<span className="text-muted-foreground text-(length:--fs-10)">
{opt.comingSoon
? opt.disabledLabel ?? "Coming soon"
: opt.description}
@ -1400,7 +1400,7 @@ export function OnboardingWizard() {
className="mb-1 last:mb-0"
>
{adapterType === "opencode_local" && (
<div className="px-2 py-1 text-[10px] uppercase tracking-wide text-muted-foreground">
<div className="px-2 py-1 text-(length:--fs-10) uppercase tracking-wide text-muted-foreground">
{group.provider} ({group.entries.length})
</div>
)}
@ -1447,7 +1447,7 @@ export function OnboardingWizard() {
<p className="text-xs font-medium">
Adapter environment check
</p>
<p className="text-[11px] text-muted-foreground">
<p className="text-(length:--fs-11) text-muted-foreground">
Runs a live probe that asks the adapter CLI to
respond with hello.
</p>
@ -1464,7 +1464,7 @@ export function OnboardingWizard() {
</div>
{adapterEnvError && (
<div className="rounded-md border border-destructive/30 bg-destructive/10 px-2.5 py-2 text-[11px] text-destructive">
<div className="rounded-md border border-destructive/30 bg-destructive/10 px-2.5 py-2 text-(length:--fs-11) text-destructive">
{adapterEnvError}
</div>
)}
@ -1481,7 +1481,7 @@ export function OnboardingWizard() {
{shouldSuggestUnsetAnthropicApiKey && (
<div className="rounded-md border border-amber-300/60 bg-amber-50/40 px-2.5 py-2 space-y-2">
<p className="text-[11px] text-amber-900/90 leading-relaxed">
<p className="text-(length:--fs-11) text-amber-900/90 leading-relaxed">
Claude failed while{" "}
<span className="font-mono">ANTHROPIC_API_KEY</span>{" "}
is set. You can clear it in this adapter config
@ -1504,7 +1504,7 @@ export function OnboardingWizard() {
)}
{adapterEnvResult && adapterEnvResult.status === "fail" && (
<div className="rounded-md border border-border/70 bg-muted/20 px-2.5 py-2 text-[11px] space-y-1.5">
<div className="rounded-md border border-border/70 bg-muted/20 px-2.5 py-2 text-(length:--fs-11) space-y-1.5">
<p className="font-medium">Manual debug</p>
<p className="text-muted-foreground font-mono break-all">
{adapterType === "cursor"
@ -1750,7 +1750,7 @@ function AdapterEnvironmentResult({
: "text-red-700 dark:text-red-300 border-red-300 dark:border-red-500/40 bg-red-50 dark:bg-red-500/10";
return (
<div className={`rounded-md border px-2.5 py-2 text-[11px] ${statusClass}`}>
<div className={`rounded-md border px-2.5 py-2 text-(length:--fs-11) ${statusClass}`}>
<div className="flex items-center justify-between gap-2">
<span className="font-medium">{statusLabel}</span>
<span className="opacity-80">

View File

@ -242,7 +242,7 @@ export function PipelineItemBodyDocument({
[conversationIssueId, doc?.latestRevisionId, latestBody, onStartConversation, pushToast, saveMutation],
);
const bodyContentClassName = "paperclip-edit-in-place-content min-h-[220px] text-[15px] leading-7";
const bodyContentClassName = "paperclip-edit-in-place-content min-h-[220px] text-(length:--fs-15) leading-7";
const renderReadOnlyBody = (body: string) => (
<FoldCurtain className="max-w-3xl">
@ -276,7 +276,7 @@ export function PipelineItemBodyDocument({
/>
</div>
<div className="mt-2 flex flex-wrap items-center justify-between gap-2">
<span className="text-[11px] text-muted-foreground">
<span className="text-(length:--fs-11) text-muted-foreground">
Saving creates rev {(doc?.latestRevisionNumber ?? 0) + 1} · to save · Esc to cancel
</span>
<div className="flex items-center gap-2">
@ -415,7 +415,7 @@ export function PipelineItemBodyDocument({
/>
) : null}
actionsSlot={editing ? (
<span className="text-[11px] font-medium text-amber-300"> Editing · unsaved</span>
<span className="text-(length:--fs-11) font-medium text-amber-300"> Editing · unsaved</span>
) : (
<Button variant="ghost" size="sm" className="h-auto gap-1.5 px-2 py-1 text-xs" onClick={beginEdit}>
<FilePenLine className="h-3.5 w-3.5" />

View File

@ -113,7 +113,7 @@ export function PipelineStageHistoryPanel({
<p className="text-sm font-medium">
Revision {revision.revisionNumber}
{isCurrent ? (
<span className="ml-2 rounded-full bg-muted px-2 py-0.5 text-[11px] font-medium text-muted-foreground">
<span className="ml-2 rounded-full bg-muted px-2 py-0.5 text-(length:--fs-11) font-medium text-muted-foreground">
Current
</span>
) : null}

View File

@ -46,7 +46,7 @@ export function ProductivityReviewBadge({
<Link
to={reviewPath}
className={cn(
"inline-flex items-center gap-1 rounded-full border border-amber-500/40 bg-amber-500/10 px-2 py-0.5 text-[10px] font-medium text-amber-700 dark:text-amber-300 shrink-0 hover:bg-amber-500/20 transition-colors",
"inline-flex items-center gap-1 rounded-full border border-amber-500/40 bg-amber-500/10 px-2 py-0.5 text-(length:--fs-10) font-medium text-amber-700 dark:text-amber-300 shrink-0 hover:bg-amber-500/20 transition-colors",
className,
)}
aria-label={`Under review · productivity review ${reviewIdentifier} (${label})`}

View File

@ -59,7 +59,7 @@ export type ProjectConfigFieldKey =
function SaveIndicator({ state }: { state: ProjectFieldSaveState }) {
if (state === "saving") {
return (
<span className="inline-flex items-center gap-1 text-[11px] text-muted-foreground">
<span className="inline-flex items-center gap-1 text-(length:--fs-11) text-muted-foreground">
<Loader2 className="h-3 w-3 animate-spin" />
Saving
</span>
@ -67,7 +67,7 @@ function SaveIndicator({ state }: { state: ProjectFieldSaveState }) {
}
if (state === "saved") {
return (
<span className="inline-flex items-center gap-1 text-[11px] text-green-600 dark:text-green-400">
<span className="inline-flex items-center gap-1 text-(length:--fs-11) text-green-600 dark:text-green-400">
<Check className="h-3 w-3" />
Saved
</span>
@ -75,7 +75,7 @@ function SaveIndicator({ state }: { state: ProjectFieldSaveState }) {
}
if (state === "error") {
return (
<span className="inline-flex items-center gap-1 text-[11px] text-destructive">
<span className="inline-flex items-center gap-1 text-(length:--fs-11) text-destructive">
<AlertCircle className="h-3 w-3" />
Failed
</span>
@ -641,7 +641,7 @@ export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSa
}}
onChange={(env) => commitField("env", { env: env ?? null })}
/>
<p className="text-[11px] text-muted-foreground">
<p className="text-(length:--fs-11) text-muted-foreground">
Applied to all runs for tasks in this project. Project values override agent env on key conflicts.
</p>
</div>
@ -669,7 +669,7 @@ export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSa
<TooltipTrigger asChild>
<button
type="button"
className="inline-flex h-4 w-4 items-center justify-center rounded-full border border-border text-[10px] text-muted-foreground hover:text-foreground"
className="inline-flex h-4 w-4 items-center justify-center rounded-full border border-border text-(length:--fs-10) text-muted-foreground hover:text-foreground"
aria-label="Codebase help"
>
?
@ -682,7 +682,7 @@ export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSa
</div>
<div className="space-y-2 rounded-md border border-border/70 p-3">
<div className="space-y-1">
<div className="text-[11px] uppercase tracking-wide text-muted-foreground">Repo</div>
<div className="text-(length:--fs-11) uppercase tracking-wide text-muted-foreground">Repo</div>
{codebase.repoUrl ? (
<div className="flex items-center justify-between gap-2">
{isSafeExternalUrl(codebase.repoUrl) ? (
@ -745,14 +745,14 @@ export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSa
</div>
<div className="space-y-1">
<div className="text-[11px] uppercase tracking-wide text-muted-foreground">Local folder</div>
<div className="text-(length:--fs-11) uppercase tracking-wide text-muted-foreground">Local folder</div>
<div className="flex items-center justify-between gap-2">
<div className="min-w-0 space-y-1">
<div className="min-w-0 break-all font-mono text-xs text-muted-foreground">
{codebase.effectiveLocalFolder}
</div>
{codebase.origin === "managed_checkout" && (
<div className="text-[11px] text-muted-foreground">Paperclip-managed folder.</div>
<div className="text-(length:--fs-11) text-muted-foreground">Paperclip-managed folder.</div>
)}
</div>
<div className="flex items-center gap-1">
@ -783,7 +783,7 @@ export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSa
</div>
{hasAdditionalLegacyWorkspaces && (
<div className="text-[11px] text-muted-foreground">
<div className="text-(length:--fs-11) text-muted-foreground">
Additional legacy workspace records exist on this project. Paperclip is using the primary workspace as the codebase view.
</div>
)}
@ -797,10 +797,10 @@ export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSa
>
<div className="min-w-0 space-y-0.5">
<div className="flex items-center gap-2">
<span className="text-[11px] font-medium">{service.serviceName}</span>
<span className="text-(length:--fs-11) font-medium">{service.serviceName}</span>
<span
className={cn(
"rounded-full px-1.5 py-0.5 text-[10px] uppercase tracking-wide",
"rounded-full px-1.5 py-0.5 text-(length:--fs-10) uppercase tracking-wide",
service.status === "running"
? "bg-green-500/15 text-green-700 dark:text-green-300"
: service.status === "failed"
@ -811,7 +811,7 @@ export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSa
{service.status}
</span>
</div>
<div className="text-[11px] text-muted-foreground">
<div className="text-(length:--fs-11) text-muted-foreground">
{service.url ? (
<a
href={service.url}
@ -826,7 +826,7 @@ export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSa
)}
</div>
</div>
<div className="text-[10px] text-muted-foreground whitespace-nowrap">
<div className="text-(length:--fs-10) text-muted-foreground whitespace-nowrap">
{service.lifecycle}
</div>
</div>
@ -928,7 +928,7 @@ export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSa
<TooltipTrigger asChild>
<button
type="button"
className="inline-flex h-4 w-4 items-center justify-center rounded-full border border-border text-[10px] text-muted-foreground hover:text-foreground"
className="inline-flex h-4 w-4 items-center justify-center rounded-full border border-border text-(length:--fs-10) text-muted-foreground hover:text-foreground"
aria-label="Execution workspaces help"
>
?
@ -974,7 +974,7 @@ export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSa
<span>New tasks default to isolated checkout</span>
<SaveIndicator state={fieldState("execution_workspace_default_mode")} />
</div>
<div className="text-[11px] text-muted-foreground">
<div className="text-(length:--fs-11) text-muted-foreground">
If disabled, new tasks stay on the project's primary checkout unless someone opts in.
</div>
</div>
@ -1158,7 +1158,7 @@ export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSa
placeholder="bash ./scripts/teardown-worktree.sh"
/>
</div>
<p className="text-[11px] text-muted-foreground">
<p className="text-(length:--fs-11) text-muted-foreground">
Provision runs inside the derived worktree before agent execution. Teardown is stored here for
future cleanup flows.
</p>

View File

@ -59,7 +59,7 @@ export function ProjectWorkspaceSummaryCard({
<div className="flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between">
<div className="min-w-0 space-y-2">
<div className="flex flex-wrap items-center gap-2">
<span className="inline-flex items-center rounded-full border border-border bg-background px-2.5 py-1 text-[11px] font-medium uppercase tracking-[0.14em] text-muted-foreground">
<span className="inline-flex items-center rounded-full border border-border bg-background px-2.5 py-1 text-(length:--fs-11) font-medium uppercase tracking-(--ls-0_14) text-muted-foreground">
{workspaceKindLabel(summary.kind)}
</span>
<span className="inline-flex items-center rounded-full border border-border/70 bg-background px-2.5 py-1 text-xs text-muted-foreground">
@ -149,7 +149,7 @@ export function ProjectWorkspaceSummaryCard({
<div className="flex items-start gap-2">
<GitBranch className="mt-0.5 h-3.5 w-3.5 shrink-0 text-muted-foreground" />
<div className="min-w-0 flex-1">
<div className="text-[11px] uppercase tracking-[0.14em] text-muted-foreground">Branch</div>
<div className="text-(length:--fs-11) uppercase tracking-(--ls-0_14) text-muted-foreground">Branch</div>
<div className="flex items-start gap-2">
<CopyText
text={summary.branchName}
@ -176,7 +176,7 @@ export function ProjectWorkspaceSummaryCard({
<div className="flex items-start gap-2">
<FolderOpen className="mt-0.5 h-3.5 w-3.5 shrink-0 text-muted-foreground" />
<div className="min-w-0 flex-1">
<div className="text-[11px] uppercase tracking-[0.14em] text-muted-foreground">Path</div>
<div className="text-(length:--fs-11) uppercase tracking-(--ls-0_14) text-muted-foreground">Path</div>
<div className="flex items-start gap-2">
<CopyText
text={summary.cwd}
@ -204,7 +204,7 @@ export function ProjectWorkspaceSummaryCard({
<div className="flex items-start gap-2">
<ExternalLink className="mt-0.5 h-3.5 w-3.5 shrink-0 text-muted-foreground" />
<div className="min-w-0">
<div className="text-[11px] uppercase tracking-[0.14em] text-muted-foreground">Service</div>
<div className="text-(length:--fs-11) uppercase tracking-(--ls-0_14) text-muted-foreground">Service</div>
<a
href={summary.primaryServiceUrl}
target="_blank"
@ -226,7 +226,7 @@ export function ProjectWorkspaceSummaryCard({
{summary.issues.length > 0 ? (
<div className="space-y-2">
<div className="text-[11px] font-medium uppercase tracking-[0.14em] text-muted-foreground">
<div className="text-(length:--fs-11) font-medium uppercase tracking-(--ls-0_14) text-muted-foreground">
Linked tasks
</div>
<div className="flex flex-wrap gap-2">

View File

@ -76,7 +76,7 @@ export function ProjectWorkspacesContent({
</div>
{cleanupFailedSummaries.length > 0 ? (
<div className="space-y-2">
<div className="text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground">
<div className="text-xs font-medium uppercase tracking-(--ls-0_18) text-muted-foreground">
Cleanup attention needed
</div>
<div className="space-y-3">

View File

@ -272,7 +272,7 @@ export function ProviderQuotaCard({
<span className="text-xs text-muted-foreground truncate font-mono block">
{row.model}
</span>
<span className="text-[11px] text-muted-foreground truncate block">
<span className="text-(length:--fs-11) text-muted-foreground truncate block">
{providerDisplayName(row.biller)} · {billingTypeDisplayName(row.billingType)}
</span>
</div>
@ -314,7 +314,7 @@ export function ProviderQuotaCard({
Subscription quota
</p>
{quotaSource && !isClaudeQuotaPanel && !isCodexQuotaPanel ? (
<span className="text-[10px] uppercase tracking-[0.16em] text-muted-foreground">
<span className="text-(length:--fs-10) uppercase tracking-(--ls-0_16) text-muted-foreground">
{quotaSourceDisplayName(quotaSource)}
</span>
) : null}

View File

@ -57,7 +57,7 @@ export function ReusableExecutionWorkspaceSelect<TWorkspace extends ReusableExec
renderOption={(option, { selected }) => (
<span className="flex min-w-0 flex-col">
<span className={cn("truncate", selected && "font-medium")}>{option.label}</span>
<span className="truncate text-[11px] text-muted-foreground">
<span className="truncate text-(length:--fs-11) text-muted-foreground">
{option.workspace.status ? `${option.workspace.status} - ` : ""}
{option.description}
</span>

View File

@ -427,10 +427,10 @@ function RevisionList({
return (
<aside className="space-y-1">
<header className="flex items-center justify-between pb-2">
<p className="text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground">
<p className="text-xs font-medium uppercase tracking-(--ls-0_18) text-muted-foreground">
Revisions
</p>
<span className="text-[11px] text-muted-foreground">{totalRevisions} total</span>
<span className="text-(length:--fs-11) text-muted-foreground">{totalRevisions} total</span>
</header>
{revisions.map((revision) => {
const isSelected = revision.id === selectedRevisionId;
@ -460,12 +460,12 @@ function RevisionList({
<div className="flex items-center gap-2 text-sm font-medium">
<span>rev {revision.revisionNumber}</span>
{isCurrent && (
<span className="rounded-full border border-border px-1.5 text-[10px] uppercase tracking-[0.12em] text-muted-foreground">
<span className="rounded-full border border-border px-1.5 text-(length:--fs-10) uppercase tracking-(--ls-0_12) text-muted-foreground">
Current
</span>
)}
{revision.restoredFromRevisionId && (
<span className="rounded-full border border-amber-500/40 bg-amber-500/10 px-1.5 text-[10px] uppercase tracking-[0.12em] text-amber-200">
<span className="rounded-full border border-amber-500/40 bg-amber-500/10 px-1.5 text-(length:--fs-10) uppercase tracking-(--ls-0_12) text-amber-200">
Restored
</span>
)}
@ -601,17 +601,17 @@ function RevisionPreview({
</header>
<div className={`${cardWrapper} p-3`}>
<p className="pb-2 text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground">
<p className="pb-2 text-xs font-medium uppercase tracking-(--ls-0_18) text-muted-foreground">
Structured fields
</p>
<div className="grid gap-3 md:grid-cols-2 divide-y md:divide-y-0 divide-border">
{fieldRows.map((row) => (
<div key={row.key} className="space-y-1 p-2">
<p className="text-[11px] uppercase tracking-wide text-muted-foreground">{row.label}</p>
<p className="text-(length:--fs-11) uppercase tracking-wide text-muted-foreground">{row.label}</p>
<p className="text-sm">
{row.value || <span className="text-muted-foreground"></span>}
{row.differs && (
<span className="ml-2 rounded-full border border-amber-500/40 bg-amber-500/10 px-1.5 text-[10px] uppercase tracking-[0.12em] text-amber-200">
<span className="ml-2 rounded-full border border-amber-500/40 bg-amber-500/10 px-1.5 text-(length:--fs-10) uppercase tracking-(--ls-0_12) text-amber-200">
differs from current
</span>
)}
@ -622,7 +622,7 @@ function RevisionPreview({
</div>
<div className={`${cardWrapper} p-3 space-y-2`}>
<p className="text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground">
<p className="text-xs font-medium uppercase tracking-(--ls-0_18) text-muted-foreground">
Description
</p>
<div className="rounded-md bg-background/40 p-3 text-sm leading-7">
@ -635,7 +635,7 @@ function RevisionPreview({
</div>
<div className={`${cardWrapper} p-3 space-y-2`}>
<p className="text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground">
<p className="text-xs font-medium uppercase tracking-(--ls-0_18) text-muted-foreground">
Triggers ({triggers.length})
</p>
{triggers.length === 0 ? (
@ -644,7 +644,7 @@ function RevisionPreview({
<ul className="divide-y divide-border">
{triggers.map((trigger) => (
<li key={trigger.id} className="py-2 flex flex-wrap items-center gap-2 text-sm">
<span className="rounded-full border border-border px-2 py-0.5 text-[10px] uppercase tracking-[0.12em] text-muted-foreground">
<span className="rounded-full border border-border px-2 py-0.5 text-(length:--fs-10) uppercase tracking-(--ls-0_12) text-muted-foreground">
{trigger.kind}
</span>
<span className="font-medium">{trigger.label ?? trigger.kind}</span>
@ -668,7 +668,7 @@ function RevisionPreview({
{snapshot.variables.length > 0 && (
<div className={`${cardWrapper} p-3 space-y-2`}>
<p className="text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground">
<p className="text-xs font-medium uppercase tracking-(--ls-0_18) text-muted-foreground">
Variables ({snapshot.variables.length})
</p>
<ul className="divide-y divide-border">
@ -840,7 +840,7 @@ function RoutineRevisionDiffModal({
</div>
<div className="overflow-auto flex-1 space-y-4">
<section className="space-y-2">
<p className="text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground">
<p className="text-xs font-medium uppercase tracking-(--ls-0_18) text-muted-foreground">
Field changes
</p>
{fieldChanges.length === 0 ? (
@ -871,7 +871,7 @@ function RoutineRevisionDiffModal({
)}
</section>
<section className="space-y-2">
<p className="text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground">
<p className="text-xs font-medium uppercase tracking-(--ls-0_18) text-muted-foreground">
Description diff
</p>
<DiffTable rows={descriptionDiff} />
@ -912,7 +912,7 @@ function RevisionPicker({
return (
<div className="flex items-center gap-2">
<span
className={`rounded-full border px-2 py-0.5 text-[10px] font-medium uppercase tracking-wider ${toneClass}`}
className={`rounded-full border px-2 py-0.5 text-(length:--fs-10) font-medium uppercase tracking-wider ${toneClass}`}
>
{label}
</span>
@ -951,7 +951,7 @@ function DiffTable({ rows }: { rows: DiffRow[] }) {
};
return (
<div className="rounded-md border border-border text-xs font-mono leading-6 overflow-hidden">
<div className="grid grid-cols-[56px_56px_24px_minmax(0,1fr)] border-b border-border/60 bg-muted/30 px-3 py-2 text-[11px] uppercase tracking-wide text-muted-foreground">
<div className="grid grid-cols-[56px_56px_24px_minmax(0,1fr)] border-b border-border/60 bg-muted/30 px-3 py-2 text-(length:--fs-11) uppercase tracking-wide text-muted-foreground">
<span>Old</span>
<span>New</span>
<span />

View File

@ -154,7 +154,7 @@ export function RoutineSaveBar({
>
{isSaving ? <Loader2 className="mr-1.5 h-3.5 w-3.5 animate-spin" /> : null}
Save changes
<kbd className="ml-2 hidden rounded bg-foreground/10 px-1 text-[10px] font-medium sm:inline">
<kbd className="ml-2 hidden rounded bg-foreground/10 px-1 text-(length:--fs-10) font-medium sm:inline">
S
</kbd>
</Button>

View File

@ -114,7 +114,7 @@ export function RoutineSubSidebar({
>
{NAV_GROUPS.map((group) => (
<div key={group.label} className="flex flex-col gap-0.5">
<p className="px-3 py-2 text-[11px] font-semibold uppercase tracking-[0.12em] text-muted-foreground/80">
<p className="px-3 py-2 text-(length:--fs-11) font-semibold uppercase tracking-(--ls-0_12) text-muted-foreground/80">
{group.label}
</p>
{group.items.map((item) => {
@ -189,7 +189,7 @@ export function RoutineSectionPicker({
<SelectContent>
{NAV_GROUPS.map((group) => (
<SelectGroup key={group.label}>
<SelectLabel className="uppercase tracking-[0.12em] text-[11px]">
<SelectLabel className="uppercase tracking-(--ls-0_12) text-(length:--fs-11)">
{group.label}
</SelectLabel>
{group.items.map((item) => (

View File

@ -298,7 +298,7 @@ export function RoutineVariablesHint() {
<div className="space-y-5 text-sm">
<section className="space-y-2">
<h3 className="text-xs font-semibold uppercase tracking-[0.18em] text-muted-foreground">
<h3 className="text-xs font-semibold uppercase tracking-(--ls-0_18) text-muted-foreground">
Custom variables
</h3>
<p className="text-muted-foreground">
@ -319,7 +319,7 @@ export function RoutineVariablesHint() {
</section>
<section className="space-y-2">
<h3 className="text-xs font-semibold uppercase tracking-[0.18em] text-muted-foreground">
<h3 className="text-xs font-semibold uppercase tracking-(--ls-0_18) text-muted-foreground">
Built-in variables
</h3>
<p className="text-muted-foreground">

View File

@ -131,7 +131,7 @@ export function SecretBindingPicker({
{value ? (
<button
type="button"
className="text-[11px] text-muted-foreground hover:text-foreground inline-flex items-center gap-1"
className="text-(length:--fs-11) text-muted-foreground hover:text-foreground inline-flex items-center gap-1"
onClick={() => onChange(null)}
disabled={disabled}
>
@ -210,17 +210,17 @@ export function SecretBindingPicker({
</div>
{selectedSecret ? (
<p className={cn("text-[11px] text-muted-foreground", statusTone(selectedSecret.status))}>
<p className={cn("text-(length:--fs-11) text-muted-foreground", statusTone(selectedSecret.status))}>
{selectedSecret.status !== "active" ? `Status: ${selectedSecret.status}. ` : null}
Bound to {versionDisplay(value?.version)} · {selectedSecret.key}
</p>
) : selectedMissing ? (
<p className="text-[11px] text-destructive flex items-center gap-1">
<p className="text-(length:--fs-11) text-destructive flex items-center gap-1">
<AlertCircle className="h-3 w-3" />
The previously selected secret is no longer available. Pick another or remove the binding.
</p>
) : (filteredSecrets.length === 0 && !secretsQuery.isPending) ? (
<p className="text-[11px] text-muted-foreground">{emptyHint}</p>
<p className="text-(length:--fs-11) text-muted-foreground">{emptyHint}</p>
) : null}
<Dialog open={createOpen} onOpenChange={setCreateOpen}>
@ -249,7 +249,7 @@ export function SecretBindingPicker({
placeholder="Paste the secret value"
className="font-mono text-xs"
/>
<p className="text-[11px] text-muted-foreground mt-1">
<p className="text-(length:--fs-11) text-muted-foreground mt-1">
The value is stored once and never re-displayed. Rotate to replace.
</p>
</div>

View File

@ -145,7 +145,7 @@ export function Sidebar() {
onClick={() => openNewIssue()}
data-slot="icon-button"
aria-label={rail ? "New Task" : undefined}
className="flex items-center gap-2.5 px-3 py-2 pointer-coarse:py-1.5 text-[13px] font-medium text-foreground/80 hover:bg-accent/50 hover:text-foreground transition-colors"
className="flex items-center gap-2.5 px-3 py-2 pointer-coarse:py-1.5 text-(length:--fs-13) font-medium text-foreground/80 hover:bg-accent/50 hover:text-foreground transition-colors"
>
<SquarePen className="h-4 w-4 shrink-0" />
<span className={rail ? SIDEBAR_RAIL_HIDDEN_LABEL : "truncate"}>New Task</span>
@ -197,14 +197,14 @@ export function Sidebar() {
slotTypes={["sidebar"]}
context={pluginContext}
className="flex flex-col gap-0.5"
itemClassName="text-[13px] font-medium"
itemClassName="text-(length:--fs-13) font-medium"
missingBehavior="placeholder"
/>
<PluginLauncherOutlet
placementZones={["sidebar"]}
context={pluginContext}
className="flex flex-col gap-0.5"
itemClassName="text-[13px] font-medium"
itemClassName="text-(length:--fs-13) font-medium"
/>
</SidebarSection>

View File

@ -144,7 +144,7 @@ export function SidebarAccountMenu({
<PopoverTrigger asChild>
<button
type="button"
className="flex w-full items-center gap-2.5 px-3 py-2 text-left text-[13px] font-medium text-foreground/80 transition-colors hover:bg-accent/50 hover:text-foreground"
className="flex w-full items-center gap-2.5 px-3 py-2 text-left text-(length:--fs-13) font-medium text-foreground/80 transition-colors hover:bg-accent/50 hover:text-foreground"
aria-label="Open account menu"
>
<Avatar size="sm">
@ -172,7 +172,7 @@ export function SidebarAccountMenu({
<div className="min-w-0 flex-1 pt-1">
<div className="flex items-center gap-2">
<h2 className="truncate text-base font-semibold text-foreground">{displayName}</h2>
<span className="rounded-full bg-accent px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
<span className="rounded-full bg-accent px-2 py-0.5 text-(length:--fs-10) font-semibold uppercase tracking-wide text-muted-foreground">
{accountBadge}
</span>
</div>

View File

@ -155,7 +155,7 @@ function SidebarAgentItem({
if (isMobile) setSidebarOpen(false);
}}
className={cn(
"flex min-w-0 flex-1 items-center gap-2.5 px-3 py-1.5 pointer-coarse:py-1 text-[13px] font-medium transition-colors",
"flex min-w-0 flex-1 items-center gap-2.5 px-3 py-1.5 pointer-coarse:py-1 text-(length:--fs-13) font-medium transition-colors",
// Reserve room for the ⋯ menu, plus the inline unstar star on starred rows.
starred && !isMobile ? "pr-14" : "pr-8",
isActive
@ -180,7 +180,7 @@ function SidebarAgentItem({
</span>
) : null}
{runCount > 0 ? (
<span className="text-[11px] font-medium text-blue-600 dark:text-blue-400">
<span className="text-(length:--fs-11) font-medium text-blue-600 dark:text-blue-400">
{runCount} live
</span>
) : null}
@ -580,7 +580,7 @@ export function SidebarAgents({ streamlined = false }: { streamlined?: boolean }
onClick={() => {
if (isMobile) setSidebarOpen(false);
}}
className="flex items-center gap-2.5 px-3 py-1.5 pointer-coarse:py-1 text-[13px] font-medium text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground"
className="flex items-center gap-2.5 px-3 py-1.5 pointer-coarse:py-1 text-(length:--fs-13) font-medium text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground"
>
<Users className="shrink-0 h-3.5 w-3.5" />
<span className={rail ? SIDEBAR_RAIL_HIDDEN_LABEL : undefined}>See all agents</span>

View File

@ -51,7 +51,7 @@ function WorkspaceIcon({ company }: { company: Company }) {
companyName={company.name}
logoUrl={company.logoUrl}
brandColor={company.brandColor}
className="size-5 shrink-0 rounded-md text-[11px]"
className="size-5 shrink-0 rounded-md text-(length:--fs-11)"
/>
);
}
@ -118,7 +118,7 @@ function SortableCompanyItem({
</button>
) : (
<>
<span className="shrink-0 rounded bg-muted px-1.5 py-0.5 font-mono text-[10px] text-muted-foreground">
<span className="shrink-0 rounded bg-muted px-1.5 py-0.5 font-mono text-(length:--fs-10) text-muted-foreground">
{company.issuePrefix}
</span>
{isSelected ? <Check className="size-4 text-muted-foreground" /> : null}
@ -244,7 +244,7 @@ export function SidebarCompanyMenu({ open: controlledOpen, onOpenChange }: Sideb
</DropdownMenuTrigger>
<DropdownMenuContent align="start" sideOffset={8} className="w-64 p-1">
<div className="flex items-center justify-between gap-2 px-2 py-1.5">
<DropdownMenuLabel className="p-0 text-[11px] font-semibold uppercase text-muted-foreground">
<DropdownMenuLabel className="p-0 text-(length:--fs-11) font-semibold uppercase text-muted-foreground">
Switch company
</DropdownMenuLabel>
<button
@ -254,7 +254,7 @@ export function SidebarCompanyMenu({ open: controlledOpen, onOpenChange }: Sideb
event.stopPropagation();
setIsEditingOrder((current) => !current);
}}
className="rounded px-1.5 py-0.5 text-[11px] font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
className="rounded px-1.5 py-0.5 text-(length:--fs-11) font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
>
{isEditingOrder ? "Done" : "Edit"}
</button>

View File

@ -97,7 +97,7 @@ export function SidebarNavItem({
onClick={() => { if (isMobile) setSidebarOpen(false); }}
className={({ isActive }) =>
cn(
"flex items-center gap-2.5 px-3 py-2 pointer-coarse:py-1.5 text-[13px] font-medium transition-colors",
"flex items-center gap-2.5 px-3 py-2 pointer-coarse:py-1.5 text-(length:--fs-13) font-medium transition-colors",
isActive
? "bg-accent text-foreground"
: "text-foreground/80 hover:bg-accent/50 hover:text-foreground",
@ -132,7 +132,7 @@ export function SidebarNavItem({
{!rail && textBadge && (
<span
className={cn(
"ml-auto rounded-full px-1.5 py-0.5 text-[10px] font-medium leading-none",
"ml-auto rounded-full px-1.5 py-0.5 text-(length:--fs-10) font-medium leading-none",
textBadgeTone === "amber"
? "bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-400"
: "bg-muted text-muted-foreground",
@ -147,7 +147,7 @@ export function SidebarNavItem({
<span className="animate-pulse absolute inline-flex h-full w-full rounded-full bg-blue-400 opacity-75" />
<span className="relative inline-flex rounded-full h-2 w-2 bg-blue-500" />
</span>
<span className="text-[11px] font-medium text-blue-600 dark:text-blue-400">{liveCount} live</span>
<span className="text-(length:--fs-11) font-medium text-blue-600 dark:text-blue-400">{liveCount} live</span>
</span>
)}
{!rail && hasBadge && (

View File

@ -138,7 +138,7 @@ function ProjectItem({
if (isMobile) setSidebarOpen(false);
}}
className={cn(
"flex min-w-0 flex-1 items-center gap-2.5 px-3 py-1.5 pr-8 pointer-coarse:py-1 text-[13px] font-medium transition-colors",
"flex min-w-0 flex-1 items-center gap-2.5 px-3 py-1.5 pr-8 pointer-coarse:py-1 text-(length:--fs-13) font-medium transition-colors",
activeProjectRef === routeRef || activeProjectRef === project.id
? "bg-accent text-foreground"
: "text-foreground/80 hover:bg-accent/50 hover:text-foreground",

View File

@ -74,7 +74,7 @@ function SidebarSectionHeader({
const hasMenu = Boolean(
menu && ((menu.actions?.length ?? 0) > 0 || (menu.radioChoices?.length ?? 0) > 0),
);
const labelClassName = "text-[10px] font-medium uppercase tracking-widest font-mono text-muted-foreground/60";
const labelClassName = "text-(length:--fs-10) font-medium uppercase tracking-widest font-mono text-muted-foreground/60";
const headerControlVisibilityClassName = isMobile
? "opacity-100"
: "opacity-0 group-hover/sidebar-section:opacity-100 group-focus-within/sidebar-section:opacity-100";

View File

@ -123,7 +123,7 @@ export function SidebarServerInfo() {
return (
<div className="mt-2 border-t border-border pt-2">
<p className="px-3 pb-1 pt-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground">
<p className="px-3 pb-1 pt-1 text-(length:--fs-11) font-medium uppercase tracking-wide text-muted-foreground">
Server
</p>
<ServerInfoRow

View File

@ -121,7 +121,7 @@ export function SidebarStarredProjects() {
if (isMobile) setSidebarOpen(false);
}}
className={cn(
"flex min-w-0 flex-1 items-center gap-2.5 px-3 py-1.5 pl-8 pointer-coarse:py-1 pr-8 text-[13px] font-medium transition-colors",
"flex min-w-0 flex-1 items-center gap-2.5 px-3 py-1.5 pl-8 pointer-coarse:py-1 pr-8 text-(length:--fs-13) font-medium transition-colors",
isActive
? "bg-accent text-foreground"
: "text-foreground/80 hover:bg-accent/50 hover:text-foreground",

View File

@ -16,7 +16,7 @@ export function SourceResolvedFoldBadge({
return (
<span
className={cn(
"inline-flex items-center gap-1 rounded-md border px-1.5 py-0.5 text-[11px] font-medium",
"inline-flex items-center gap-1 rounded-md border px-1.5 py-0.5 text-(length:--fs-11) font-medium",
"border-emerald-300/60 bg-emerald-50/80 text-emerald-900",
"dark:border-emerald-500/30 dark:bg-emerald-500/10 dark:text-emerald-200",
className,

View File

@ -35,7 +35,7 @@ function MetaRow({
}) {
return (
<div className="grid grid-cols-[10rem_1fr] gap-x-3 gap-y-0 py-1 text-xs sm:grid-cols-[12rem_1fr]">
<dt className="truncate text-[11px] font-medium uppercase tracking-[0.08em] text-emerald-900/70 dark:text-emerald-200/70">
<dt className="truncate text-(length:--fs-11) font-medium uppercase tracking-(--ls-0_08) text-emerald-900/70 dark:text-emerald-200/70">
{label}
</dt>
<dd className="min-w-0 break-words text-emerald-950 dark:text-emerald-100">{children}</dd>
@ -80,7 +80,7 @@ export function SourceResolvedFoldCallout({
<Sparkles className="h-4 w-4 text-emerald-700 dark:text-emerald-300" />
</span>
<div className="min-w-0 flex-1">
<div className="flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[11px] font-semibold uppercase tracking-[0.14em]">
<div className="flex flex-wrap items-center gap-x-2 gap-y-0.5 text-(length:--fs-11) font-semibold uppercase tracking-(--ls-0_14)">
<span className="text-emerald-900 dark:text-emerald-200">SOURCE-RESOLVED FOLD</span>
<span className="text-muted-foreground/60" aria-hidden>·</span>
<span className="font-medium normal-case tracking-normal text-muted-foreground">
@ -95,7 +95,7 @@ export function SourceResolvedFoldCallout({
</>
) : null}
</div>
<p className="mt-1 text-[14px] leading-6">
<p className="mt-1 text-(length:--fs-14) leading-6">
This run was folded as a source-resolved false positive.
</p>
</div>
@ -115,24 +115,24 @@ export function SourceResolvedFoldCallout({
>
{sourceLabel}
</Link>
<span className="rounded-md border border-emerald-300/60 bg-background/60 px-1.5 py-0.5 text-[11px] font-medium text-emerald-900 dark:border-emerald-500/30 dark:text-emerald-200">
<span className="rounded-md border border-emerald-300/60 bg-background/60 px-1.5 py-0.5 text-(length:--fs-11) font-medium text-emerald-900 dark:border-emerald-500/30 dark:text-emerald-200">
{fold.sourceIssueStatus}
</span>
</span>
</MetaRow>
<MetaRow label="Same-run evidence">
<span className="inline-flex flex-wrap items-baseline gap-1.5">
<span className="rounded bg-background/70 px-1.5 py-0.5 font-mono text-[11px] text-emerald-900 dark:bg-background/40 dark:text-emerald-100">
<span className="rounded bg-background/70 px-1.5 py-0.5 font-mono text-(length:--fs-11) text-emerald-900 dark:bg-background/40 dark:text-emerald-100">
{fold.sameRunEvidenceKind}
</span>
<code
className="rounded bg-background/70 px-1.5 py-0.5 font-mono text-[11px] text-emerald-900 dark:bg-background/40 dark:text-emerald-100"
className="rounded bg-background/70 px-1.5 py-0.5 font-mono text-(length:--fs-11) text-emerald-900 dark:bg-background/40 dark:text-emerald-100"
title={fold.sameRunEvidenceId}
>
{evidenceShort}
</code>
{evidenceAt ? (
<span className="text-[11px] text-muted-foreground">at {evidenceAt}</span>
<span className="text-(length:--fs-11) text-muted-foreground">at {evidenceAt}</span>
) : null}
</span>
</MetaRow>

View File

@ -29,7 +29,7 @@ export function SourceTrustBadge({
variant="outline"
aria-label={label}
className={cn(
"inline-flex items-center gap-1 whitespace-nowrap px-1.5 py-0 text-[10px] font-medium tracking-normal",
"inline-flex items-center gap-1 whitespace-nowrap px-1.5 py-0 text-(length:--fs-10) font-medium tracking-normal",
promoted
? "border-border text-muted-foreground"
: "border-amber-500/40 text-amber-700 dark:text-amber-100",

View File

@ -114,7 +114,7 @@ function formatTimestamp(ts: string) {
function MetadataRow({ row, tone }: { row: SystemNoticeMetadataRow; tone: ToneTokens }) {
return (
<div className="grid grid-cols-[7.5rem_1fr] gap-x-3 gap-y-0.5 px-3 py-1.5 text-xs">
<div className="truncate text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground">
<div className="truncate text-(length:--fs-11) font-medium uppercase tracking-(--ls-0_08) text-muted-foreground">
{row.label}
</div>
<div className="min-w-0 break-words text-foreground/90">
@ -124,7 +124,7 @@ function MetadataRow({ row, tone }: { row: SystemNoticeMetadataRow; tone: ToneTo
return <span>{row.value}</span>;
case "code":
return (
<code className="rounded bg-muted px-1.5 py-0.5 font-mono text-[11px] text-foreground/80">
<code className="rounded bg-muted px-1.5 py-0.5 font-mono text-(length:--fs-11) text-foreground/80">
{row.value}
</code>
);
@ -187,14 +187,14 @@ function MetadataRow({ row, tone }: { row: SystemNoticeMetadataRow; tone: ToneTo
return (
<a
href={row.href}
className="inline-flex items-center gap-2 rounded-sm font-mono text-[11px] underline-offset-2 hover:underline"
className="inline-flex items-center gap-2 rounded-sm font-mono text-(length:--fs-11) underline-offset-2 hover:underline"
>
{inner}
</a>
);
}
return (
<span className="inline-flex items-center gap-2 font-mono text-[11px]">
<span className="inline-flex items-center gap-2 font-mono text-(length:--fs-11)">
{inner}
</span>
);
@ -252,7 +252,7 @@ export function SystemNotice({
<ToneIcon className={cn("h-4 w-4", tokens.iconClass)} />
</span>
<div className="min-w-0 flex-1">
<div className="flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[11px] font-semibold uppercase tracking-[0.14em]">
<div className="flex flex-wrap items-center gap-x-2 gap-y-0.5 text-(length:--fs-11) font-semibold uppercase tracking-(--ls-0_14)">
<span className={tokens.label}>{resolvedLabel}</span>
{source ? (
<>
@ -280,7 +280,7 @@ export function SystemNotice({
</>
) : null}
</div>
<div className="mt-1 break-words text-[14px] leading-6 text-foreground">{body}</div>
<div className="mt-1 break-words text-(length:--fs-14) leading-6 text-foreground">{body}</div>
</div>
{hasDetails ? (
<button
@ -289,7 +289,7 @@ export function SystemNotice({
aria-expanded={open}
aria-controls={detailsId}
className={cn(
"ml-1 inline-flex h-7 shrink-0 items-center gap-1 rounded-md border border-transparent px-2 text-[11px] font-medium uppercase tracking-[0.12em] text-muted-foreground transition-[background-color,border-color,color]",
"ml-1 inline-flex h-7 shrink-0 items-center gap-1 rounded-md border border-transparent px-2 text-(length:--fs-11) font-medium uppercase tracking-(--ls-0_12) text-muted-foreground transition-[background-color,border-color,color]",
"hover:border-border/70 hover:bg-background/70 hover:text-foreground",
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/50",
)}
@ -316,7 +316,7 @@ export function SystemNotice({
{metadata!.map((section, sectionIdx) => (
<div key={sectionIdx} className="py-1.5 first:pt-2 last:pb-2">
{section.title ? (
<div className="px-3 pb-1 pt-0.5 text-[10px] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
<div className="px-3 pb-1 pt-0.5 text-(length:--fs-10) font-semibold uppercase tracking-(--ls-0_18) text-muted-foreground">
{section.title}
</div>
) : null}

View File

@ -128,7 +128,7 @@ function WorkspaceFileBreadcrumbs({
if (!rootLabel && segments.length === 0) return null;
return (
<nav aria-label="Current folder" className="min-w-0 overflow-hidden text-[11px] text-muted-foreground">
<nav aria-label="Current folder" className="min-w-0 overflow-hidden text-(length:--fs-11) text-muted-foreground">
<ol className="flex min-w-0 items-center gap-1 overflow-hidden">
{rootLabel ? (
<li className="min-w-0 shrink">
@ -1072,7 +1072,7 @@ export function WorkspaceFileBrowser({
<div ref={scrollContainerRef} className="min-h-0 flex-1 overflow-y-auto">{body}</div>
{lazyTruncatedFolders.has(currentFolderKey) || (data?.truncated && !isLazyBrowse) ? (
<div className="border-t border-border pt-2 text-[11px] text-muted-foreground">
<div className="border-t border-border pt-2 text-(length:--fs-11) text-muted-foreground">
{isLazyBrowse ? (
<button
type="button"

View File

@ -354,7 +354,7 @@ function CommandSection({
{item.healthStatus && item.statusLabel !== "stopped" ? (
<div className="flex items-center gap-2">
<span className={cn(
"inline-flex items-center rounded-full border px-2.5 py-1 text-[11px]",
"inline-flex items-center rounded-full border px-2.5 py-1 text-(length:--fs-11)",
item.healthStatus === "healthy"
? "border-emerald-500/30 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300"
: item.healthStatus === "unhealthy"
@ -405,7 +405,7 @@ export function WorkspaceRuntimeControls({
<div className={cn("space-y-4", className)}>
<div className={cn("border border-border/70 bg-background p-3", square ? "rounded-none" : "rounded-xl")}>
<div className="space-y-1">
<div className="text-xs font-medium uppercase tracking-[0.16em] text-muted-foreground">Workspace commands</div>
<div className="text-xs font-medium uppercase tracking-(--ls-0_16) text-muted-foreground">Workspace commands</div>
<div className="flex flex-wrap items-center gap-2">
<span
className={cn(

View File

@ -17,7 +17,7 @@ export function WorktreeBanner() {
return (
<div
className="relative overflow-hidden border-b px-3 py-1.5 text-[11px] font-medium tracking-[0.2em] uppercase"
className="relative overflow-hidden border-b px-3 py-1.5 text-(length:--fs-11) font-medium tracking-(--ls-0_2) uppercase"
style={{
backgroundColor: branding.color,
color: branding.textColor,
@ -33,7 +33,7 @@ export function WorktreeBanner() {
type="button"
onClick={handleCopyName}
title="Click to copy worktree name"
className="truncate font-semibold tracking-[0.12em] cursor-pointer hover:opacity-80 transition-opacity bg-transparent border-none p-0 text-current uppercase text-[11px]"
className="truncate font-semibold tracking-(--ls-0_12) cursor-pointer hover:opacity-80 transition-opacity bg-transparent border-none p-0 text-current uppercase text-(length:--fs-11)"
>
{copied ? "Copied!" : branding.name}
</button>

View File

@ -26,7 +26,7 @@ function PlaceholderPreview({ label }: { label?: string }) {
<PreviewFrame className="flex items-center justify-center">
<div className="flex flex-col items-center gap-1.5 text-muted-foreground/50">
<Paperclip className="h-7 w-7" aria-hidden="true" />
{label ? <span className="text-[11px] font-medium uppercase tracking-wide">{label}</span> : null}
{label ? <span className="text-(length:--fs-11) font-medium uppercase tracking-wide">{label}</span> : null}
</div>
</PreviewFrame>
);
@ -223,7 +223,7 @@ export function ArtifactCard({ artifact }: ArtifactCardProps) {
</div>
</div>
<div className="mt-0.5 flex items-center gap-1.5 text-[11px] text-muted-foreground/65">
<div className="mt-0.5 flex items-center gap-1.5 text-(length:--fs-11) text-muted-foreground/65">
<span>Last edited {formatDate(artifact.updatedAt)}</span>
{artifact.createdByAgent ? (
<>

View File

@ -56,7 +56,7 @@ export function ArtifactGroupCard({ group, to }: ArtifactGroupCardProps) {
<Layers className="h-7 w-7" aria-hidden="true" />
</div>
)}
<span className="absolute right-2 top-2 inline-flex items-center gap-1 rounded-full bg-background/85 px-2 py-0.5 text-[11px] font-medium text-foreground/90 shadow-sm backdrop-blur">
<span className="absolute right-2 top-2 inline-flex items-center gap-1 rounded-full bg-background/85 px-2 py-0.5 text-(length:--fs-11) font-medium text-foreground/90 shadow-sm backdrop-blur">
<Layers className="h-3 w-3" aria-hidden="true" />
{group.count}
</span>
@ -64,7 +64,7 @@ export function ArtifactGroupCard({ group, to }: ArtifactGroupCardProps) {
<div className="flex flex-1 flex-col gap-1 p-3">
<div className="flex h-7 items-center gap-2">
<span className="shrink-0 font-mono text-[11px] text-muted-foreground">
<span className="shrink-0 font-mono text-(length:--fs-11) text-muted-foreground">
{group.issue.identifier}
</span>
<h3
@ -75,7 +75,7 @@ export function ArtifactGroupCard({ group, to }: ArtifactGroupCardProps) {
</h3>
</div>
<div className="mt-0.5 flex items-center gap-1.5 text-[11px] text-muted-foreground/65">
<div className="mt-0.5 flex items-center gap-1.5 text-(length:--fs-11) text-muted-foreground/65">
<span>{countLabel}</span>
<span className="text-muted-foreground/50">·</span>
<span>Updated {formatDate(group.updatedAt)}</span>

View File

@ -75,7 +75,7 @@ export function SecretPopoverForm({
<div className="space-y-1">
<PopoverTitle className="text-sm font-medium">{heading}</PopoverTitle>
{mode === "store" ? (
<PopoverDescription className="text-[11px] text-muted-foreground">
<PopoverDescription className="text-(length:--fs-11) text-muted-foreground">
Moves the typed value into an encrypted company secret and binds{" "}
<span className="font-mono">{initialName || "this variable"}</span> to it.
</PopoverDescription>
@ -83,7 +83,7 @@ export function SecretPopoverForm({
</div>
<label className="block space-y-1">
<span className="text-[11px] font-medium text-muted-foreground">Name</span>
<span className="text-(length:--fs-11) font-medium text-muted-foreground">Name</span>
<input
className={cn(fieldClass, nameError && "border-destructive focus-visible:ring-destructive/40")}
value={name}
@ -101,11 +101,11 @@ export function SecretPopoverForm({
}
}}
/>
{nameError ? <span className="block text-[11px] text-destructive">{nameError}</span> : null}
{nameError ? <span className="block text-(length:--fs-11) text-destructive">{nameError}</span> : null}
</label>
<label className="block space-y-1">
<span className="text-[11px] font-medium text-muted-foreground">Value</span>
<span className="text-(length:--fs-11) font-medium text-muted-foreground">Value</span>
<div className="relative">
<input
className={cn(fieldClass, "pr-8", valueError && "border-destructive focus-visible:ring-destructive/40")}
@ -127,10 +127,10 @@ export function SecretPopoverForm({
{reveal ? <EyeOff className="h-3.5 w-3.5" /> : <Eye className="h-3.5 w-3.5" />}
</button>
</div>
{valueError ? <span className="block text-[11px] text-destructive">{valueError}</span> : null}
{valueError ? <span className="block text-(length:--fs-11) text-destructive">{valueError}</span> : null}
</label>
{error ? <p className="text-[11px] text-destructive">{error}</p> : null}
{error ? <p className="text-(length:--fs-11) text-destructive">{error}</p> : null}
<div className="flex items-center justify-end gap-2 pt-0.5">
<Button type="button" variant="ghost" size="sm" onClick={onCancel} disabled={submitting}>

View File

@ -281,15 +281,15 @@ export function EnvironmentVariableRow({
<DropdownMenuContent align="start" className="w-56">
<DropdownMenuItem className="flex-col items-start gap-0.5" onSelect={() => switchSource("text")}>
<span className="text-sm">Text value</span>
<span className="text-[11px] text-muted-foreground">Store the value inline as plain text.</span>
<span className="text-(length:--fs-11) text-muted-foreground">Store the value inline as plain text.</span>
</DropdownMenuItem>
<DropdownMenuItem className="flex-col items-start gap-0.5" onSelect={() => switchSource("secret")}>
<span className="text-sm">Company secret</span>
<span className="text-[11px] text-muted-foreground">Resolve a stored company secret at run start.</span>
<span className="text-(length:--fs-11) text-muted-foreground">Resolve a stored company secret at run start.</span>
</DropdownMenuItem>
<DropdownMenuItem className="flex-col items-start gap-0.5" onSelect={() => switchSource("user_secret")}>
<span className="text-sm">User secret</span>
<span className="text-[11px] text-muted-foreground">
<span className="text-(length:--fs-11) text-muted-foreground">
Resolve the responsible user&apos;s own value at run start.
</span>
</DropdownMenuItem>
@ -321,7 +321,7 @@ export function EnvironmentVariableRow({
type="button"
onClick={openStoreAsSecret}
disabled={disabled}
className="flex items-center gap-1 px-2 text-[11px] text-amber-700 hover:bg-amber-500/10 dark:text-amber-400"
className="flex items-center gap-1 px-2 text-(length:--fs-11) text-amber-700 hover:bg-amber-500/10 dark:text-amber-400"
title="This value looks sensitive — store it as a secret"
>
<ShieldAlert className="size-3.5" />
@ -369,7 +369,7 @@ export function EnvironmentVariableRow({
}}
aria-label="Version"
className={cn(
"absolute right-8 top-1/2 z-10 -translate-y-1/2 rounded px-1.5 py-0.5 text-[10px] font-medium",
"absolute right-8 top-1/2 z-10 -translate-y-1/2 rounded px-1.5 py-0.5 text-(length:--fs-10) font-medium",
versionPinned
? "bg-amber-500/15 text-amber-700 dark:text-amber-400"
: "text-muted-foreground hover:bg-accent",
@ -392,7 +392,7 @@ export function EnvironmentVariableRow({
row.version === "latest" && "font-medium",
)}
>
latest <span className="text-[11px] text-muted-foreground">(recommended)</span>
latest <span className="text-(length:--fs-11) text-muted-foreground">(recommended)</span>
</button>
{Array.from({ length: versions }, (_, idx) => versions - idx)
.filter((v) => v > 0)
@ -522,7 +522,7 @@ export function EnvironmentVariableRow({
id={healthId}
role="status"
className={cn(
"mt-0.5 text-[11px]",
"mt-0.5 text-(length:--fs-11)",
health.level === "error" ? "text-destructive" : "text-amber-600 dark:text-amber-400",
)}
>
@ -532,7 +532,7 @@ export function EnvironmentVariableRow({
{/* 5s undo after Secret→Text */}
{undoPrev ? (
<p className="mt-0.5 inline-flex items-center gap-2 text-[11px] text-muted-foreground">
<p className="mt-0.5 inline-flex items-center gap-2 text-(length:--fs-11) text-muted-foreground">
Reverted to text {" "}
<button
type="button"
@ -552,7 +552,7 @@ export function EnvironmentVariableRow({
<p
id={nameErrorId}
className={cn(
"col-span-2 col-start-1 row-start-3 min-w-0 text-[11px] @[40rem]/env:col-span-2 @[40rem]/env:row-start-2",
"col-span-2 col-start-1 row-start-3 min-w-0 text-(length:--fs-11) @[40rem]/env:col-span-2 @[40rem]/env:row-start-2",
nameIssue.level === "error" ? "text-destructive" : "text-amber-600 dark:text-amber-400",
)}
>

View File

@ -24,7 +24,7 @@ const FOLDER_VALUE_PREFIX = "__secret_folder__:";
function statusBadge(status: SecretStatus | undefined) {
if (!status || status === "active") return null;
return (
<Badge variant="outline" className="ml-auto text-[10px] font-normal text-muted-foreground">
<Badge variant="outline" className="ml-auto text-(length:--fs-10) font-normal text-muted-foreground">
{status}
</Badge>
);
@ -292,7 +292,7 @@ export function SecretPicker({
<span className="flex min-w-0 flex-col">
<span className={cn("truncate text-sm", selected && "font-medium")}>{option.label}</span>
{option.pathHint ? (
<span className="truncate font-mono text-[11px] text-muted-foreground">{option.pathHint}</span>
<span className="truncate font-mono text-(length:--fs-11) text-muted-foreground">{option.pathHint}</span>
) : null}
</span>
</span>
@ -310,7 +310,7 @@ export function SecretPicker({
{option.label}
</span>
{option.pathHint && option.pathHint !== option.label ? (
<span className="truncate font-mono text-[11px] text-muted-foreground">{option.pathHint}</span>
<span className="truncate font-mono text-(length:--fs-11) text-muted-foreground">{option.pathHint}</span>
) : null}
</span>
{statusBadge(option.status)}

View File

@ -377,7 +377,7 @@ export const EnvironmentVariablesEditor = forwardRef<EnvironmentVariablesEditorH
<TooltipProvider>
<div ref={editorRootRef} className="@container/env space-y-2">
{attentionCount > 1 ? (
<p className="inline-flex items-center gap-1.5 text-[11px] font-medium text-amber-700 dark:text-amber-400">
<p className="inline-flex items-center gap-1.5 text-(length:--fs-11) font-medium text-amber-700 dark:text-amber-400">
<AlertCircle className="size-3.5" />
{attentionCount} bindings need attention
</p>
@ -387,8 +387,8 @@ export const EnvironmentVariablesEditor = forwardRef<EnvironmentVariablesEditorH
<>
{/* Header (desktop only) */}
<div className="hidden gap-x-1.5 @[40rem]/env:grid @[40rem]/env:grid-cols-[minmax(160px,2fr)_minmax(240px,3fr)_32px]">
<span className="text-[11px] font-medium uppercase tracking-wide text-muted-foreground">Name</span>
<span className="text-[11px] font-medium uppercase tracking-wide text-muted-foreground">Value</span>
<span className="text-(length:--fs-11) font-medium uppercase tracking-wide text-muted-foreground">Name</span>
<span className="text-(length:--fs-11) font-medium uppercase tracking-wide text-muted-foreground">Value</span>
<span />
</div>
@ -438,7 +438,7 @@ export const EnvironmentVariablesEditor = forwardRef<EnvironmentVariablesEditorH
{quickBind.length > 0 && !disabled ? (
<div className="flex flex-wrap items-center gap-1.5">
<span className="inline-flex items-center gap-1 text-[11px] text-muted-foreground/70">
<span className="inline-flex items-center gap-1 text-(length:--fs-11) text-muted-foreground/70">
<KeyRound className="size-3" />
Recently used:
</span>
@ -447,7 +447,7 @@ export const EnvironmentVariablesEditor = forwardRef<EnvironmentVariablesEditorH
key={secret.id}
type="button"
onClick={() => bindRecentSecret(secret)}
className="inline-flex items-center gap-1 rounded-full border border-border px-2 py-0.5 font-mono text-[11px] text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground"
className="inline-flex items-center gap-1 rounded-full border border-border px-2 py-0.5 font-mono text-(length:--fs-11) text-muted-foreground transition-colors hover:bg-accent/50 hover:text-foreground"
title={`Bind ${secret.name}`}
>
+ {secret.name}
@ -488,9 +488,9 @@ export const EnvironmentVariablesEditor = forwardRef<EnvironmentVariablesEditorH
</div>
) : null}
{hint ? <p className="text-[11px] text-muted-foreground/70">{hint}</p> : null}
{hint ? <p className="text-(length:--fs-11) text-muted-foreground/70">{hint}</p> : null}
{rows.some((row) => row.source === "user_secret" && row.userSecretKey) ? (
<p className="inline-flex items-start gap-1 text-[11px] text-muted-foreground/70">
<p className="inline-flex items-start gap-1 text-(length:--fs-11) text-muted-foreground/70">
<UserRound className="mt-0.5 size-3 shrink-0" />
<span>
User secrets resolve from the user responsible for the run. Required bindings fail until that user

View File

@ -65,7 +65,7 @@ function OutputMediaPreview({
)}
<div className="absolute inset-x-0 bottom-0 bg-black/65 px-2 py-1.5 text-left">
<p className="truncate text-xs font-medium text-white" title={filename}>{filename}</p>
<p className="truncate text-[10px] text-white/65">{metaBits.join(" · ")}</p>
<p className="truncate text-(length:--fs-10) text-white/65">{metaBits.join(" · ")}</p>
</div>
</>
);
@ -135,7 +135,7 @@ export function IssueOutputSection({ workProducts, resolveCreatorName, onMediaCl
{rest.length > 0 ? (
<div className="space-y-2">
<p className="text-[11px] font-medium uppercase tracking-wide text-muted-foreground">Also produced</p>
<p className="text-(length:--fs-11) font-medium uppercase tracking-wide text-muted-foreground">Also produced</p>
{mediaRest.length > 0 ? (
<div className="grid grid-cols-4 gap-2">
{mediaRest.map((item) => (

View File

@ -22,7 +22,7 @@ export function OutputFileTile({ contentType, className, sizeClassName = "h-8 w-
return (
<span
className={cn(
"flex shrink-0 items-center justify-center rounded-md text-[10px] font-semibold tabular-nums",
"flex shrink-0 items-center justify-center rounded-md text-(length:--fs-10) font-semibold tabular-nums",
sizeClassName,
TONE_CLASSES[glyph.tone],
className,

View File

@ -70,13 +70,13 @@ export function OutputPrimaryCard({ item, creatorName, onMediaClick }: OutputPri
<div className="min-w-0 flex-1">
<p className="break-words text-sm font-semibold text-foreground">{filename}</p>
{item.degraded ? (
<p className="mt-0.5 text-[11px] text-destructive">
<p className="mt-0.5 text-(length:--fs-11) text-destructive">
Output metadata is unavailable this file cant be played or downloaded here.
</p>
) : (
<div className="mt-0.5 flex flex-wrap items-center gap-x-1.5 gap-y-0.5 text-[11px] text-muted-foreground">
<div className="mt-0.5 flex flex-wrap items-center gap-x-1.5 gap-y-0.5 text-(length:--fs-11) text-muted-foreground">
{item.isPrimary && (
<Badge variant="secondary" className="px-1.5 py-0 text-[10px]">
<Badge variant="secondary" className="px-1.5 py-0 text-(length:--fs-10)">
Primary
</Badge>
)}

View File

@ -31,7 +31,7 @@ export function OutputRow({ item, creatorName }: OutputRowProps) {
</p>
<p
className={cn(
"truncate text-[11px]",
"truncate text-(length:--fs-11)",
item.degraded ? "text-destructive" : "text-muted-foreground",
)}
>

Some files were not shown because too many files have changed in this diff Show More