-
The app hit an unexpected error.
+
The app hit an unexpected error.
Restart the app or check the daemon logs if this keeps happening.
diff --git a/frontend/src/renderer/components/TerminalPane.tsx b/frontend/src/renderer/components/TerminalPane.tsx
index 79367e1a38..02fc2834d5 100644
--- a/frontend/src/renderer/components/TerminalPane.tsx
+++ b/frontend/src/renderer/components/TerminalPane.tsx
@@ -27,23 +27,23 @@ export function TerminalPane({ session, theme, daemonReady, terminalTarget, font
terminalTarget?.kind === "reviewer" ? reviewerPreviewLines(session) : workerPreviewLines(session, provider);
return (
- ~/{session?.workspaceName ?? "reverbcode"} {" "}
- {session?.branch || "main"} $ {provider}
+ ~/{session?.workspaceName ?? "reverbcode"} {" "}
+ {session?.branch || "main"} $ {provider}
{"\n"}
{lines.map((line, index) => (
{line}
@@ -198,7 +198,7 @@ function AttachedTerminal({ session, theme, daemonReady, terminalTarget, fontSiz
if (initFailed) {
return (
-
+
Terminal failed to initialize on this GPU/driver. Restart the app to retry.
);
@@ -229,17 +229,17 @@ function AttachedTerminal({ session, theme, daemonReady, terminalTarget, fontSiz
theme={theme}
/>
{showEmptyState && (
-
+
-
Agent Orchestrator
-
+
Agent Orchestrator
+
No session selected. Pick a worker to attach its terminal.
)}
{banner && (
-
+
{banner}
)}
@@ -275,18 +275,18 @@ function TerminalEndedStrip({ canRestore, error, isRestoring, onRestore, variant
return (
-
+
-
+
Terminal ended
-
{message}
+
{message}
- {error &&
{error}
}
+ {error &&
{error}
}
{canRestore && (
diff --git a/frontend/src/renderer/components/TitlebarNav.tsx b/frontend/src/renderer/components/TitlebarNav.tsx
index da9070f229..2c11a642f0 100644
--- a/frontend/src/renderer/components/TitlebarNav.tsx
+++ b/frontend/src/renderer/components/TitlebarNav.tsx
@@ -45,16 +45,16 @@ export function TitlebarNav() {
if (!isMac) return null;
return (
-
+
-
+
router.history.back()} title="Go back">
-
+
router.history.forward()}
title="Go forward"
>
-
+
);
@@ -84,7 +84,7 @@ function TitlebarButton({
return (
& VariantProps) {
+ return ;
+}
+
+export function TopbarKillError({ className, ...props }: React.HTMLAttributes) {
+ return ;
+}
+
+export const topbarHeaderClass =
+ "flex h-toolbar shrink-0 items-center gap-3 border-b border-border bg-background px-4 z-chrome";
+
+export const topbarHeaderMacClass = "pl-titlebar-content-offset";
+
+export const topbarProjectLabelClass = "text-brand font-semibold tracking-tight leading-none text-foreground whitespace-nowrap";
diff --git a/frontend/src/renderer/components/UpdatesSection.tsx b/frontend/src/renderer/components/UpdatesSection.tsx
index 3cd1e397f3..87ee64bbbb 100644
--- a/frontend/src/renderer/components/UpdatesSection.tsx
+++ b/frontend/src/renderer/components/UpdatesSection.tsx
@@ -59,22 +59,22 @@ export function UpdatesSection() {
return (
- Updates
+ Updates
-
+
Automatic updates
-
+
Update channel
setChannel(v as UpdateChannel)} disabled={!form.enabled}>
-
+
@@ -88,7 +88,7 @@ export function UpdatesSection() {
{form.channel === "nightly" && form.enabled && (
-
+
Nightly builds are cut every day and can be unstable or lose data. Only use Nightly if you are comfortable
with that.
@@ -99,11 +99,11 @@ export function UpdatesSection() {
{save.isPending ? "Saving…" : "Save changes"}
{save.isError && (
-
+
{save.error instanceof Error ? save.error.message : "Save failed"}
)}
- {savedAt && !save.isPending && !save.isError && Saved. }
+ {savedAt && !save.isPending && !save.isError && Saved. }
@@ -137,13 +137,13 @@ function UpdateActions() {
return (
-
+
Current version
- {version.data ? `v${version.data}` : "…"}
+ {version.data ? `v${version.data}` : "…"}
void aoBridge.updates.check()} disabled={busy}>
- {checking && }
+ {checking && }
Check for updates
@@ -167,23 +167,23 @@ function UpdateActions() {
function UpdateStatusLine({ status }: { status: UpdateStatus }) {
switch (status.state) {
case "checking":
- return
Checking for updates… ;
+ return
Checking for updates… ;
case "available":
return (
-
+
Update available{status.version ? ` (v${status.version})` : ""}.
);
case "downloading":
- return Downloading… {status.percent ?? 0}% ;
+ return Downloading… {status.percent ?? 0}% ;
case "downloaded":
- return Downloaded. Restart to finish updating. ;
+ return Downloaded. Restart to finish updating. ;
case "not-available":
- return You're on the latest version. ;
+ return You're on the latest version. ;
case "unsupported":
- return {status.message ?? "Updates need the installed app."} ;
+ return {status.message ?? "Updates need the installed app."} ;
case "error":
- return {status.message ?? "Update failed."} ;
+ return {status.message ?? "Update failed."} ;
default:
return null;
}
@@ -192,7 +192,7 @@ function UpdateStatusLine({ status }: { status: UpdateStatus }) {
function EnabledSelect({ id, value, onChange }: { id: string; value: boolean; onChange: (value: boolean) => void }) {
return (
onChange(v === "on")}>
-
+
diff --git a/frontend/src/renderer/components/XtermTerminal.tsx b/frontend/src/renderer/components/XtermTerminal.tsx
index 102a642b65..d64b3f8520 100644
--- a/frontend/src/renderer/components/XtermTerminal.tsx
+++ b/frontend/src/renderer/components/XtermTerminal.tsx
@@ -29,6 +29,7 @@ import { WebLinksAddon } from "@xterm/addon-web-links";
import { WebglAddon } from "@xterm/addon-webgl";
import type { AttachableTerminal, TerminalUserInputSource } from "../hooks/useTerminalSession";
import { aoBridge } from "../lib/bridge";
+import { TERMINAL_FONT_SIZE_DEFAULT } from "../lib/design-tokens";
import { buildTerminalThemes } from "../lib/terminal-themes";
import type { Theme } from "../stores/ui-store";
@@ -72,9 +73,7 @@ function loadRenderer(term: Terminal): void {
}
}
-// xterm palette tracks the app theme (see lib/terminal-themes.ts + --term-* in
-// styles.css). The PTY content is still the agent's own ANSI output.
-const terminalThemes = buildTerminalThemes();
+// xterm palette tracks the app theme (see lib/terminal-themes.ts + tokens.css).
const SUPPRESS_NATIVE_PASTE_MS = 100;
// Erase scrollback (3J) + display (2J) and home the cursor. Deliberately NOT
@@ -219,7 +218,8 @@ export function XtermTerminal(props: XtermTerminalProps) {
useEffect(() => {
const term = termRef.current;
if (!term) return;
- term.options.theme = props.theme === "dark" ? terminalThemes.dark : terminalThemes.light;
+ const { dark, light } = buildTerminalThemes();
+ term.options.theme = props.theme === "dark" ? dark : light;
}, [props.theme]);
useEffect(() => {
@@ -237,6 +237,7 @@ export function XtermTerminal(props: XtermTerminalProps) {
let term: Terminal;
try {
+ const { dark, light } = buildTerminalThemes();
term = new Terminal({
// Required for the Unicode 11 width addon below.
allowProposedApi: true,
@@ -249,7 +250,7 @@ export function XtermTerminal(props: XtermTerminalProps) {
fontFamily:
getComputedStyle(host).getPropertyValue("--font-mono").trim() ||
'ui-monospace, Menlo, Monaco, "Courier New", monospace',
- fontSize: props.fontSize ?? 12,
+ fontSize: props.fontSize ?? TERMINAL_FONT_SIZE_DEFAULT,
lineHeight: 1.35,
// Agent TUIs leave SGR bold active while using ANSI black for
// separators; keep bold weight-only so black stays black.
@@ -265,7 +266,7 @@ export function XtermTerminal(props: XtermTerminalProps) {
// stops FitAddon reserving ~14px on the right for a scrollbar that can
// never appear.
scrollback: 0,
- theme: props.theme === "dark" ? terminalThemes.dark : terminalThemes.light,
+ theme: props.theme === "dark" ? dark : light,
});
} catch (error) {
callbacksRef.current.onError?.(error);
@@ -497,7 +498,7 @@ export function XtermTerminal(props: XtermTerminalProps) {
} else if (event.deltaMode === 2 /* DOM_DELTA_PAGE */) {
lines = (Math.trunc(event.deltaY) || Math.sign(event.deltaY)) * term.rows;
} else {
- const rowHeight = (term.options.fontSize ?? 12) * (term.options.lineHeight ?? 1);
+ const rowHeight = (term.options.fontSize ?? TERMINAL_FONT_SIZE_DEFAULT) * (term.options.lineHeight ?? 1);
wheelAccumPx += event.deltaY;
lines = Math.trunc(wheelAccumPx / rowHeight);
wheelAccumPx -= lines * rowHeight;
diff --git a/frontend/src/renderer/components/ui/badge.tsx b/frontend/src/renderer/components/ui/badge.tsx
index c3c63b87ce..dabe521cd5 100644
--- a/frontend/src/renderer/components/ui/badge.tsx
+++ b/frontend/src/renderer/components/ui/badge.tsx
@@ -12,7 +12,7 @@ export function Badge({
return (
) {
- return ;
+ return ;
}
diff --git a/frontend/src/renderer/components/ui/input.tsx b/frontend/src/renderer/components/ui/input.tsx
index a94c33bfdb..0575506dff 100644
--- a/frontend/src/renderer/components/ui/input.tsx
+++ b/frontend/src/renderer/components/ui/input.tsx
@@ -5,7 +5,7 @@ export const Input = React.forwardRef (
{withHandle && (
-
+
)}
diff --git a/frontend/src/renderer/components/ui/select.tsx b/frontend/src/renderer/components/ui/select.tsx
index c274cc6429..d1fc489f31 100644
--- a/frontend/src/renderer/components/ui/select.tsx
+++ b/frontend/src/renderer/components/ui/select.tsx
@@ -29,14 +29,14 @@ function SelectTrigger({
data-slot="select-trigger"
data-size={size}
className={cn(
- "flex w-fit items-center justify-between gap-2 rounded-md border border-border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-border-strong focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
+ "flex w-fit items-center justify-between gap-2 rounded-md border border-border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-border-strong focus-visible:ring-0.75 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground data-[size=default]:h-control-board data-[size=sm]:h-control-form *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-icon-base [&_svg:not([class*='text-'])]:text-muted-foreground",
className,
)}
{...props}
>
{children}
-
+
);
@@ -54,7 +54,7 @@ function SelectContent({
-
+
{children}
@@ -122,7 +122,7 @@ function SelectScrollUpButton({ className, ...props }: React.ComponentProps
-
+
);
}
@@ -137,7 +137,7 @@ function SelectScrollDownButton({
className={cn("flex cursor-default items-center justify-center py-1", className)}
{...props}
>
-
+
);
}
diff --git a/frontend/src/renderer/components/ui/sheet.tsx b/frontend/src/renderer/components/ui/sheet.tsx
index 133c0c3f60..1d5187bb40 100644
--- a/frontend/src/renderer/components/ui/sheet.tsx
+++ b/frontend/src/renderer/components/ui/sheet.tsx
@@ -27,7 +27,7 @@ function SheetOverlay({ className, ...props }: React.ComponentProps
-
+
Close
)}
diff --git a/frontend/src/renderer/components/ui/sidebar.tsx b/frontend/src/renderer/components/ui/sidebar.tsx
index b1d0676ab7..1aa2a356eb 100644
--- a/frontend/src/renderer/components/ui/sidebar.tsx
+++ b/frontend/src/renderer/components/ui/sidebar.tsx
@@ -16,9 +16,9 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/comp
const SIDEBAR_COOKIE_NAME = "sidebar_state";
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
-const SIDEBAR_WIDTH = "16rem";
-const SIDEBAR_WIDTH_MOBILE = "18rem";
-const SIDEBAR_WIDTH_ICON = "3rem";
+const SIDEBAR_WIDTH = "var(--size-sidebar-default)";
+const SIDEBAR_WIDTH_MOBILE = "var(--size-sidebar-mobile)";
+const SIDEBAR_WIDTH_ICON = "var(--size-sidebar-icon)";
const SIDEBAR_KEYBOARD_SHORTCUT = "b";
type SidebarContextProps = {
@@ -209,7 +209,7 @@ function Sidebar({
) {
onClick={toggleSidebar}
title="Toggle Sidebar"
className={cn(
- "absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border sm:flex",
+ "absolute inset-y-0 z-titlebar hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-0.5 hover:after:bg-sidebar-border sm:flex",
"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize",
"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
"group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar",
@@ -299,7 +299,7 @@ function SidebarInput({ className, ...props }: React.ComponentProps
);
@@ -375,7 +375,7 @@ function SidebarGroupLabel({
data-slot="sidebar-group-label"
data-sidebar="group-label"
className={cn(
- "flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
+ "flex h-control-form shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-icon-base [&>svg]:shrink-0",
"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
className,
)}
@@ -396,7 +396,7 @@ function SidebarGroupAction({
data-slot="sidebar-group-action"
data-sidebar="group-action"
className={cn(
- "absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
+ "absolute top-4 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-icon-base [&>svg]:shrink-0",
// Increases the hit area of the button on mobile.
"after:absolute after:-inset-2 md:after:hidden",
"group-data-[collapsible=icon]:hidden",
@@ -441,7 +441,7 @@ function SidebarMenuItem({ className, ...props }: React.ComponentProps<"li">) {
}
const sidebarMenuButtonVariants = cva(
- "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm ring-sidebar-ring outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
+ "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm ring-sidebar-ring outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-control-form! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground [&>span:last-child]:truncate [&>svg]:size-icon-base [&>svg]:shrink-0",
{
variants: {
variant: {
@@ -450,8 +450,8 @@ const sidebarMenuButtonVariants = cva(
"bg-background shadow-[0_0_0_1px_var(--sidebar-border)] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_var(--sidebar-accent)]",
},
size: {
- default: "h-8 text-sm",
- sm: "h-7 text-xs",
+ default: "h-control-form text-sm",
+ sm: "h-control-md text-xs",
lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!",
},
},
@@ -523,7 +523,7 @@ function SidebarMenuAction({
data-slot="sidebar-menu-action"
data-sidebar="menu-action"
className={cn(
- "absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform peer-hover/menu-button:text-sidebar-accent-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
+ "absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform peer-hover/menu-button:text-sidebar-accent-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-icon-base [&>svg]:shrink-0",
// Increases the hit area of the button on mobile.
"after:absolute after:-inset-2 md:after:hidden",
"peer-data-[size=sm]/menu-button:top-1",
@@ -574,10 +574,10 @@ function SidebarMenuSkeleton({
- {showIcon && }
+ {showIcon && }
span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
+ "flex h-control-md min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground ring-sidebar-ring outline-hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-icon-base [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
"data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
size === "sm" && "text-xs",
size === "md" && "text-sm",
diff --git a/frontend/src/renderer/components/ui/table.tsx b/frontend/src/renderer/components/ui/table.tsx
index 8f53d126ee..4d3ed651d9 100644
--- a/frontend/src/renderer/components/ui/table.tsx
+++ b/frontend/src/renderer/components/ui/table.tsx
@@ -46,7 +46,7 @@ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
[role=checkbox]]:translate-y-[2px]",
+ "h-table-head px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-0.5",
className,
)}
{...props}
@@ -59,7 +59,7 @@ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
[role=checkbox]]:translate-y-[2px]",
+ "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-0.5",
className,
)}
{...props}
diff --git a/frontend/src/renderer/components/ui/tabs.tsx b/frontend/src/renderer/components/ui/tabs.tsx
index 20703b5aab..541c5d0803 100644
--- a/frontend/src/renderer/components/ui/tabs.tsx
+++ b/frontend/src/renderer/components/ui/tabs.tsx
@@ -6,7 +6,7 @@ export const Tabs = TabsPrimitive.Root;
export function TabsList({ className, ...props }: React.ComponentPropsWithoutRef) {
return (
);
diff --git a/frontend/src/renderer/components/ui/tooltip.tsx b/frontend/src/renderer/components/ui/tooltip.tsx
index 2a2b06959e..e447c0f8c1 100644
--- a/frontend/src/renderer/components/ui/tooltip.tsx
+++ b/frontend/src/renderer/components/ui/tooltip.tsx
@@ -14,7 +14,7 @@ export function TooltipContent({
open !== isSidebarOpen && toggleSidebar()}
open={isSidebarOpen}
- style={{ "--sidebar-width": "var(--ao-sidebar-w, 240px)", "--sidebar-width-icon": "48px" } as CSSProperties}
+ style={{ "--sidebar-width": "var(--ao-sidebar-w, var(--size-sidebar-default))", "--sidebar-width-icon": "var(--size-sidebar-icon)" } as CSSProperties}
>
.
*/
@theme inline {
- --font-sans:
- -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Helvetica Neue",
- sans-serif;
- /* Nerd Font stack (ported from yyork): the terminal reads --font-mono so
- * agent TUIs get powerline separators and file-type icons. These are
- * system-installed fonts — the app bundles none — and the browser picks the
- * first one present, falling back to plain monospace (no icon glyphs) if a
- * user has no Nerd Font. JetBrainsMono Nerd Font is the primary target. */
- --font-mono:
- "JetBrainsMono Nerd Font Mono", "JetBrainsMono Nerd Font", "FiraCode Nerd Font Mono", "FiraCode Nerd Font",
- "MesloLGS NF", "CaskaydiaCove Nerd Font Mono", "CaskaydiaCove Nerd Font", "Hack Nerd Font Mono", "Hack Nerd Font",
- "Symbols Nerd Font Mono", "Symbols Nerd Font", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
- "Liberation Mono", "Courier New", monospace;
+ --font-sans: var(--font-family-base);
+ --font-mono: var(--font-family-mono);
+
+ /* Typography — align Tailwind text-* with token scale */
+ --text-xs: var(--font-size-sm);
+ --text-sm: var(--font-size-md);
+ --text-base: var(--font-size-md);
+
+ /* Typography — token-named half-steps (text-control = dense 13px chrome) */
+ --text-micro: var(--font-size-xs);
+ --text-2xs: var(--font-size-2xs);
+ --text-caption: var(--font-size-caption);
+ --text-sm-md: var(--font-size-sm-md);
+ --text-md-sm: var(--font-size-md-sm);
+ --text-control: var(--font-size-base);
+ --text-brand: var(--font-size-brand);
+ --text-subtitle: var(--font-size-subtitle);
+ --text-heading-sm: var(--font-size-heading-sm);
+ --text-heading: var(--font-size-heading);
+ --text-heading-lg: var(--font-size-heading-lg);
+
+ /* Radius — align Tailwind rounded-* with token scale */
+ --radius-sm: var(--radius-sm);
+ --radius-md: var(--radius-md);
+ --radius-lg: var(--radius-lg);
+ --radius-panel: var(--radius-panel);
+ --radius-full: var(--radius-full);
+
+ /* Breakpoints — for Tailwind max-* variants */
+ --breakpoint-layout-narrow: 680px;
+ --breakpoint-inspector-compact: 300px;
+
+ /* Spacing — align Tailwind p-*, gap-*, etc. with token scale */
+ --spacing-0_5: var(--space-0_5);
+ --spacing-0_75: var(--space-0_75);
+ --spacing-1: var(--space-1);
+ --spacing-1_25: var(--space-1_25);
+ --spacing-1_5: var(--space-1_5);
+ --spacing-1_75: var(--space-1_75);
+ --spacing-2: var(--space-2);
+ --spacing-2_25: var(--space-2_25);
+ --spacing-2_5: var(--space-2_5);
+ --spacing-2_75: var(--space-2_75);
+ --spacing-3: var(--space-3);
+ --spacing-3_25: var(--space-3_25);
+ --spacing-3_5: var(--space-3_5);
+ --spacing-3_75: var(--space-3_75);
+ --spacing-4: var(--space-4);
+ --spacing-4_5: var(--space-4_5);
+ --spacing-5: var(--space-5);
+ --spacing-5_5: var(--space-5_5);
+ --spacing-6: var(--space-6);
+ --spacing-8: var(--space-8);
+ --spacing-10: var(--space-10);
+
+ /* Z-index — z-chrome, z-titlebar, z-overlay */
+ --z-index-chrome: var(--z-chrome);
+ --z-index-titlebar: var(--z-titlebar);
+ --z-index-overlay: var(--z-overlay);
+
+ /* Elevation — align Tailwind shadow-* with token scale */
+ --shadow-sm: var(--elevation-sm);
+ --shadow-md: var(--elevation-md);
+ --shadow-lg: var(--elevation-lg);
+ --shadow-xl: var(--elevation-xl);
/* Surfaces */
- --color-background: var(--bg);
- --color-foreground: var(--fg);
- --color-surface: var(--bg-1);
- --color-card: var(--bg-1);
- --color-card-foreground: var(--fg);
- --color-raised: var(--bg-2);
- --color-overlay: var(--bg-3);
- --color-popover: var(--bg-1);
- --color-popover-foreground: var(--fg);
- /* shadcn input border uses border-input; map to our hairline border */
- --color-input: var(--border);
- --color-sidebar: var(--sidebar-bg);
- --color-sidebar-foreground: var(--fg-muted);
- --color-sidebar-primary: var(--accent);
- --color-sidebar-primary-foreground: var(--accent-fg);
- --color-sidebar-accent: var(--bg-2);
- --color-sidebar-accent-foreground: var(--fg);
- --color-sidebar-border: var(--border);
- --color-sidebar-ring: var(--accent);
- --color-terminal: var(--term-bg);
+ --color-background: var(--color-bg-primary);
+ --color-foreground: var(--color-text-primary);
+ --color-surface: var(--color-bg-secondary);
+ --color-card: var(--color-bg-secondary);
+ --color-card-foreground: var(--color-text-primary);
+ --color-raised: var(--color-bg-tertiary);
+ --color-overlay: var(--color-bg-elevated);
+ --color-popover: var(--color-bg-secondary);
+ --color-popover-foreground: var(--color-text-primary);
+ --color-input: var(--bridge-border);
+ --color-sidebar: var(--color-bg-sidebar);
+ --color-sidebar-foreground: var(--color-text-muted);
+ --color-sidebar-primary: var(--bridge-accent);
+ --color-sidebar-primary-foreground: var(--bridge-accent-fg);
+ --color-sidebar-accent: var(--color-bg-tertiary);
+ --color-sidebar-accent-foreground: var(--color-text-primary);
+ --color-sidebar-border: var(--bridge-border);
+ --color-sidebar-ring: var(--bridge-accent);
+ --color-terminal: var(--color-bg-terminal);
+ --color-terminal-foreground: var(--color-text-terminal);
+ --color-terminal-dim: var(--color-text-terminal-dim);
+ --color-scrim: var(--bridge-scrim);
+
+ /* Browser static preview (light mock inside dark app) */
+ --color-preview: var(--color-preview-bg);
+ --color-preview-foreground: var(--color-preview-fg);
+ --color-preview-muted: var(--bridge-preview-muted);
+ --color-preview-link: var(--bridge-preview-link);
+ --color-preview-heading: var(--bridge-preview-heading);
+ --color-preview-body: var(--bridge-preview-body);
+ --color-preview-card: var(--bridge-preview-card);
+ --color-preview-success: var(--bridge-preview-success);
+ --color-preview-tile: var(--bridge-preview-tile);
+ --color-preview-tile-border: var(--bridge-preview-tile-border);
+ --color-preview-terminal: var(--bridge-preview-terminal);
+ --color-preview-terminal-border: var(--bridge-preview-terminal-border);
+ --color-preview-terminal-foreground: var(--bridge-preview-terminal-fg);
+
+ /* Icon chrome — size-icon-* utilities */
+ --size-icon-2xs: var(--size-icon-2xs);
+ --size-icon-xs: var(--size-icon-xs);
+ --size-icon-sm: var(--size-icon-sm);
+ --size-icon-md: var(--size-icon-md);
+ --size-icon-base: var(--size-icon-base);
+ --size-icon-lg: var(--size-icon-lg);
+ --size-icon-xl: var(--size-icon-xl);
+
+ /* Typography — tracking & leading */
+ --tracking-tight-xl: var(--tracking-tight-xl);
+ --tracking-tight-lg: var(--tracking-tight-lg);
+ --tracking-tight: var(--tracking-tight);
+ --tracking-wide-xs: var(--tracking-wide-xs);
+ --tracking-wide-sm: var(--tracking-wide-sm);
+ --tracking-wide: var(--tracking-wide);
+ --tracking-wide-md: var(--tracking-wide-md);
+ --tracking-wide-lg: var(--tracking-wide-lg);
+ --tracking-wide-xl: var(--tracking-wide-xl);
+
+ --leading-snug: var(--line-height-snug);
+ --leading-body: var(--line-height-normal);
+ --leading-row: var(--line-height-row);
+ --leading-body-md: var(--line-height-body-md);
+ --leading-relaxed: var(--line-height-relaxed);
+ --leading-loose: var(--line-height-loose);
+
+ --font-weight-medium: var(--font-weight-medium);
+ --font-weight-semibold: var(--font-weight-semibold);
+
+ --duration-fast: var(--duration-fast);
+ --duration-normal: var(--duration-normal);
+
+ /* Layout — toolbar offset for fixed sidebar below topbar */
+ --spacing-toolbar: var(--size-toolbar);
+ --spacing-titlebar-content-offset: var(--size-titlebar-content-offset);
+ --spacing-titlebar-cluster-left: var(--size-titlebar-cluster-left);
+ --spacing-control-xs: var(--size-control-xs);
+ --spacing-control-sm: var(--size-control-sm);
+ --spacing-control-form: var(--size-control-form);
+ --spacing-control-md: var(--size-control-md);
+ --spacing-control-lg: var(--size-control-lg);
+ --spacing-control-xl: var(--size-control-xl);
+ --spacing-control-board-sm: var(--size-control-board-sm);
+ --spacing-control-board: var(--size-control-board);
+ --spacing-table-head: var(--size-table-head);
+ --spacing-inspector-tabs: var(--size-inspector-tabs);
+ --spacing-browser-url: var(--size-browser-url);
+ --spacing-browser-min: var(--size-browser-min);
+ --spacing-dot-sm: var(--size-dot-sm);
+ --spacing-content-max: var(--size-content-max);
+ --spacing-board-empty: var(--size-board-empty);
+ --spacing-preview-content: var(--size-preview-content);
+ --spacing-preview-max: var(--size-preview-max);
+ --spacing-notification-width: var(--size-notification-width);
+ --spacing-notification-max-height: var(--size-notification-max-height);
+ --spacing-notification-icon: var(--size-notification-icon);
+ --spacing-font-size-label: var(--size-font-size-label);
+ --spacing-pr-table-actions: var(--size-pr-table-actions);
+ --spacing-pr-col-number: var(--size-pr-col-number);
+ --spacing-pr-col-state: var(--size-pr-col-state);
+ --spacing-inspector-min: var(--size-inspector-min);
+ --spacing-textarea-min: var(--size-textarea-min);
+ --spacing-sidebar-project-actions: var(--size-sidebar-project-actions);
+ --spacing-row-md: var(--size-row-md);
+ --spacing-empty-offset-y: var(--size-empty-offset-y);
+ --spacing-kv-label: var(--size-kv-label);
+ --spacing-branch-chip: var(--size-branch-chip);
+
+ --color-muted: var(--color-bg-tertiary);
+ --color-muted-foreground: var(--color-text-muted);
+ --color-passive: var(--color-text-passive);
+ --color-secondary: var(--color-bg-tertiary);
+ --color-secondary-foreground: var(--color-text-muted);
+
+ --color-primary: var(--bridge-accent);
+ --color-primary-foreground: var(--bridge-accent-fg);
+ --color-accent: var(--bridge-accent);
+ --color-accent-foreground: var(--bridge-accent-fg);
+ --color-accent-weak: var(--bridge-accent-weak);
+ --color-accent-dim: var(--bridge-accent-dim);
+ --color-ring: var(--bridge-accent);
+
+ --color-border: var(--bridge-border);
+ --color-border-strong: var(--bridge-border-strong);
+
+ --color-working: var(--bridge-working);
+ --color-success: var(--bridge-success);
+ --color-success-bright: var(--color-success-bright);
+ --color-warning: var(--bridge-warning);
+ --color-error: var(--bridge-danger);
+ --color-destructive: var(--bridge-danger);
+ --color-destructive-foreground: var(--color-accent-foreground);
+
+ --color-interactive-hover: var(--bridge-interactive-hover);
+ --color-interactive-active: var(--bridge-interactive-active);
- /* Text */
- --color-muted: var(--bg-2);
- --color-muted-foreground: var(--fg-muted);
- --color-passive: var(--fg-passive);
- --color-secondary: var(--bg-2);
- --color-secondary-foreground: var(--fg-muted);
+ --animate-status-pulse: status-pulse 1.8s ease-in-out infinite;
+ --animate-overlay-in: overlay-in 150ms ease-out;
+ --animate-modal-in: modal-in 150ms ease-out;
+}
- /* Accent (refined blue) — primary buttons, active session, focus */
- --color-primary: var(--accent);
- --color-primary-foreground: var(--accent-fg);
- --color-accent: var(--accent);
- --color-accent-foreground: var(--accent-fg);
- --color-accent-weak: var(--accent-weak);
- --color-accent-dim: var(--accent-dim);
- --color-ring: var(--accent);
+@utility w-dialog-md {
+ width: min(var(--size-dialog-md), calc(100vw - var(--space-8)));
+}
- /* Borders */
- --color-border: var(--border);
- --color-border-strong: var(--border-1);
+@utility w-dialog-lg {
+ width: min(var(--size-dialog-lg), calc(100vw - var(--space-8)));
+}
- /* Status — map 1:1 to the daemon's derived statuses (agent-orchestrator
- * palette): working=orange, needs-you=amber, mergeable=green, fail=red. */
- --color-working: var(--orange);
- --color-success: var(--green);
- --color-success-strong: var(--green-strong);
- --color-warning: var(--amber);
- --color-error: var(--red);
+@utility w-dialog-xl {
+ width: min(var(--size-dialog-xl), calc(100vw - var(--space-8)));
+}
- /* shadcn "destructive" → our error red (Button destructive, Alert, etc.) */
- --color-destructive: var(--red);
- --color-destructive-foreground: #ffffff;
+@utility w-dialog-orchestrator {
+ width: min(var(--size-dialog-orchestrator), calc(100vw - var(--space-8)));
+}
- /* Theme-adaptive interactive surfaces (sidebar hovers, tabs, kanban chrome) */
- --color-interactive-hover: var(--interactive-hover);
- --color-interactive-active: var(--interactive-active);
+@utility grid-cols-notification {
+ grid-template-columns: var(--size-notification-icon) minmax(0, 1fr) auto;
+}
- --radius-sm: 4px;
- --radius-md: 6px;
- --radius-lg: 8px;
- --radius-xl: 12px;
+@utility max-w-inspector-status-chip {
+ max-width: var(--size-inspector-status-chip-max);
+}
- --animate-status-pulse: status-pulse 1.8s ease-in-out infinite;
- --animate-overlay-in: overlay-in 150ms ease-out;
- --animate-modal-in: modal-in 150ms ease-out;
+@utility w-font-size-label {
+ width: var(--size-font-size-label);
+}
+
+@utility bg-purple-subtle {
+ background-color: color-mix(in srgb, var(--color-purple) 12%, transparent);
+}
+
+@utility text-purple-accent {
+ color: var(--color-purple);
+}
+
+@utility shadow-timeline-dot {
+ box-shadow: 0 0 0 3px var(--color-bg-primary);
}
-:root {
- /* Dark — cloned from the agent-orchestrator web app (packages/web). #0a0b0d
- * base, #15171b is the only bordered surface, hairline white-alpha lines,
- * blue accent, orange=working / amber=needs-you / green=mergeable / red=fail. */
- --bg: #0a0b0d;
- --bg-1: #15171b;
- --bg-2: #1b1d22;
- --bg-3: #212329;
- --fg: #f4f5f7;
- --fg-muted: #9ba1aa;
- --fg-passive: #646a73;
- --border: rgb(255 255 255 / 0.06);
- --border-1: rgb(255 255 255 / 0.1);
- --accent: #4d8dff;
- --accent-fg: #ffffff;
- --accent-weak: rgb(77 141 255 / 0.16);
- --accent-dim: #24406e;
- --orange: #f59f4c;
- --green: #74b98a;
- --green-strong: #74b98a;
- --amber: #e8c14a;
- --red: #ef6b6b;
- --purple: #a78bfa;
- /* Terminal — dark palette (light override below). */
- --term-bg: #15171b;
- --term-fg: #d7d7d2;
- --term-green: #74b98a;
- --term-dim: #7c7c7c;
- --term-blue: #4d8dff;
- --term-amber: #e8c14a;
- --shadow: 0 1px 0 rgb(0 0 0 / 0.4), 0 12px 32px rgb(0 0 0 / 0.5);
- /* Sidebar surface sits a step below --bg (cloned #08090b). */
- --sidebar-bg: #08090b;
- --interactive-hover: rgb(255 255 255 / 0.04);
- --interactive-active: rgb(255 255 255 / 0.07);
- --kanban-column-bg: rgb(255 255 255 / 0.018);
- --kanban-pending-glow: rgb(255 255 255 / 0.02);
+@utility shadow-timeline-dot-now {
+ box-shadow:
+ 0 0 0 3px var(--color-bg-primary),
+ 0 0 8px var(--color-working);
}
-:root[data-theme="light"] {
- /* Light — supported, not primary. */
- --bg: #fcfcfc;
- --bg-1: #ffffff;
- --bg-2: #ededee;
- --bg-3: #e4e4e6;
- --fg: #1a1a1a;
- --fg-muted: #666666;
- --fg-passive: #9a9a9a;
- --border: #e3e3e5;
- --border-1: #d4d4d6;
- --accent: #2563eb;
- --accent-fg: #ffffff;
- --accent-weak: rgb(37 99 235 / 0.12);
- --accent-dim: #bcd2f7;
- --sidebar-bg: var(--bg);
- --orange: #c2410c;
- --green: #1a7f37;
- --green-strong: #1a7f37;
- --amber: #9a6b00;
- --red: #c0392b;
- --purple: #7c3aed;
- --interactive-hover: rgb(0 0 0 / 0.04);
- --interactive-active: rgb(0 0 0 / 0.07);
- --kanban-column-bg: rgb(0 0 0 / 0.02);
- --kanban-pending-glow: rgb(0 0 0 / 0.03);
- --term-bg: #fafafa;
- --term-fg: #24292f;
- --term-green: #1a7f37;
- --term-dim: #6b7280;
- --term-blue: #2563eb;
- --term-amber: #9a6b00;
- --shadow: 0 1px 0 rgb(0 0 0 / 0.03), 0 12px 30px rgb(20 30 50 / 0.1);
+@utility bg-surface-faint {
+ background-color: color-mix(in srgb, var(--color-bg-primary) 35%, transparent);
}
* {
@@ -176,11 +280,11 @@ body,
body {
margin: 0;
overflow: hidden;
- background: var(--bg);
- color: var(--fg);
+ background: var(--color-bg-primary);
+ color: var(--color-text-primary);
font-family: var(--font-sans);
- font-size: 14px;
- line-height: 1.5;
+ font-size: var(--font-size-md);
+ line-height: var(--line-height-normal);
-webkit-font-smoothing: antialiased;
}
@@ -234,113 +338,15 @@ select {
}
.terminal-pane-frame:fullscreen {
- background: var(--bg);
-}
-
-.terminal-toolbar {
- display: flex;
- height: 56px;
- flex: 0 0 56px;
- align-items: center;
- border-bottom: 1px solid var(--border);
- background: var(--bg);
- padding: 0 18px;
-}
-
-.terminal-toolbar__label {
- display: flex;
- min-width: 0;
- align-items: center;
- gap: 12px;
-}
-
-.terminal-toolbar__eyebrow {
- flex: 0 0 auto;
- font-family: var(--font-mono);
- font-size: 11px;
- font-weight: 700;
- letter-spacing: 0.09em;
- color: var(--fg-muted);
-}
-
-.terminal-toolbar__session {
- min-width: 0;
- overflow: hidden;
- font-family: var(--font-mono);
- font-size: 13px;
- font-weight: 600;
- color: var(--fg-passive);
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
-.terminal-toolbar__controls {
- display: flex;
- margin-left: auto;
- align-items: center;
- gap: 12px;
- font-family: var(--font-mono);
- color: var(--fg-passive);
-}
-
-.terminal-toolbar__control {
- display: inline-flex;
- width: 24px;
- height: 24px;
- align-items: center;
- justify-content: center;
- border: 0;
- border-radius: 5px;
- background: transparent;
- color: var(--fg-passive);
- cursor: pointer;
- font-family: var(--font-mono);
- font-size: 13px;
- line-height: 1;
- transition:
- background 120ms ease,
- color 120ms ease,
- opacity 120ms ease;
-}
-
-.terminal-toolbar__control:hover {
- background: var(--interactive-hover);
- color: var(--fg);
-}
-
-.terminal-toolbar__control:focus-visible {
- outline: 2px solid color-mix(in srgb, var(--accent) 50%, transparent);
- outline-offset: 1px;
-}
-
-.terminal-toolbar__control:disabled {
- cursor: default;
- opacity: 0.35;
-}
-
-.terminal-toolbar__control:disabled:hover {
- background: transparent;
- color: var(--fg-passive);
-}
-
-.terminal-toolbar__control--icon {
- margin-left: 6px;
-}
-
-.terminal-toolbar__font-size {
- width: 42px;
- text-align: center;
- font-size: 12px;
- font-weight: 600;
- color: var(--fg-muted);
+ background: var(--color-bg-primary);
}
:root[data-theme="light"] .xterm .xterm-viewport::-webkit-scrollbar-thumb {
- background: rgb(0 0 0 / 0.12);
+ background: var(--color-scrollbar);
}
:root[data-theme="light"] .xterm .xterm-viewport:hover::-webkit-scrollbar-thumb {
- background: rgb(0 0 0 / 0.2);
+ background: var(--color-scrollbar-hover);
}
@keyframes status-pulse {
@@ -373,517 +379,21 @@ select {
}
}
-/* ── Resizable panel handles (sidebar + inspector) ──────────────────────── */
-.resize-handle {
- position: absolute;
- top: 0;
- bottom: 0;
- width: 7px;
- z-index: 5;
- cursor: col-resize;
- background: transparent;
- touch-action: none;
-}
-
-.resize-handle--right {
- right: -3px;
-}
-
-.resize-handle--left {
- left: -3px;
-}
-
-.resize-handle::after {
- content: "";
- position: absolute;
- top: 0;
- bottom: 0;
- left: 50%;
- width: 1px;
- transform: translateX(-50%);
- background: transparent;
- transition: background 0.12s ease;
-}
-
-.resize-handle:hover::after,
-body.is-resizing-x .resize-handle::after {
- background: var(--border);
-}
-
+/* ── Global resize state (sidebar drag) ─────────────────────────────────── */
body.is-resizing-x {
cursor: col-resize;
user-select: none;
}
-/* No width transition while actively dragging the sidebar resize handle
- * (shadcn's sidebar animates width for collapse/expand). */
+body.is-resizing-x [data-slot="resize-handle"]::after {
+ background: var(--color-border);
+}
+
body.is-resizing-x [data-slot="sidebar-gap"],
body.is-resizing-x [data-slot="sidebar-container"] {
transition: none;
}
-/* ── Shell topbar (agent-orchestrator .dashboard-app-header) ──────────────
- * One header for every screen (rendered by the shell layout), so one padding:
- * AO's session-topbar values. Upstream splits this into a 14px dashboard
- * header and a 16/14px session override; with the bar hoisted there is a
- * single frame and the crumb never shifts between views. The bar spans the
- * full window width with the sidebar pinned below it (approved divergence
- * 2026-06-12), so its bottom border runs edge-to-edge and the sidebar border
- * stops at the header instead of crossing the traffic-light strip. */
-.dashboard-app-header {
- display: flex;
- height: 56px;
- flex-shrink: 0;
- align-items: center;
- gap: 13px;
- padding: 0 16px 0 14px;
- border-bottom: 1px solid var(--border);
- background: var(--bg);
- z-index: 10;
-}
-
-.dashboard-app-header__project {
- font-size: 14.5px;
- font-weight: 600;
- letter-spacing: -0.01em;
- line-height: 1;
- color: var(--fg);
- white-space: nowrap;
-}
-
-.topbar-project-line {
- display: inline-flex;
- min-width: 0;
- align-items: center;
- gap: 6px;
-}
-
-.dashboard-app-header__spacer {
- flex: 1;
- min-width: 0;
-}
-
-.dashboard-app-header__actions {
- display: flex;
- flex-shrink: 0;
- align-items: center;
- gap: 6px;
-}
-
-.dashboard-app-header__icon-btn {
- display: grid;
- width: 34px;
- height: 34px;
- place-items: center;
- border-radius: 7px;
- color: var(--fg-muted);
- transition:
- background 0.12s ease,
- color 0.12s ease;
-}
-
-.dashboard-app-header__icon-btn:hover {
- background: var(--interactive-hover);
- color: var(--fg);
-}
-
-.dashboard-app-header__kill-btn {
- display: inline-flex;
- height: 30px;
- align-items: center;
- gap: 5px;
- border-radius: 6px;
- border: 1px solid color-mix(in srgb, var(--red) 58%, transparent);
- background: color-mix(in srgb, var(--red) 5%, transparent);
- padding: 0 10px;
- font-size: 12px;
- font-weight: 650;
- line-height: 1;
- color: var(--red);
- transition:
- background 0.12s ease,
- color 0.12s ease;
-}
-
-.dashboard-app-header__kill-btn:hover {
- background: color-mix(in srgb, var(--red) 12%, transparent);
- border-color: color-mix(in srgb, var(--red) 75%, transparent);
-}
-
-.dashboard-app-header__kill-confirm {
- display: inline-flex;
- align-items: center;
- gap: 6px;
-}
-
-.dashboard-app-header__kill-confirm-btn {
- display: inline-flex;
- height: 34px;
- align-items: center;
- gap: 6px;
- border-radius: 7px;
- border: 1px solid color-mix(in srgb, var(--red) 40%, transparent);
- padding: 0 12px;
- font-size: 13px;
- font-weight: 600;
- line-height: 1;
- color: var(--red);
- background: color-mix(in srgb, var(--red) 10%, transparent);
- transition: background 0.12s ease;
-}
-
-.dashboard-app-header__kill-confirm-btn:hover {
- background: color-mix(in srgb, var(--red) 16%, transparent);
-}
-
-.dashboard-app-header__kill-confirm-btn:disabled {
- opacity: 0.6;
-}
-
-.dashboard-app-header__kill-cancel-btn {
- display: inline-flex;
- height: 34px;
- align-items: center;
- border-radius: 7px;
- padding: 0 10px;
- font-size: 13px;
- font-weight: 600;
- line-height: 1;
- color: var(--fg-muted);
- transition: color 0.12s ease;
-}
-
-.dashboard-app-header__kill-cancel-btn:hover {
- color: var(--fg);
-}
-
-.dashboard-app-header__kill-error {
- font-size: 11px;
- color: var(--red);
-}
-
-.dashboard-app-header__primary-btn {
- display: inline-flex;
- height: 34px;
- align-items: center;
- gap: 6px;
- border-radius: 7px;
- padding: 0 15px;
- font-size: 13px;
- font-weight: 600;
- line-height: 1;
- background: var(--accent);
- color: var(--accent-fg);
- transition: filter 0.12s ease;
-}
-
-.dashboard-app-header__primary-btn:hover {
- filter: brightness(1.08);
-}
-
-.dashboard-app-header__primary-btn:disabled {
- opacity: 0.6;
-}
-
-.dashboard-app-header__primary-btn--compact {
- height: 32px;
- border-radius: 7px;
- padding: 0 14px;
- font-size: 13px;
-}
-
-.dashboard-app-header__accent-btn {
- display: inline-flex;
- height: 34px;
- align-items: center;
- gap: 6px;
- border-radius: 7px;
- border: 1px solid var(--border);
- padding: 0 15px;
- font-size: 13px;
- font-weight: 600;
- line-height: 1;
- background: var(--raised);
- color: var(--fg-muted);
- transition: background 0.12s ease;
-}
-
-.dashboard-app-header__accent-btn:hover {
- background: var(--surface);
- color: var(--fg);
-}
-
-.session-topbar__lead {
- display: flex;
- min-width: 0;
- align-items: center;
- gap: 13px;
-}
-
-/* ── macOS titlebar cluster (TitlebarNav) ─────────────────────────────────
- * Fixed beside the traffic lights so the toggle/history buttons occupy the
- * exact same spot in both sidebar states. The 56px strip matches the
- * .dashboard-app-header height so the buttons share the topbar's center line
- * (y 28) with the project crumb / bell; the lights match via
- * trafficLightPosition y:20 in main.ts. Lights span x=14–66; the cluster
- * starts a 13px group gap after them (the .dashboard-app-header gap), so
- * the toggle reads as its own group rather than a fourth light. */
-.titlebar-nav {
- position: fixed;
- top: 0;
- left: 79px;
- z-index: 20;
- display: flex;
- height: 56px;
- align-items: center;
- gap: 2px;
-}
-
-.titlebar-nav__btn {
- width: 28px;
- height: 28px;
-}
-
-/* macOS: the full-width header starts its content past the lights + fixed
- * cluster: cluster right edge 79 + 3×28 + 2×2 = 167px, + the header's 13px
- * group gap = 180px. */
-.dashboard-app-header.is-under-titlebar-nav {
- padding-left: 180px;
-}
-
-.topbar-project-pills-group {
- display: inline-flex;
- min-width: 0;
- align-items: center;
- gap: 8px;
-}
-
-.topbar-identity-sep {
- font-size: 12px;
- line-height: 1;
- color: var(--fg-passive);
-}
-
-.session-detail-mode-badge {
- display: inline-flex;
- height: 24px;
- align-items: center;
- gap: 4px;
- border: 1px solid var(--border);
- border-radius: 6px;
- padding: 0 8px;
- font-size: 10px;
- font-weight: 600;
- line-height: 1;
- letter-spacing: 0.05em;
-}
-
-.session-detail-mode-badge--neutral {
- background: var(--surface);
- color: var(--fg-muted);
-}
-
-.session-topbar__identity {
- display: flex;
- min-width: 0;
- align-items: center;
- gap: 11px;
-}
-
-.session-topbar__branch {
- display: inline-flex;
- min-width: 0;
- align-items: center;
- gap: 5px;
- font-family: var(--font-mono);
- font-size: 10.5px;
- line-height: 1;
- color: var(--fg-passive);
-}
-
-/* ── Session inspector rail (agent-orchestrator SessionInspector) ───────── */
-.session-inspector {
- container-type: inline-size;
- display: flex;
- height: 100%;
- min-height: 0;
- flex-direction: column;
- overflow: hidden;
- background: var(--bg);
-}
-
-.session-inspector__tabs {
- display: flex;
- align-items: center;
- gap: 3px;
- height: 47px;
- flex-shrink: 0;
- padding: 0 11px;
- border-bottom: 1px solid var(--border);
-}
-
-.session-inspector__tab {
- flex: 1;
- display: inline-flex;
- align-items: center;
- justify-content: center;
- gap: 6px;
- min-width: 0;
- padding: 7px 6px;
- border-radius: 7px;
- font-size: 11.5px;
- font-weight: 600;
- color: var(--fg-passive);
- cursor: pointer;
- transition:
- background 0.12s ease,
- color 0.12s ease;
-}
-
-.session-inspector__tab:hover {
- background: var(--interactive-hover);
- color: var(--fg);
-}
-
-.session-inspector__tab.is-active {
- background: var(--interactive-active);
- color: var(--fg);
-}
-
-.session-inspector__tab-icon {
- display: inline-flex;
- flex-shrink: 0;
-}
-
-.session-inspector__tab-icon svg {
- width: 14px;
- height: 14px;
-}
-
-.session-inspector__tab-label {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
-.session-inspector__body {
- flex: 1;
- min-height: 0;
- overflow-y: auto;
- padding: 18px 18px 40px;
-}
-
-/* Browser tab: the panel fills the rail edge-to-edge, so drop the body padding
- and the panel's own border/radius so it sits flush against the resize handle. */
-.session-inspector__body.session-inspector__body--browser {
- padding: 0;
- overflow: hidden;
-}
-
-.session-inspector__body--browser .browser-panel {
- border: 0;
- border-radius: 0;
-}
-
-/* Inspector resize handle (shadcn resizable separator, AO visual): a 7px
- * transparent grab strip whose centered 1px line lights accent on hover, drag
- * (rrp sets data-separator="active"), and keyboard focus. */
-.session-inspector__resize-handle {
- width: 7px;
- cursor: col-resize;
- background: transparent;
- touch-action: none;
-}
-
-.session-inspector__resize-handle::after {
- content: "";
- position: absolute;
- top: 0;
- bottom: 0;
- left: 50%;
- width: 1px;
- transform: translateX(-50%);
- background: var(--border-1);
- transition: background 0.12s ease;
-}
-
-.session-inspector__resize-handle:hover::after,
-.session-inspector__resize-handle:focus-visible::after,
-.session-inspector__resize-handle[data-separator="active"]::after {
- background: var(--border);
-}
-
-.reviewer-terminal-header {
- display: flex;
- height: 36px;
- flex-shrink: 0;
- align-items: center;
- gap: 12px;
- border-bottom: 1px solid var(--border);
- background: var(--term-bg);
- padding: 0 14px;
- font-family: var(--font-mono);
-}
-
-.reviewer-terminal-header__back {
- display: inline-flex;
- height: 24px;
- flex-shrink: 0;
- align-items: center;
- gap: 5px;
- border-radius: 6px;
- border: 1px solid var(--border);
- background: var(--bg-1);
- padding: 0 8px;
- font-size: 11px;
- color: var(--fg-muted);
- transition:
- background 0.12s ease,
- color 0.12s ease;
-}
-
-.reviewer-terminal-header__back:hover {
- background: var(--interactive-hover);
- color: var(--fg);
-}
-
-.reviewer-terminal-header__back svg,
-.reviewer-terminal-header__role svg {
- width: 13px;
- height: 13px;
- flex-shrink: 0;
-}
-
-.reviewer-terminal-header__role {
- display: inline-flex;
- height: 24px;
- flex-shrink: 0;
- align-items: center;
- gap: 6px;
- border-radius: 6px;
- border: 1px solid color-mix(in srgb, var(--green) 34%, transparent);
- background: color-mix(in srgb, var(--green) 9%, transparent);
- padding: 0 9px;
- font-size: 11px;
- font-weight: 700;
- color: #8bdc75;
- text-transform: uppercase;
-}
-
-:root[data-theme="light"] .reviewer-terminal-header__role {
- color: var(--green);
-}
-
-.reviewer-terminal-header__harness {
- min-width: 0;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- font-size: 13px;
- font-weight: 650;
- color: var(--fg);
-}
-
/* Collapse/expand animation for the inspector panel: rrp v4 drives panel
* sizes via flex-grow, which is animatable. Suppress it while the separator
* is actively dragged so resizing tracks the pointer 1:1. */
@@ -894,696 +404,3 @@ body.is-resizing-x [data-slot="sidebar-container"] {
.session-split:has([data-separator="active"]) #inspector[data-panel] {
transition: none;
}
-
-.inspector-section {
- margin-bottom: 22px;
-}
-
-.inspector-section--separated {
- border-top: 1px solid var(--border);
- padding-top: 18px;
-}
-
-.inspector-section__head {
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-bottom: 11px;
- font-size: 10.5px;
- font-weight: 600;
- text-transform: uppercase;
- letter-spacing: 0.09em;
- color: var(--fg-passive);
-}
-
-.inspector-section__link {
- font-size: 11px;
- font-weight: 500;
- text-transform: none;
- letter-spacing: 0;
- color: var(--accent);
-}
-
-.inspector-section__link:hover {
- text-decoration: underline;
-}
-
-.inspector-empty {
- font-size: 12px;
- color: var(--fg-muted);
- line-height: 1.5;
-}
-
-.inspector-pr-summary {
- display: flex;
- min-width: 0;
- align-items: center;
- gap: 8px;
-}
-
-.inspector-pr-summary__title {
- min-width: 0;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- font-size: 12.5px;
- font-weight: 500;
- color: var(--fg);
-}
-
-.inspector-pr-summary__state {
- margin-left: auto;
- flex-shrink: 0;
-}
-
-.reviewer-list {
- display: flex;
- flex-direction: column;
- gap: 14px;
-}
-
-.reviewer-kicker {
- display: inline-flex;
- min-width: 0;
- align-items: center;
- gap: 8px;
- font-family: var(--font-mono);
- font-size: 13px;
- font-weight: 700;
- color: var(--fg);
-}
-
-.reviewer-kicker svg {
- width: 15px;
- height: 15px;
- flex-shrink: 0;
- color: var(--fg-passive);
-}
-
-.reviewer-kicker span:first-of-type {
- min-width: 0;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
-.reviewer-kicker span:last-child {
- font-family: var(--font-sans);
- font-size: 11.5px;
- font-weight: 500;
- color: var(--fg-passive);
-}
-
-.reviewer-error {
- margin: 0;
- border-radius: 6px;
- border: 1px solid color-mix(in srgb, var(--red) 28%, transparent);
- background: color-mix(in srgb, var(--red) 8%, transparent);
- padding: 8px 10px;
- font-size: 11.5px;
- line-height: 1.45;
- color: var(--red);
-}
-
-.reviewer-notice {
- margin: 0;
- border-radius: 6px;
- border: 1px solid color-mix(in srgb, var(--green) 28%, transparent);
- background: color-mix(in srgb, var(--green) 8%, transparent);
- padding: 8px 10px;
- font-size: 11.5px;
- line-height: 1.45;
- color: var(--green);
-}
-
-.reviewer-card {
- display: flex;
- flex-direction: column;
- gap: 12px;
- border-radius: 8px;
- border: 1px solid var(--border);
- background: var(--bg-1);
- padding: 12px;
-}
-
-.reviewer-card--success {
- border-color: color-mix(in srgb, var(--green) 25%, var(--border));
-}
-
-.reviewer-card--danger {
- border-color: color-mix(in srgb, var(--red) 22%, var(--border));
-}
-
-.reviewer-card__top {
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 10px;
- min-width: 0;
-}
-
-.reviewer-card__name {
- display: inline-flex;
- min-width: 0;
- align-items: center;
- gap: 8px;
- font-family: var(--font-mono);
- font-size: 12.5px;
- font-weight: 600;
- color: var(--fg);
-}
-
-.reviewer-card__name svg {
- width: 15px;
- height: 15px;
- flex-shrink: 0;
- color: var(--fg-passive);
-}
-
-.reviewer-card__name span {
- min-width: 0;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
-.reviewer-card__identity {
- display: flex;
- min-width: 0;
- flex-direction: column;
- gap: 4px;
-}
-
-.reviewer-card__label {
- min-width: 0;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- font-size: 12px;
- font-weight: 650;
- color: var(--fg-muted);
-}
-
-.reviewer-status {
- display: inline-flex;
- height: 20px;
- max-width: 58%;
- flex-shrink: 0;
- align-items: center;
- gap: 5px;
- overflow: hidden;
- border-radius: 6px;
- padding: 0 8px;
- font-size: 10.5px;
- font-weight: 650;
- line-height: 1;
- white-space: nowrap;
- text-overflow: ellipsis;
-}
-
-.reviewer-status svg {
- width: 13px;
- height: 13px;
- flex-shrink: 0;
-}
-
-.reviewer-status--neutral {
- background: var(--bg-2);
- color: var(--fg-muted);
-}
-
-.reviewer-status--running {
- background: color-mix(in srgb, var(--orange) 12%, transparent);
- color: var(--orange);
-}
-
-.reviewer-status--success {
- background: color-mix(in srgb, var(--green) 14%, transparent);
- color: var(--green);
-}
-
-.reviewer-status--danger {
- background: color-mix(in srgb, var(--red) 14%, transparent);
- color: var(--red);
-}
-
-.reviewer-card__actions {
- display: grid;
- grid-template-columns: repeat(2, minmax(0, 1fr));
- gap: 10px;
- padding-top: 4px;
-}
-
-.reviewer-card__actions:has(.reviewer-card__action:only-child) {
- grid-template-columns: 1fr;
-}
-
-.reviewer-card__action {
- display: inline-flex;
- height: 38px;
- min-width: 0;
- align-items: center;
- justify-content: center;
- gap: 7px;
- overflow: hidden;
- border-radius: 7px;
- border: 1px solid var(--border);
- background: var(--bg-2);
- padding: 0 10px;
- font-size: 12px;
- font-weight: 650;
- color: var(--fg-muted);
- white-space: nowrap;
- text-overflow: ellipsis;
- transition:
- background 0.12s ease,
- border-color 0.12s ease,
- color 0.12s ease;
-}
-
-.reviewer-card__action svg {
- width: 14px;
- height: 14px;
- flex-shrink: 0;
-}
-
-.reviewer-card__action:hover:not(:disabled) {
- background: var(--interactive-hover);
- color: var(--fg);
-}
-
-.reviewer-card__action:disabled {
- cursor: not-allowed;
- opacity: 0.45;
-}
-
-.reviewer-card__action--primary {
- border-color: color-mix(in srgb, var(--green) 42%, transparent);
- background: color-mix(in srgb, var(--green) 10%, transparent);
- color: #8bdc75;
-}
-
-.reviewer-card__action--wide {
- width: 100%;
-}
-
-.reviewer-summary-list {
- display: flex;
- flex-direction: column;
- gap: 0;
- overflow: hidden;
- border-radius: 7px;
- border: 1px solid var(--border);
- background: color-mix(in srgb, var(--bg-0) 35%, transparent);
-}
-
-.reviewer-row {
- display: grid;
- grid-template-columns: minmax(0, 1fr) auto;
- align-items: center;
- gap: 10px;
- border-radius: 0;
- border: 0;
- border-bottom: 1px solid var(--border);
- background: transparent;
- padding: 11px 12px;
- min-height: 52px;
-}
-
-.reviewer-row:last-child {
- border-bottom: 0;
-}
-
-.reviewer-row--success {
- border-color: var(--border);
-}
-
-.reviewer-row--danger {
- border-color: var(--border);
-}
-
-.reviewer-row__main {
- display: inline-flex;
- min-width: 0;
- align-items: center;
- gap: 9px;
-}
-
-.reviewer-row__dot {
- width: 7px;
- height: 7px;
- flex-shrink: 0;
- border-radius: 999px;
- background: var(--fg-passive);
-}
-
-.reviewer-row__dot--running {
- background: var(--orange);
-}
-
-.reviewer-row__dot--success {
- background: var(--green);
-}
-
-.reviewer-row__dot--danger {
- background: var(--red);
-}
-
-.reviewer-row__copy {
- display: grid;
- grid-template-columns: auto auto;
- min-width: 0;
- align-items: baseline;
- column-gap: 6px;
- row-gap: 2px;
- font-size: 12px;
- font-weight: 650;
- color: var(--fg);
-}
-
-.reviewer-row__copy svg {
- display: none;
- width: 14px;
- height: 14px;
- flex-shrink: 0;
- color: var(--fg-passive);
-}
-
-.reviewer-row__copy a {
- grid-column: 1 / -1;
- min-width: 0;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- color: inherit;
- text-decoration: none;
-}
-
-.reviewer-row__copy a:hover {
- text-decoration: underline;
-}
-
-.reviewer-row__number {
- grid-column: 1;
- font-family: var(--font-mono);
- font-size: 11px;
- color: var(--fg-passive);
-}
-
-.reviewer-row__verdict {
- white-space: nowrap;
- font-size: 11px;
- font-weight: 650;
- color: var(--fg-muted);
-}
-
-.reviewer-row__verdict--running {
- color: var(--orange);
-}
-
-.reviewer-row__verdict--success {
- color: var(--green);
-}
-
-.reviewer-row__verdict--danger {
- color: var(--red);
-}
-
-@media (max-width: 680px) {
- .reviewer-row {
- grid-template-columns: minmax(0, 1fr) auto;
- }
-}
-
-:root[data-theme="light"] .reviewer-card__action--primary {
- color: var(--green);
-}
-
-.inspector-empty--center {
- padding: 24px 8px;
- text-align: center;
-}
-
-.inspector-kv {
- display: flex;
- flex-direction: column;
- gap: 1px;
-}
-
-.inspector-kv__row {
- display: flex;
- align-items: center;
- gap: 10px;
- padding: 6px 2px;
- font-size: 12.5px;
-}
-
-.inspector-kv__k {
- width: 74px;
- flex-shrink: 0;
- color: var(--fg-muted);
-}
-
-.inspector-kv__v {
- min-width: 0;
- color: var(--fg);
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
-.inspector-kv__v--mono {
- font-family: var(--font-mono);
- font-size: 11.5px;
-}
-
-@container (max-width: 300px) {
- .session-inspector__body {
- padding-inline: 14px;
- }
-
- .inspector-pr-summary {
- align-items: flex-start;
- flex-wrap: wrap;
- }
-
- .inspector-pr-summary__state {
- margin-left: 22px;
- }
-
- .inspector-kv__row {
- align-items: flex-start;
- flex-direction: column;
- gap: 2px;
- }
-
- .inspector-kv__k {
- width: auto;
- }
-
- .inspector-kv__v {
- width: 100%;
- }
-
- .reviewer-card {
- gap: 12px;
- padding: 12px;
- overflow: hidden;
- }
-
- .reviewer-card__top {
- align-items: flex-start;
- flex-direction: column;
- }
-
- .reviewer-status {
- max-width: 100%;
- }
-
- .reviewer-card__actions {
- grid-template-columns: 1fr;
- }
-}
-
-.inspector-timeline {
- position: relative;
- padding-left: 20px;
-}
-
-.inspector-timeline::before {
- content: "";
- position: absolute;
- left: 5px;
- top: 4px;
- bottom: 6px;
- width: 1px;
- background: var(--border);
-}
-
-.inspector-timeline__ev {
- position: relative;
- padding: 0 0 15px;
-}
-
-.inspector-timeline__ev:last-child {
- padding-bottom: 0;
-}
-
-.inspector-timeline__node {
- position: absolute;
- left: -18px;
- top: 3px;
- width: 9px;
- height: 9px;
- border-radius: 50%;
- background: var(--fg-passive);
- box-shadow: 0 0 0 3px var(--bg);
-}
-
-.inspector-timeline__ev--now .inspector-timeline__node {
- background: var(--orange);
- box-shadow:
- 0 0 0 3px var(--bg),
- 0 0 8px var(--orange);
-}
-
-.inspector-timeline__ev--good .inspector-timeline__node {
- background: var(--green);
-}
-
-.inspector-timeline__ev--warn .inspector-timeline__node {
- background: var(--amber);
-}
-
-.inspector-timeline__ev--bad .inspector-timeline__node {
- background: var(--red);
-}
-
-.inspector-timeline__et {
- font-size: 12px;
- color: var(--fg);
- line-height: 1.45;
-}
-
-.inspector-timeline__et b {
- font-weight: 600;
-}
-
-.inspector-timeline__badge {
- display: inline-flex;
- vertical-align: middle;
-}
-
-.inspector-timeline__detail {
- color: var(--fg-muted);
-}
-
-.inspector-timeline__ets {
- font-size: 10.5px;
- color: var(--fg-passive);
- font-family: var(--font-mono);
- margin-top: 2px;
-}
-
-.browser-panel {
- display: flex;
- height: 100%;
- min-height: 320px;
- flex-direction: column;
- overflow: hidden;
- border: 1px solid var(--border);
- border-radius: 8px;
- background: var(--bg);
-}
-
-/* Maximized browser overlay: a fixed layer over the whole app window (portaled
- to , so it covers the sidebar + topbar too, not just the session area).
- The panel goes edge-to-edge, so drop its border/radius. */
-.browser-popout-overlay {
- position: fixed;
- inset: 0;
- z-index: 40;
- background: var(--bg);
-}
-
-.browser-popout-overlay .browser-panel {
- border: 0;
- border-radius: 0;
-}
-
-.browser-panel__toolbar {
- display: flex;
- align-items: center;
- gap: 5px;
- flex-shrink: 0;
- min-width: 0;
- padding: 7px;
- border-bottom: 1px solid var(--border);
- background: var(--surface);
-}
-
-.browser-panel__url {
- position: relative;
- min-width: 0;
- flex: 1;
-}
-
-.browser-panel__url-icon {
- position: absolute;
- left: 9px;
- top: 50%;
- width: 14px;
- height: 14px;
- transform: translateY(-50%);
- color: var(--fg-passive);
- pointer-events: none;
-}
-
-.browser-panel__url-input {
- height: 29px;
- padding-left: 29px;
- font-family: var(--font-mono);
- font-size: 12px;
-}
-
-.browser-panel__content {
- position: relative;
- flex: 1;
- min-height: 0;
- overflow: hidden;
- background: var(--bg);
-}
-
-.browser-panel__slot {
- position: absolute;
- inset: 0;
- min-width: 1px;
- min-height: 1px;
-}
-
-.browser-panel__overlay {
- position: absolute;
- inset: 0;
- display: grid;
- place-items: center;
- padding: 20px;
- text-align: center;
- font-family: var(--font-mono);
- font-size: 12px;
- color: var(--fg-passive);
- pointer-events: none;
-}
-
-.browser-panel__error {
- position: absolute;
- left: 10px;
- right: 10px;
- bottom: 10px;
- margin: 0;
- padding: 8px 10px;
- border: 1px solid color-mix(in srgb, var(--red) 35%, transparent);
- border-radius: 7px;
- background: color-mix(in srgb, var(--red) 8%, var(--bg));
- color: var(--red);
- font-size: 12px;
-}
diff --git a/frontend/src/styles/tokens.css b/frontend/src/styles/tokens.css
new file mode 100644
index 0000000000..ee64e75751
--- /dev/null
+++ b/frontend/src/styles/tokens.css
@@ -0,0 +1,361 @@
+/*
+ * Design tokens — Agent Orchestrator frontend
+ * ============================================
+ * Source of truth for the app (Electron renderer) visual system.
+ * Extracted from the existing dark-first Cursor-like UI in
+ * src/renderer/styles.css — not a restyle.
+ *
+ * Theme switching:
+ * - Default (:root) → dark
+ * - :root[data-theme="light"] → light (renderer Zustand toggle)
+ * - :root.dark / .dark → alias for landing/docs (Fumadocs)
+ *
+ * Imported by src/renderer/styles.css. See DESIGN_TOKENS.md.
+ */
+
+:root,
+:root.dark,
+.dark {
+ /* ── Color scheme hint for native form controls / scrollbars ── */
+ color-scheme: dark;
+
+ /* ═══════════════════════════════════════════════════════════════
+ COLOR — semantic (swap these per theme; do not invent new roles
+ for one-off hex — map one-offs to the nearest existing role)
+ ═══════════════════════════════════════════════════════════════ */
+
+ /* Surfaces (near-black ramp) */
+ --color-bg-primary: #0a0b0d;
+ --color-bg-secondary: #15171b;
+ --color-bg-tertiary: #1b1d22;
+ --color-bg-elevated: #212329;
+ --color-bg-sidebar: #08090b;
+ --color-bg-terminal: #15171b;
+
+ /* Text */
+ --color-text-primary: #f4f5f7;
+ --color-text-muted: #9ba1aa;
+ --color-text-passive: #646a73;
+ --color-text-terminal: #d7d7d2;
+ --color-text-terminal-dim: #7c7c7c;
+
+ /* Borders (hairline white-alpha on dark) */
+ --color-border: rgb(255 255 255 / 0.06);
+ --color-border-strong: rgb(255 255 255 / 0.1);
+
+ /* Accent — refined blue (primary actions, focus, active session) */
+ --color-accent: #4d8dff;
+ --color-accent-foreground: #ffffff;
+ --color-accent-weak: rgb(77 141 255 / 0.16);
+ --color-accent-dim: #24406e;
+
+ /* Status — matches daemon derived statuses */
+ --color-working: #f59f4c; /* agent working */
+ --color-warning: #e8c14a; /* needs-you / amber */
+ --color-success: #74b98a; /* mergeable */
+ --color-success-bright: #8bdc75; /* reviewer role highlight (was hardcoded) */
+ --color-danger: #ef6b6b; /* fail */
+ --color-purple: #a78bfa; /* accessory / magenta lane */
+
+ /* Interactive overlays */
+ --color-interactive-hover: rgb(255 255 255 / 0.04);
+ --color-interactive-active: rgb(255 255 255 / 0.07);
+ --color-overlay-subtle: rgb(255 255 255 / 0.018);
+ --color-overlay-faint: rgb(255 255 255 / 0.02);
+ --color-scrollbar: rgb(255 255 255 / 0.12);
+ --color-scrollbar-hover: rgb(255 255 255 / 0.2);
+ --color-scrim: rgb(0 0 0 / 0.55);
+
+ /* ═══════════════════════════════════════════════════════════════
+ TYPOGRAPHY
+ ═══════════════════════════════════════════════════════════════ */
+
+ --font-family-base:
+ -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans",
+ "Helvetica Neue", sans-serif;
+ --font-family-mono:
+ "JetBrainsMono Nerd Font Mono", "JetBrainsMono Nerd Font", "FiraCode Nerd Font Mono",
+ "FiraCode Nerd Font", "MesloLGS NF", "CaskaydiaCove Nerd Font Mono", "CaskaydiaCove Nerd Font",
+ "Hack Nerd Font Mono", "Hack Nerd Font", "Symbols Nerd Font Mono", "Symbols Nerd Font",
+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+
+ /* Scale — dense UI chrome uses half-steps between base sizes */
+ --font-size-2xs: 10.5px; /* uppercase meta, board footers */
+ --font-size-xs: 10px; /* micro labels, tight pills */
+ --font-size-caption: 11px; /* badges, kanban labels */
+ --font-size-sm-md: 11.5px; /* inspector tabs, status pills */
+ --font-size-sm: 12px; /* secondary chrome / Tailwind text-xs */
+ --font-size-md-sm: 12.5px; /* kv rows, PR summaries */
+ --font-size-base: 13px; /* dense controls (board buttons) */
+ --font-size-brand: 14.5px; /* titlebar project name */
+ --font-size-md: 14px; /* body / Tailwind text-sm */
+ --font-size-subtitle: 15px; /* dialog titles, stat values */
+ --font-size-heading-sm: 17px; /* empty-state headings */
+ --font-size-heading: 21px; /* dashboard subhead */
+ --font-size-heading-lg: 22px; /* preview mock headings */
+
+ --font-weight-medium: 500;
+ --font-weight-semibold: 600;
+
+ --line-height-normal: 1.5;
+ --line-height-snug: 1.42;
+ --line-height-row: 1.25rem; /* 20px — helper rows at text-xs / text-control */
+ --line-height-body-md: 1.55;
+ --line-height-relaxed: 1.6;
+ --line-height-loose: 1.7;
+
+ /* Letter-spacing — uppercase meta, tight headings */
+ --tracking-tight-xl: -0.025em;
+ --tracking-tight-lg: -0.015em;
+ --tracking-tight: -0.01em;
+ --tracking-wide-xs: 0.04em;
+ --tracking-wide-sm: 0.05em;
+ --tracking-wide: 0.06em;
+ --tracking-wide-md: 0.08em;
+ --tracking-wide-lg: 0.09em;
+ --tracking-wide-xl: 0.12em;
+
+ /* Motion */
+ --duration-fast: 120ms;
+ --duration-normal: 150ms;
+
+ /* ═══════════════════════════════════════════════════════════════
+ SPACING — 4px base (audit: 4/6/8/10/12/14/16/18 most common)
+ Prefer even steps; map odd pixels (5/7/9/11/13/15) to nearest.
+ ═══════════════════════════════════════════════════════════════ */
+
+ --space-0_5: 2px;
+ --space-0_75: 3px;
+ --space-1: 4px;
+ --space-1_25: 5px;
+ --space-1_5: 6px;
+ --space-1_75: 7px;
+ --space-2: 8px;
+ --space-2_25: 9px;
+ --space-2_5: 10px;
+ --space-2_75: 11px;
+ --space-3: 12px;
+ --space-3_25: 13px;
+ --space-3_5: 14px;
+ --space-3_75: 15px;
+ --space-4: 16px;
+ --space-4_5: 18px;
+ --space-5: 20px;
+ --space-5_5: 22px;
+ --space-6: 24px;
+ --space-8: 32px;
+ --space-10: 40px;
+
+ /* ═══════════════════════════════════════════════════════════════
+ Z-INDEX — stacking layers
+ ═══════════════════════════════════════════════════════════════ */
+
+ --z-chrome: 10;
+ --z-titlebar: 20;
+ --z-overlay: 50;
+
+ /* ═══════════════════════════════════════════════════════════════
+ RADIUS
+ ═══════════════════════════════════════════════════════════════ */
+
+ --radius-sm: 4px; /* chips, tiny controls — absorb old 5px */
+ --radius-md: 6px; /* default controls — absorb old 7px */
+ --radius-lg: 8px; /* cards, larger buttons */
+ --radius-panel: 13px; /* kanban columns, empty-state cards */
+ --radius-full: 999px; /* pills, avatars, status dots */
+
+ /* ═══════════════════════════════════════════════════════════════
+ BREAKPOINTS — documented here; @media cannot use var()
+ ═══════════════════════════════════════════════════════════════ */
+
+ --breakpoint-layout-narrow: 680px; /* reviewer grid — @custom-media in styles.css */
+ --breakpoint-inspector-compact: 300px; /* inspector @container */
+
+ /* ═══════════════════════════════════════════════════════════════
+ LAYOUT — fixed chrome dimensions (not spacing scale)
+ ═══════════════════════════════════════════════════════════════ */
+
+ --size-hairline: 1px;
+ --size-icon-2xs: 12px;
+ --size-icon-xs: 9px;
+ --size-icon-sm: 13px;
+ --size-icon-md: 14px;
+ --size-icon-base: 16px;
+ --size-icon-lg: 15px;
+ --size-icon-xl: 18px;
+ --size-dot-sm: 7px;
+ --size-control-form: 32px;
+ --size-control-xs: 20px;
+ --size-control-sm: 24px;
+ --size-control-md: 28px;
+ --size-control-lg: 34px;
+ --size-control-xl: 38px;
+ --size-control-board-sm: 30px;
+ --size-control-board: 36px;
+ --size-table-head: var(--space-10);
+ --size-toolbar: 56px;
+ --size-inspector-tabs: 47px;
+ --size-row-md: 52px;
+ --size-browser-url: 29px;
+ --size-browser-min: 320px;
+ --size-sidebar-icon: 48px;
+ --size-sidebar-default: 240px;
+ --size-sidebar-mobile: 288px;
+ --size-titlebar-cluster-left: 79px;
+ --size-titlebar-content-offset: 180px;
+ --size-resize-handle: 7px;
+ --size-resize-handle-offset: 3px;
+ --size-kanban-glow: 130px;
+ --size-kv-label: 74px;
+ --size-notification-width: 380px;
+ --size-notification-max-height: 420px;
+ --size-notification-icon: 26px;
+ --size-font-size-label: 44px;
+ --size-inspector-status-chip-max: 58%;
+ --size-board-empty: 460px;
+ --size-preview-max: 760px;
+ --size-preview-content: 400px;
+ --size-pr-table-actions: 220px;
+ --size-pr-col-number: 64px;
+ --size-pr-col-state: 96px;
+ --size-content-max: 320px;
+ --size-dialog-md: 420px;
+ --size-dialog-lg: 440px;
+ --size-dialog-orchestrator: 460px;
+ --size-dialog-xl: 560px;
+ --size-branch-chip: 13rem;
+ --size-inspector-min: 280px;
+ --size-textarea-min: 112px;
+ --size-sidebar-project-actions: 84px;
+
+ --size-empty-offset-y: 5vh; /* board empty-state vertical nudge */
+
+ /* Browser static preview (light mock page inside dark app) */
+ --color-preview-bg: #f7f8fb;
+ --color-preview-fg: #17202a;
+ --color-preview-border: #dfe4ea;
+ --color-preview-muted: #687384;
+ --color-preview-link: #2f5b9d;
+ --color-preview-card-border: #d7dee8;
+ --color-preview-heading: #111827;
+ --color-preview-body: #526070;
+ --color-preview-success-bg: #e7f8ed;
+ --color-preview-tile-border: #e1e7ef;
+ --color-preview-tile-bg: #fbfcfe;
+ --color-preview-terminal-border: #dce4ef;
+ --color-preview-terminal-bg: #0f172a;
+ --color-preview-terminal-fg: #cbd5e1;
+
+ /* Mock project accent swatches (sidebar dots) */
+ --color-project-accent-mint: #6ee7b7;
+ --color-project-accent-sky: #93c5fd;
+
+ /* xterm extended palette (ANSI bright + selection) */
+ --color-term-cyan: #6fb3c9;
+ --color-term-selection-dark: rgb(77 141 255 / 0.3);
+ --color-term-selection-light: rgb(37 99 235 / 0.25);
+ --color-term-selection-inactive: rgb(128 128 128 / 0.2);
+ --color-term-selection-inactive-light: rgb(128 128 128 / 0.15);
+ --color-term-bright-red: #ff8a8a;
+ --color-term-bright-green: #8fd6a6;
+ --color-term-bright-yellow: #f0d06b;
+ --color-term-bright-blue: #7eaaff;
+ --color-term-bright-magenta: #c4b0fc;
+ --color-term-bright-cyan: #8fcfe0;
+ --color-term-red-light: #b42318;
+ --color-term-magenta-light: #8e24aa;
+ --color-term-cyan-light: #0b7285;
+ --color-term-white-light: #4b5563;
+ --color-term-bright-black-light: #374151;
+ --color-term-bright-red-light: #912018;
+ --color-term-bright-green-light: #176639;
+ --color-term-bright-yellow-light: #6f4a00;
+ --color-term-bright-blue-light: #1d4ed8;
+ --color-term-bright-magenta-light: #7b1fa2;
+ --color-term-bright-cyan-light: #155e75;
+
+ /* ═══════════════════════════════════════════════════════════════
+ SHADOWS
+ ═══════════════════════════════════════════════════════════════ */
+
+ --elevation-sm: 0 1px 0 rgb(0 0 0 / 0.35);
+ --elevation-md: 0 1px 0 rgb(0 0 0 / 0.4), 0 12px 32px rgb(0 0 0 / 0.5);
+ --elevation-lg: 0 8px 40px rgb(0 0 0 / 0.55);
+ --elevation-xl: 0 1px 0 rgb(0 0 0 / 0.4), 0 20px 50px rgb(0 0 0 / 0.55);
+
+ /* @theme bridge — avoids Tailwind theme key / :root name collisions */
+ --bridge-border: var(--color-border);
+ --bridge-border-strong: var(--color-border-strong);
+ --bridge-accent: var(--color-accent);
+ --bridge-accent-fg: var(--color-accent-foreground);
+ --bridge-accent-weak: var(--color-accent-weak);
+ --bridge-accent-dim: var(--color-accent-dim);
+ --bridge-working: var(--color-working);
+ --bridge-success: var(--color-success);
+ --bridge-warning: var(--color-warning);
+ --bridge-danger: var(--color-danger);
+ --bridge-interactive-hover: var(--color-interactive-hover);
+ --bridge-interactive-active: var(--color-interactive-active);
+ --bridge-scrim: var(--color-scrim);
+ --bridge-preview-muted: var(--color-preview-muted);
+ --bridge-preview-link: var(--color-preview-link);
+ --bridge-preview-heading: var(--color-preview-heading);
+ --bridge-preview-body: var(--color-preview-body);
+ --bridge-preview-card: var(--color-preview-card-border);
+ --bridge-preview-success: var(--color-preview-success-bg);
+ --bridge-preview-tile: var(--color-preview-tile-bg);
+ --bridge-preview-tile-border: var(--color-preview-tile-border);
+ --bridge-preview-terminal: var(--color-preview-terminal-bg);
+ --bridge-preview-terminal-border: var(--color-preview-terminal-border);
+ --bridge-preview-terminal-fg: var(--color-preview-terminal-fg);
+
+ --font-sans: var(--font-family-base);
+ --font-mono: var(--font-family-mono);
+}
+
+/* Light theme — set via data-theme (index.html boot script + Zustand toggle). */
+
+:root[data-theme="light"] {
+ color-scheme: light;
+
+ --color-bg-primary: #fcfcfc;
+ --color-bg-secondary: #ffffff;
+ --color-bg-tertiary: #ededee;
+ --color-bg-elevated: #e4e4e6;
+ --color-bg-sidebar: #fcfcfc;
+ --color-bg-terminal: #fafafa;
+
+ --color-text-primary: #1a1a1a;
+ --color-text-muted: #666666;
+ --color-text-passive: #9a9a9a;
+ --color-text-terminal: #24292f;
+ --color-text-terminal-dim: #6b7280;
+
+ --color-border: #e3e3e5;
+ --color-border-strong: #d4d4d6;
+
+ --color-accent: #2563eb;
+ --color-accent-foreground: #ffffff;
+ --color-accent-weak: rgb(37 99 235 / 0.12);
+ --color-accent-dim: #bcd2f7;
+
+ --color-working: #c2410c;
+ --color-warning: #9a6b00;
+ --color-success: #1a7f37;
+ --color-success-bright: #176639;
+ --color-danger: #c0392b;
+ --color-purple: #7c3aed;
+
+ --color-interactive-hover: rgb(0 0 0 / 0.04);
+ --color-interactive-active: rgb(0 0 0 / 0.07);
+ --color-overlay-subtle: rgb(0 0 0 / 0.02);
+ --color-overlay-faint: rgb(0 0 0 / 0.03);
+ --color-scrollbar: rgb(0 0 0 / 0.12);
+ --color-scrollbar-hover: rgb(0 0 0 / 0.2);
+ --color-scrim: rgb(0 0 0 / 0.45);
+
+ --elevation-sm: 0 1px 0 rgb(0 0 0 / 0.06);
+ --elevation-md: 0 1px 0 rgb(0 0 0 / 0.03), 0 12px 30px rgb(20 30 50 / 0.1);
+ --elevation-lg: 0 16px 48px rgb(20 30 50 / 0.16);
+ --elevation-xl: 0 1px 0 rgb(0 0 0 / 0.03), 0 20px 50px rgb(20 30 50 / 0.14);
+}
From e8558f8a733fc49bf99cec36b0f2f0ce7233761b Mon Sep 17 00:00:00 2001
From: Just_Anniee <145839789+Annieeeee11@users.noreply.github.com>
Date: Thu, 9 Jul 2026 02:45:34 +0530
Subject: [PATCH 02/11] fix: fixed the ResizeHandle import in Sidebar.tsx
---
frontend/src/renderer/components/Sidebar.tsx | 1 +
1 file changed, 1 insertion(+)
diff --git a/frontend/src/renderer/components/Sidebar.tsx b/frontend/src/renderer/components/Sidebar.tsx
index 07c5d3ecc6..4904b15322 100644
--- a/frontend/src/renderer/components/Sidebar.tsx
+++ b/frontend/src/renderer/components/Sidebar.tsx
@@ -66,6 +66,7 @@ import aoLogo from "../assets/ao-logo.png";
import { cn } from "../lib/utils";
import { useUiStore } from "../stores/ui-store";
import { CreateProjectAgentSheet, type CreateProjectAgentSelection } from "./CreateProjectAgentSheet";
+import { ResizeHandle } from "./ResizeHandle";
import { Button } from "./ui/button";
import { ResizeHandle } from "./ResizeHandle";
From 458d8a1db368985c2c338b744da03dee8fd858ad Mon Sep 17 00:00:00 2001
From: codebanditssss