Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
@import "tailwindcss";
@source "../";
@custom-variant dark (&:is(.dark *));
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
--color-sidebar-ring: var(--sidebar-ring);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar: var(--sidebar);
--color-chart-5: var(--chart-5);
--color-chart-4: var(--chart-4);
--color-chart-3: var(--chart-3);
--color-chart-2: var(--chart-2);
--color-chart-1: var(--chart-1);
--color-ring: var(--ring);
--color-input: var(--input);
--color-border: var(--border);
--color-destructive: var(--destructive);
--color-accent-foreground: var(--accent-foreground);
--color-accent: var(--accent);
--color-muted-foreground: var(--muted-foreground);
--color-muted: var(--muted);
--color-secondary-foreground: var(--secondary-foreground);
--color-secondary: var(--secondary);
--color-primary-foreground: var(--primary-foreground);
--color-primary: var(--primary);
--color-popover-foreground: var(--popover-foreground);
--color-popover: var(--popover);
--color-card-foreground: var(--card-foreground);
--color-card: var(--card);
/*
* The radius scale is 3 / 4 / 6 / 9 / 999 (DESIGN.md section 13). shadcn derives
* rounded-sm/md/lg/xl from one `--radius: 0.625rem`, which produced 6/8/10/14px:
* every primitive and every legacy component was a step or two off the product's
* scale, so an 8px control sitting on a 9px plate read as a different system.
* Pinning the derived steps here fixes all of them at the root.
*/
--radius-sm: 3px;
--radius-md: 4px;
--radius-lg: 6px;
--radius-xl: 9px;
--radius-2xl: 9px;
--radius-3xl: 9px;
}
/* ─── Light Theme Variables ──────────────────────────────────── */
:root {
/* ── Shell tokens (DESIGN.md section 11) ────────────────────────────────────
The floating shell must render in both themes. Everything the module system
uses resolves here so no screen invents a colour (section 22). */
/* the workspace field: one gradient per theme, never a hardcoded dark one */
--shell-canvas-grad: radial-gradient(ellipse 70% 62% at 50% 46%, #FBFAF7 0%, #F5F2ED 46%, #F0EDE6 78%, #EAE6DE 100%);
--shell-grid: rgba(13, 13, 14, 0.045);
--shell-tick: rgba(13, 13, 14, 0.22);
--shell-scrim: rgba(28, 24, 20, 0.35);
--shell-cube-border: rgba(13, 13, 14, 0.18);
--shell-cube-face-a: rgba(255, 255, 255, 0.97);
--shell-cube-face-b: rgba(246, 243, 238, 0.97);
--shell-cube-face-c: rgba(236, 231, 223, 0.97);
--shell-cube-shadow: inset 0 0 16px rgba(0, 0, 0, 0.06), inset 0 1px 0 rgba(255, 255, 255, 0.90);
/* Machined material for the 正在生成 part (DESIGN.md section 17). Same grey the
viewport uses for the part, so the loader and the result read as one material. */
--shell-part-face: #9AA5B1;
--shell-part-edge: #7C8794;
--shell-part-shadow: rgba(28, 24, 20, 0.20);
--shell-canvas: #F4F2EE;
/* The field the part sits on: one step deeper than the canvas, from the token map
(DESIGN.md colors.canvas-deep-dark) rather than the old cool #F4F6F8. */
--shell-canvas-deep: #EDE9E1;
/* Solid equivalents of the field grid (base + 5.5% ink / + 11%), because the WebGL
grid helper takes flat colours and cannot read an rgba token. */
--shell-field-grid: #E0DCD5;
--shell-field-grid-strong: #D5D2CB;
/* Scrollbars are a browser surface the shell owns (DESIGN.md section 22). */
--shell-scroll-thumb: #C7C0B4;
--shell-scroll-thumb-hover: #AAA294;
--shell-module: rgba(255, 255, 255, 0.92);
--shell-module-solid: #FFFFFF;
--shell-inner: #EDF1F5;
--shell-raise: #E4E1DA;
--shell-well: rgba(13, 13, 14, 0.045);
--shell-hover: rgba(13, 13, 14, 0.05);
--shell-border: rgba(13, 13, 14, 0.10);
--shell-border-strong: rgba(13, 13, 14, 0.20);
--shell-hairline: rgba(13, 13, 14, 0.06);
--shell-text: #1B1917;
--shell-text-muted: #5C564D;
/* Light theme ladder. DESIGN.md section 21 requires sufficient contrast "including
the 9px engraved labels and dim values", so every step clears 4.5:1 against the
module plate and the canvas: label 5.2:1, dim and placeholder 4.6:1. The previous
label/dim pair measured 4.24:1 and 3.11:1 and failed its own rule. */
--shell-text-label: #6B6459;
--shell-text-dim: #7C7468;
--shell-placeholder: #7C7468;
--shell-signal: #E0512A;
--shell-signal-soft: #B8471F;
--shell-ok: #2E9E5B;
--shell-warn: #B5821A;
--shell-fail: #C0392B;
--shell-shadow: 0 14px 30px -10px rgba(28, 24, 20, 0.16), 0 3px 8px rgba(28, 24, 20, 0.08);
--shell-shadow-lift: 0 22px 46px -12px rgba(28, 24, 20, 0.22), 0 0 0 1px rgba(224, 81, 42, 0.40);
--radius: 0.625rem;
/*
* shadcn's base tokens are the third alias layer (after --shell-* and --cad-*).
* Every primitive - Dialog, Sheet, Button, Input, Select, Tabs, Switch, Tooltip,
* DropdownMenu, Command, the toaster - reads its surface, text and border from
* here. Left on the stock oklch greys they render cool against a warm shell, and
* any child that does not set its own colour inherits a near-white that is not in
* the palette. They now resolve to the shell, in both themes (DESIGN.md section 22).
*/
--background: var(--shell-module-solid);
--foreground: var(--shell-text);
--card: var(--shell-module-solid);
--card-foreground: var(--shell-text);
--popover: var(--shell-module-solid);
--popover-foreground: var(--shell-text);
--primary: var(--shell-signal);
--primary-foreground: #1A0F08;
--secondary: var(--shell-well);
--secondary-foreground: var(--shell-text);
--muted: var(--shell-well);
--muted-foreground: var(--shell-text-label);
--accent: color-mix(in srgb, var(--shell-signal) 12%, transparent);
--accent-foreground: var(--shell-signal-soft);
--destructive: var(--shell-fail);
--border: var(--shell-border);
--input: var(--shell-border);
--ring: #E0512A;
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
/* AgentSCAD custom - Light (Direction 2: Shapr3D x VisionOS Precision Metrology) */
--app-bg: #F4F6F8;
--app-surface: #FFFFFF;
--app-surface-raised: #EDF1F5;
--app-surface-50: rgba(244, 246, 248, 0.5);
--app-surface-hover: rgba(17, 24, 32, 0.04);
--app-surface-95: rgba(244, 246, 248, 0.95);
--app-border: #D5DDE6;
--app-border-subtle: rgba(213, 221, 230, 0.6);
--app-border-strong: #B8C5D3;
--app-text-primary: #111820;
--app-text-secondary: #3B4B5B;
--app-text-muted: #607080;
--app-text-dim: #8FA0B2;
--app-text-bright: #05080C;
--app-scrollbar-thumb: #B8C5D3;
--app-scrollbar-thumb-hover: #8FA0B2;
--app-scrollbar-track: transparent;
--app-focus-ring: rgba(224, 81, 42, 0.45);
--app-interactive-hover: rgba(217, 119, 6, 0.08);
--app-shadow-sm: 0 1px 2px rgba(17, 24, 32, 0.04);
--app-shadow-md: 0 4px 12px rgba(17, 24, 32, 0.06);
--app-keyboard-bg: #EDF1F5;
--app-keyboard-border: #D5DDE6;
--app-keyboard-text: #607080;
--app-skeleton-bg: rgba(17, 24, 32, 0.06);
--app-notification-hover: rgba(17, 24, 32, 0.04);
--app-footer-separator: rgba(17, 24, 32, 0.10);
--app-footer-tooltip-bg: #FFFFFF;
--app-footer-tooltip-border: #D5DDE6;
--app-footer-tooltip-text: #3B4B5B;
--app-gradient-separator: linear-gradient(90deg, transparent, #D5DDE6, transparent);
--app-card-hover-shadow: 0 2px 8px rgba(17, 24, 32, 0.05), 0 0 0 1px #D5DDE6;
--app-pipeline-bg: rgba(17, 24, 32, 0.04);
--app-activity-hover: rgba(17, 24, 32, 0.03);
--app-selected-bg: rgba(217, 119, 6, 0.08);
--app-code-copy-hover: rgba(17, 24, 32, 0.06);
--app-empty-bg: rgba(17, 24, 32, 0.03);
--app-accent: #D97706;
--app-accent-hover: #B45309;
--app-accent-bg: rgba(217, 119, 6, 0.08);
--app-accent-border: rgba(217, 119, 6, 0.25);
--app-accent-text: #B45309;
--app-accent-text-secondary: rgba(180, 83, 9, 0.85);
--app-danger: #E25B5B;
--app-danger-bg: rgba(226, 91, 91, 0.08);
--app-warning: #D97706;
--app-warning-bg: rgba(217, 119, 6, 0.08);
--app-success: #10B981;
--app-success-bg: rgba(16, 185, 129, 0.08);
--app-info: #D97706;
--app-info-bg: rgba(217, 119, 6, 0.08);
/* Dual-Theme Status Semantics (WCAG AA >= 4.5:1 compliant in light mode) */
--app-status-success-text: #059669;
--app-status-success-bg: rgba(16, 185, 129, 0.12);
--app-status-success-border: rgba(16, 185, 129, 0.28);
--app-status-warning-text: #B45309;
--app-status-warning-bg: rgba(217, 119, 6, 0.12);
--app-status-warning-border: rgba(217, 119, 6, 0.28);
--app-status-danger-text: #C73838;
--app-status-danger-bg: rgba(226, 91, 91, 0.12);
--app-status-danger-border: rgba(226, 91, 91, 0.28);
--app-status-info-text: #B45309;
--app-status-info-bg: rgba(217, 119, 6, 0.10);
--app-status-info-border: rgba(217, 119, 6, 0.25);
--app-header-bg: rgba(244, 246, 248, 0.92);
--app-dialog-overlay: rgba(17, 24, 32, 0.35);
--app-dialog-bg: #FFFFFF;
--app-code-bg: #EDF1F5;
--app-code-border: #D5DDE6;
--app-tag-bg: rgba(17, 24, 32, 0.05);
--app-tag-border: #D5DDE6;
--app-batch-bar-bg: rgba(217, 119, 6, 0.08);
--app-batch-bar-text: #B45309;
--app-input-bg: #FFFFFF;
--app-input-border: #D5DDE6;
--app-input-focus-border: rgba(217, 119, 6, 0.45);
--app-hover-subtle: rgba(17, 24, 32, 0.04);
--app-border-separator: #D5DDE6;
--app-state-neutral-bg: rgba(96, 112, 128, 0.12);
--app-state-neutral-text: #607080;
--app-state-neutral-dot: #8FA0B2;
--app-state-neutral-border: rgba(96, 112, 128, 0.2);
/*
* The `--cad-*` layer is an ALIAS, not a second palette (DESIGN.md section 22, token
* ownership). Every legacy panel still names these tokens - the provider form, the
* theme panel, the SCAD editor, the stats and compare surfaces, the activity feed -
* and while they held the old cool blue-grey family those panels could never match
* the shell no matter how they were styled. Re-pointing the layer converts all of
* them at once: values now resolve to the shell tokens, in both themes.
*
* DESIGN.md section 11: one expressive accent (signal), no separate measurement
* hue - dimensional values carry meaning through mono type and units.
*/
--cad-bg: var(--shell-module-solid);
--cad-background: var(--shell-module-solid);
--cad-surface: var(--shell-well);
--cad-surface-raised: var(--shell-inner);
--cad-surface-muted: var(--shell-well);
--cad-border: var(--shell-border);
--cad-border-subtle: var(--shell-hairline);
--cad-border-strong: var(--shell-border-strong);
--cad-text: var(--shell-text);
--cad-text-primary: var(--shell-text);
--cad-text-secondary: var(--shell-text-muted);
--cad-text-muted: var(--shell-text-label);
--cad-text-dim: var(--shell-text-dim);
--cad-accent: var(--shell-signal);
--cad-accent-hover: var(--shell-signal);
--cad-accent-soft: color-mix(in srgb, var(--shell-signal) 10%, transparent);
--cad-accent-border: color-mix(in srgb, var(--shell-signal) 35%, transparent);
--cad-accent-bg: color-mix(in srgb, var(--shell-signal) 12%, transparent);
--cad-accent-text: var(--shell-signal-soft);
--cad-grid: var(--shell-grid);
--cad-measure: var(--shell-text);
--cad-success: var(--shell-ok);
--cad-warning: var(--shell-warn);
--cad-danger: var(--shell-fail);
--cad-input-bg: var(--shell-module-solid);
}
/* ─── Dark Theme Variables (Direction 2: Shapr3D x VisionOS Spatial Canvas) ─── */
.dark {
/* the workspace field: one gradient per theme, never a hardcoded dark one */
--shell-canvas-grad: radial-gradient(ellipse 70% 62% at 50% 46%, #322E29 0%, #242220 46%, #1A1917 78%, #141312 100%);
--shell-grid: rgba(255, 255, 255, 0.032);
--shell-tick: rgba(255, 255, 255, 0.22);
--shell-scrim: rgba(10, 9, 8, 0.62);
--shell-cube-border: rgba(255, 255, 255, 0.16);
--shell-cube-face-a: rgba(84, 78, 68, 0.95);
--shell-cube-face-b: rgba(72, 66, 57, 0.95);
--shell-cube-face-c: rgba(58, 54, 47, 0.95);
--shell-cube-shadow: inset 0 0 20px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.10);
/* Machined material for the 正在生成 part (DESIGN.md section 17). */
--shell-part-face: #9BA6B2;
--shell-part-edge: #5F6874;
/* A contact shadow, not a stain: on the dark canvas the vignette already grounds
the part, so this only needs to be a hint of weight. */
--shell-part-shadow: rgba(0, 0, 0, 0.34);
--shell-canvas: #141312;
/* Field tokens: same two steps as the light theme, warm not cool. */
--shell-canvas-deep: #0E0D0C;
--shell-field-grid: #191817;
--shell-field-grid-strong: #242322;
--shell-scroll-thumb: #3A362F;
--shell-scroll-thumb-hover: #565049;
--shell-module: rgba(34, 31, 28, 0.90);
--shell-module-solid: #26231F;
--shell-inner: #211F1C;
--shell-raise: #3A3631;
--shell-well: rgba(0, 0, 0, 0.28);
--shell-hover: rgba(255, 255, 255, 0.06);
--shell-border: rgba(255, 255, 255, 0.075);
--shell-border-strong: rgba(255, 255, 255, 0.17);
--shell-hairline: rgba(255, 255, 255, 0.045);
--shell-text: #EDE8E0;
--shell-text-muted: #BEB6AC;
/* Dark theme ladder, same rule: label 6.0:1, dim and placeholder 4.6:1 on the plate.
The previous pair measured 4.94:1 and 2.95:1; the dim step failed. */
--shell-text-label: #A79E92;
--shell-text-dim: #92897E;
--shell-placeholder: #92897E;
--shell-signal: #FF5A1F;
--shell-signal-soft: #FFB597;
--shell-ok: #7BD68A;
--shell-warn: #E8B84B;
--shell-fail: #E8583F;
--shell-shadow: 0 14px 30px -10px rgba(0, 0, 0, 0.62), 0 3px 8px rgba(0, 0, 0, 0.34);
--shell-shadow-lift: 0 22px 46px -12px rgba(0, 0, 0, 0.70), 0 0 0 1px rgba(255, 90, 31, 0.40);
/* Same alias layer as the light theme (see the comment there). */
--background: var(--shell-module-solid);
--foreground: var(--shell-text);
--card: var(--shell-module-solid);
--card-foreground: var(--shell-text);
--popover: var(--shell-module-solid);
--popover-foreground: var(--shell-text);
--primary: var(--shell-signal);
--primary-foreground: #1A0F08;
--secondary: var(--shell-well);
--secondary-foreground: var(--shell-text);
--muted: var(--shell-well);
--muted-foreground: var(--shell-text-label);
--accent: color-mix(in srgb, var(--shell-signal) 14%, transparent);
--accent-foreground: var(--shell-signal-soft);
--destructive: var(--shell-fail);
--border: var(--shell-border);
--input: var(--shell-border);
--ring: #FF5A1F;
--chart-1: oklch(0.769 0.188 70.08);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.488 0.243 264.376);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: var(--shell-module-solid);
--sidebar-foreground: var(--shell-text);
--sidebar-primary: var(--shell-signal);
--sidebar-primary-foreground: #1A0F08;
--sidebar-accent: var(--shell-well);
--sidebar-accent-foreground: #F8FAFC;
--sidebar-border: rgba(255, 255, 255, 0.09);
--sidebar-ring: #F59E0B;
/* Direction C2 — Floating Instrument Panel Design System Tokens (DESIGN.md section 11) */
--canvas-dark: #141312;
--canvas-deep-dark: #0E0D0C;
--module-dark: rgba(34, 31, 28, 0.90);
--module-solid-dark: #26231F;
--inner-dark: #211F1C;
--border-dark: rgba(255, 255, 255, 0.075);
--border-strong-dark: rgba(255, 255, 255, 0.17);
--foreground-dark: #EDE8E0;
--foreground-muted-dark: #BEB6AC;
--foreground-label-dark: #948C82;
--foreground-dim-dark: #6E6760;
--signal: #FF5A1F;
--signal-soft: #FFB597;
--pass: #7BD68A;
--warn: #E8B84B;
--fail: #E8583F;
--model-face: #9BA6B2;
--model-face-shaded: #77828E;
--mod: rgba(34, 31, 28, 0.90);
--mod-solid: #26231F;
--hair: rgba(255, 255, 255, 0.075);
--hair-2: rgba(255, 255, 255, 0.045);
--dim: #6E6760;
--label: #948C82;
--lift: inset 0 1px 0 rgba(255, 255, 255, 0.07), 0 14px 30px -10px rgba(0, 0, 0, 0.62), 0 3px 8px rgba(0, 0, 0, 0.34);
/* AgentSCAD custom - Dark (Direction C2: Warm Graphite & Signal Orange) */
--app-bg: #141312;
--app-surface: rgba(34, 31, 28, 0.90);
--app-surface-raised: #26231F;
--app-surface-50: rgba(20, 19, 18, 0.5);
--app-surface-hover: rgba(255, 255, 255, 0.04);
--app-surface-95: rgba(20, 19, 18, 0.95);
--app-border: rgba(255, 255, 255, 0.075);
--app-border-subtle: rgba(255, 255, 255, 0.045);
--app-border-strong: rgba(255, 255, 255, 0.17);
--app-text-primary: #EDE8E0;
--app-text-secondary: #BEB6AC;
--app-text-muted: #948C82;
--app-text-dim: #6E6760;
--app-text-bright: #FFFFFF;
--app-scrollbar-thumb: #33302B;
--app-scrollbar-thumb-hover: #4D4841;
--app-scrollbar-track: transparent;
--app-focus-ring: rgba(255, 90, 31, 0.45);
--app-interactive-hover: rgba(255, 90, 31, 0.12);
--app-shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.5);
--app-shadow-md: 0 16px 40px -8px rgba(0, 0, 0, 0.6);
--app-keyboard-bg: #26231F;
--app-keyboard-border: rgba(255, 255, 255, 0.075);
--app-keyboard-text: #948C82;
--app-skeleton-bg: rgba(255, 255, 255, 0.04);
--app-notification-hover: rgba(255, 255, 255, 0.03);
--app-footer-separator: rgba(255, 255, 255, 0.08);
--app-footer-tooltip-bg: #26231F;
--app-footer-tooltip-border: rgba(255, 255, 255, 0.075);
--app-footer-tooltip-text: #BEB6AC;
--app-gradient-separator: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.075), transparent);
--app-card-hover-shadow: 0 4px 20px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 90, 31, 0.2);
--app-pipeline-bg: rgba(255, 255, 255, 0.04);
--app-activity-hover: rgba(255, 255, 255, 0.03);
--app-selected-bg: rgba(255, 90, 31, 0.12);
--app-code-copy-hover: rgba(255, 255, 255, 0.08);
--app-empty-bg: rgba(255, 255, 255, 0.02);
--app-accent: #FF5A1F;
--app-accent-hover: #FF6E36;
--app-accent-bg: rgba(255, 90, 31, 0.14);
--app-accent-border: rgba(255, 90, 31, 0.35);
--app-accent-text: #FF5A1F;
--app-accent-text-secondary: #FFB597;
--app-danger: #E8583F;
--app-danger-bg: rgba(232, 88, 63, 0.12);
--app-warning: #E8B84B;
--app-warning-bg: rgba(232, 184, 75, 0.12);
--app-success: #7BD68A;
--app-success-bg: rgba(123, 214, 138, 0.12);
--app-info: #FF5A1F;
--app-info-bg: rgba(255, 90, 31, 0.12);
/* Dual-Theme Status Semantics (WCAG AA >= 4.5:1 compliant in dark mode) */
--app-status-success-text: #7BD68A;
--app-status-success-bg: rgba(123, 214, 138, 0.14);
--app-status-success-border: rgba(123, 214, 138, 0.32);
--app-status-warning-text: #E8B84B;
--app-status-warning-bg: rgba(232, 184, 75, 0.14);
--app-status-warning-border: rgba(232, 184, 75, 0.32);
--app-status-danger-text: #E8583F;
--app-status-danger-bg: rgba(232, 88, 63, 0.14);
--app-status-danger-border: rgba(232, 88, 63, 0.32);
--app-status-info-text: #F59E0B;
--app-status-info-bg: rgba(245, 158, 11, 0.14);
--app-status-info-border: rgba(245, 158, 11, 0.32);
--app-header-bg: rgba(10, 13, 16, 0.85);
--app-dialog-overlay: rgba(10, 13, 16, 0.82);
--app-dialog-bg: #12161C;
--app-code-bg: #0A0D10;
--app-code-border: rgba(255, 255, 255, 0.09);
--app-tag-bg: rgba(255, 255, 255, 0.04);
--app-tag-border: rgba(255, 255, 255, 0.09);
--app-batch-bar-bg: rgba(245, 158, 11, 0.12);
--app-batch-bar-text: #F59E0B;
--app-input-bg: #0A0D10;
--app-input-border: rgba(255, 255, 255, 0.09);
--app-input-focus-border: rgba(245, 158, 11, 0.5);
--app-hover-subtle: rgba(255, 255, 255, 0.02);
--app-border-separator: rgba(255, 255, 255, 0.09);
--app-state-neutral-bg: rgba(148, 163, 184, 0.12);
--app-state-neutral-text: #94A3B8;
--app-state-neutral-dot: #525D6E;
--app-state-neutral-border: rgba(148, 163, 184, 0.22);
/* Same alias layer as the light theme: resolve to the shell, never to a second
palette. The dark values were already close, but `--cad-text` was the old near
white (#F8FAFC) and `--cad-surface` the old cool #12161C. */
--cad-bg: var(--shell-module-solid);
--cad-background: var(--shell-module-solid);
--cad-surface: var(--shell-well);
--cad-surface-raised: var(--shell-inner);
--cad-surface-muted: var(--shell-well);
--cad-border: var(--shell-border);
--cad-border-subtle: var(--shell-hairline);
--cad-border-strong: var(--shell-border-strong);
--cad-text: var(--shell-text);
--cad-text-primary: var(--shell-text);
--cad-text-secondary: var(--shell-text-muted);
--cad-text-muted: var(--shell-text-label);
--cad-text-dim: var(--shell-text-dim);
--cad-accent: var(--shell-signal);
--cad-accent-hover: var(--shell-signal);
--cad-accent-soft: color-mix(in srgb, var(--shell-signal) 15%, transparent);
--cad-accent-border: color-mix(in srgb, var(--shell-signal) 35%, transparent);
--cad-accent-bg: color-mix(in srgb, var(--shell-signal) 14%, transparent);
--cad-accent-text: var(--shell-signal-soft);
--cad-grid: var(--shell-grid);
--cad-measure: var(--shell-text);
--cad-success: var(--shell-ok);
--cad-warning: var(--shell-warn);
--cad-danger: var(--shell-fail);
--cad-input-bg: var(--shell-module-solid);
--cad-info: var(--shell-signal);
}
@layer base {
* {
@apply border-border outline-ring/50;
box-sizing: border-box;
}
html {
scrollbar-gutter: stable;
}
body {
@apply bg-background text-foreground;
transition: background-color 0.3s ease, color 0.2s ease;
overflow-x: hidden;
}
}
.stable-scrollbar {
scrollbar-gutter: stable;
}
.stable-scrollbar-both {
scrollbar-gutter: stable both-edges;
}
/* ─── AgentSCAD CAD Design System ────────────────────── */
/* Scrollbar - one owner (this file), one palette (the shell tokens). An injected
duplicate used to paint a zinc thumb with a violet hover on every scrollable
surface through `<body>`, which is not a colour this product uses. */
:root { scrollbar-color: var(--shell-scroll-thumb) transparent; }
::-webkit-scrollbar { width: 4px; height: 4px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--shell-scroll-thumb); border-radius: 2px; }
::-webkit-scrollbar-thumb:hover { background: var(--shell-scroll-thumb-hover); }
/* Selection - the shell's own accent, not a legacy near-white that disappears on
the light canvas. */
::selection {
background: color-mix(in srgb, var(--shell-signal) 30%, transparent);
color: var(--shell-text);
}
/* Slider */
[data-radix-slider-root] {
position: relative;
display: flex;
align-items: center;
user-select: none;
touch-action: none;
}
[data-radix-slider-root] > span:first-child {
position: relative;
flex-grow: 1;
height: 3px;
border-radius: 2px;
background: var(--app-border);
}
[data-radix-slider-range] {
position: absolute;
height: 100%;
border-radius: 2px;
background: var(--app-accent);
}
[data-radix-slider-thumb] {
display: block;
width: 13px;
height: 13px;
border-radius: 50%;
background: var(--app-surface);
border: 2px solid var(--app-accent);
box-shadow: var(--app-shadow-sm);
transition: transform 0.1s ease;
outline: none;
}
[data-radix-slider-thumb]:hover { transform: scale(1.1); }
[data-radix-slider-thumb]:focus-visible { box-shadow: 0 0 0 3px var(--app-focus-ring); }
[data-radix-slider-thumb][data-disabled] { opacity: 0.4; cursor: not-allowed; }
/* Progress Bar */
[data-slot="progress-indicator"] {
background: var(--app-accent);
transition: width 0.3s ease;
}
/* Resizable Handle */
[data-panel-group-direction="horizontal"] > [data-resize-handle] { transition: background 0.15s ease; }
[data-resize-handle][data-resize-handle-active] { background: var(--app-accent) !important; }
/* Code Block */
pre code { font-variant-ligatures: none; }
/* Tab Indicator */
[data-state="active"][role="tab"] { transition: border-color 0.15s ease; }
/* Focus States - one focus colour for the whole product: the shell's signal
accent, which is what `--ring` (shadcn focus-visible) resolves to as well. */
input:focus, textarea:focus, select:focus {
outline: none;
box-shadow: 0 0 0 2px var(--ring);
}
/*
* Fields that carry their own focus treatment opt out of the generic ring.
* Inside the shell a field states focus by turning its own border amber
* (DESIGN.md section 5, "the action is a circular button inside the field");
* the generic ring drew a second amber rectangle just inside the first, which is
* what made the active composer read as a warning panel.
*/
.shell-field:focus,
.shell-field:focus-visible {
box-shadow: none;
}
/*
* The rail's create action: the signal hue in its soft form. DESIGN.md section 11
* allows one *solid* orange group per screen (the composer's action and its status
* line), and forbids a third competing orange - so this control carries the accent as
* a tint and the softer text, and only reaches full signal on hover.
*/
.rail-create {
color: var(--shell-signal-soft);
border-color: color-mix(in srgb, var(--shell-signal) 40%, transparent);
background: color-mix(in srgb, var(--shell-signal) 10%, transparent);
}
.rail-create:hover {
color: var(--shell-signal);
border-color: color-mix(in srgb, var(--shell-signal) 62%, transparent);
background: color-mix(in srgb, var(--shell-signal) 18%, transparent);
}
.rail-create .rail-create-key {
color: color-mix(in srgb, var(--shell-signal-soft) 72%, transparent);
}
/* ─── Animations ─────────────────────────────────────────── */
@keyframes status-pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.animate-status-pulse { animation: status-pulse 2s ease-in-out infinite; }
@keyframes gentle-float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-4px); }
}
.empty-float { animation: gentle-float 4s ease-in-out infinite; }
@keyframes content-fade {
0% { opacity: 0; transform: translateY(4px); }
100% { opacity: 1; transform: translateY(0); }
}
.content-fade-in { animation: content-fade 0.2s ease-out; }
@keyframes badge-shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-2px); }
75% { transform: translateX(2px); }
}
.badge-shake { animation: badge-shake 0.4s ease-in-out; }
@keyframes typing-wave {
0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
30% { transform: translateY(-3px); opacity: 1; }
}
.typing-wave-dot {
display: inline-block;
width: 4px;
height: 4px;
border-radius: 50%;
background-color: var(--app-text-muted);
}
.typing-wave-dot:nth-child(1) { animation: typing-wave 1.2s ease-in-out infinite 0s; }
.typing-wave-dot:nth-child(2) { animation: typing-wave 1.2s ease-in-out infinite 0.15s; }
.typing-wave-dot:nth-child(3) { animation: typing-wave 1.2s ease-in-out infinite 0.3s; }
@keyframes stop-btn-pulse {
0%, 100% { box-shadow: 0 0 0 0 rgba(244, 63, 94, 0.3); }
50% { box-shadow: 0 0 0 3px rgba(244, 63, 94, 0); }
}
.stop-btn-pulse { animation: stop-btn-pulse 1.5s ease-out infinite; }
@keyframes notification-slide {
0% { opacity: 0; transform: translateX(12px); }
100% { opacity: 1; transform: translateX(0); }
}
@keyframes tag-pop {
0% { transform: scale(0.85); opacity: 0; }
100% { transform: scale(1); opacity: 1; }
}
@keyframes dialog-enter {
0% { opacity: 0; transform: translateY(4px); }
100% { opacity: 1; transform: translateY(0); }
}
.dialog-enter { animation: dialog-enter 0.15s ease-out; }
/* Direction 2: Shapr3D x VisionOS Spatial Glass Islands */
.glass-island {
background: var(--glass-island-bg, rgba(18, 22, 28, 0.78));
border: 1px solid var(--glass-island-border, rgba(255, 255, 255, 0.09));
backdrop-filter: blur(28px) saturate(160%);
-webkit-backdrop-filter: blur(28px) saturate(160%);
box-shadow: 0 16px 40px -8px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.12);
border-radius: 14px;
}
:root:not(.dark) .glass-island {
background: var(--glass-island-bg-light, rgba(255, 255, 255, 0.88));
border: 1px solid var(--glass-island-border-light, rgba(213, 221, 230, 0.8));
backdrop-filter: blur(20px) saturate(140%);
-webkit-backdrop-filter: blur(20px) saturate(140%);
box-shadow: 0 10px 30px -6px rgba(17, 24, 32, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.8);
border-radius: 14px;
}
/* Job card left border */
.job-card-left-border { position: relative; }
.job-card-left-border::before {
content: '';
position: absolute;
left: 0;
top: 4px;
bottom: 4px;
width: 2px;
border-radius: 0 1px 1px 0;
background-color: var(--border-color, var(--app-text-muted));
transition: background-color 0.15s ease;
}
/* Keyboard key */
.keyboard-key {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 24px;
height: 22px;
padding: 0 6px;
font-size: 11px;
font-family: var(--font-mono), monospace;
font-weight: 500;
color: var(--app-keyboard-text);
background: var(--app-keyboard-bg);
border: 1px solid var(--app-keyboard-border);
border-bottom-width: 1.5px;
border-radius: 4px;
white-space: nowrap;
line-height: 1;
}
.keyboard-key-lg { min-width: 30px; height: 26px; font-size: 12px; padding: 0 8px; }
/* Code copy button */
.code-copy-btn {
position: absolute;
top: 4px;
right: 4px;
opacity: 0;
transition: opacity 0.15s ease, background-color 0.15s ease;
z-index: 10;
}
.code-copy-btn:hover { background-color: var(--app-code-copy-hover); }
pre:hover .code-copy-btn { opacity: 1; }
/* Tab active underline */
.tab-active-glow { position: relative; }
.tab-active-glow::after {
content: '';
position: absolute;
bottom: -1px;
left: 0;
right: 0;
height: 1px;
background: var(--app-accent);
}
/* Notification item */
.notification-item { transition: background-color 0.15s ease; }
.notification-item:hover { background-color: var(--app-notification-hover); }
/* Tag badge */
.tag-badge { animation: tag-pop 0.15s ease-out both; line-height: 1.4; }
/* Footer separator */
.footer-separator {
width: 1px;
height: 10px;
background: var(--app-footer-separator);
display: inline-block;
vertical-align: middle;
}
/* Skeleton loading */
.skeleton-loading {
background: var(--app-skeleton-bg);
border-radius: 4px;
animation: status-pulse 2s ease-in-out infinite;
}
/* Online status dot (breathing) */
.online-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--app-success);
display: inline-block;
animation: status-pulse 2.5s ease-in-out infinite;
box-shadow: 0 0 0 2px var(--app-success-bg);
}
/* Compare card border */
.compare-border-left { position: relative; border-left: 2px solid transparent; }
/* ─── Enhanced Styling Classes ─────────────────────────── */
/* Job card hover - gradient + shadow (no layout shift) */
.job-card-hover {
position: relative;
overflow: hidden;
transition: box-shadow 0.2s ease, background-color 0.2s ease;
will-change: box-shadow;
}
.job-card-hover::after {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(135deg, var(--app-accent-bg) 0%, transparent 60%);
opacity: 0;
transition: opacity 0.2s ease;
pointer-events: none;
border-radius: inherit;
}
.job-card-hover:hover::after {
opacity: 1;
}
.job-card-hover:hover {
box-shadow: var(--app-card-hover-shadow);
}
/* Tab indicator - active tab left border */
.tab-indicator {
position: relative;
}
.tab-indicator::before {
content: '';
position: absolute;
left: 0;
top: 4px;
bottom: 4px;
width: 2px;
border-radius: 0 1px 1px 0;
background: var(--app-accent);
opacity: 0;
transition: opacity 0.15s ease;
}
.tab-indicator[data-state="active"]::before {
opacity: 1;
}
/* Skeleton pulse - legacy gradient shimmer for loading states */
.skeleton-pulse {
background: linear-gradient(90deg, var(--app-skeleton-bg) 25%, var(--app-border) 50%, var(--app-skeleton-bg) 75%);
background-size: 200% 100%;
animation: skeleton-shimmer 1.5s ease-in-out infinite;
border-radius: 4px;
}
@keyframes skeleton-shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
/* Skeleton shimmer: engineering scanline shimmer */
.skeleton-shimmer {
position: relative;
overflow: hidden;
background-color: var(--app-skeleton-bg);
border-radius: 6px;
}
.skeleton-shimmer::after {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
transform: translateX(-100%);
background-image: linear-gradient(
90deg,
rgba(255, 255, 255, 0) 0,
rgba(255, 255, 255, 0.05) 20%,
rgba(255, 255, 255, 0.14) 60%,
rgba(255, 255, 255, 0)
);
animation: engineeringShimmer 1.8s infinite cubic-bezier(0.4, 0, 0.2, 1);
content: '';
}
:root:not(.dark) .skeleton-shimmer::after {
background-image: linear-gradient(
90deg,
rgba(15, 23, 42, 0) 0,
rgba(15, 23, 42, 0.04) 20%,
rgba(15, 23, 42, 0.10) 60%,
rgba(15, 23, 42, 0)
);
}
@keyframes engineeringShimmer {
100% {
transform: translateX(100%);
}
}
/* Slide in from right (tab forward) */
.slide-in-right {
animation: slideInRight 0.2s ease-out;
}
@keyframes slideInRight {
0% { opacity: 0; transform: translateX(20px); }
100% { opacity: 1; transform: translateX(0); }
}
/* Slide in from left (tab backward) */
.slide-in-left {
animation: slideInLeft 0.2s ease-out;
}
@keyframes slideInLeft {
0% { opacity: 0; transform: translateX(-20px); }
100% { opacity: 1; transform: translateX(0); }
}
/* Activity item - hover highlight */
.activity-item {
transition: background-color 0.15s ease;
border-radius: 6px;
}
.activity-item:hover {
background-color: var(--app-activity-hover);
}
/* Activity slide-in animation */
.activity-slide-in {
animation: activitySlideIn 0.25s ease-out;
}
@keyframes activitySlideIn {
0% { opacity: 0; transform: translateY(-8px); }
100% { opacity: 1; transform: translateY(0); }
}
/* State change bounce micro-animation */
.state-bounce {
animation: stateBounce 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes stateBounce {
0% { transform: scale(0.97); }
50% { transform: scale(1.02); }
100% { transform: scale(1); }
}
/* Gradient separator between header and content */
.gradient-separator {
height: 1px;
background: var(--app-gradient-separator);
border: none;
}
/* Progress indicator for pipeline states */
.pipeline-mini-progress {
height: 2px;
background: var(--app-pipeline-bg);
border-radius: 1px;
overflow: hidden;
position: relative;
}
.pipeline-mini-progress-fill {
height: 100%;
border-radius: 1px;
transition: width 0.5s ease;
}
/* Reduced motion support */
@media (prefers-reduced-motion: reduce) {
.job-card-hover::after,
.job-card-hover:hover {
transition: none;
transform: none;
}
.skeleton-pulse { animation: none; }
.skeleton-shimmer::after { animation: none; display: none; }
.slide-in-right, .slide-in-left { animation: none; }
.activity-slide-in { animation: none; }
.state-bounce { animation: none; }
.empty-float { animation: none; }
}
/* ─── 正在生成: the part tumbling on the bench ───────────────────────────────────
Two axes, so it reads as an object being turned over rather than a spinning
sprite: it nods on X while it comes round on Y. */
@keyframes partTumble {
0% { transform: rotateX(-22deg) rotateY(0deg); }
50% { transform: rotateX(16deg) rotateY(180deg); }
100% { transform: rotateX(-22deg) rotateY(360deg); }
}
.part-tumble {
animation: partTumble 5.2s cubic-bezier(0.45, 0.05, 0.55, 0.95) infinite;
}
/* Reduced motion: the part holds a readable three-quarter angle instead of turning.
This has to come after the rule above - the earlier reduced-motion block sits
higher in the file and lost the cascade, so the gear kept spinning. */
@media (prefers-reduced-motion: reduce) {
.part-tumble {
animation: none;
transform: rotateX(-20deg) rotateY(32deg);
}
}
/* Touch devices: expand hit area for icon-sized buttons to WCAG 44x44.
Visual size stays 36x36 on desktop IDE; coarse pointer (tablet/touch) gets a
transparent ::before expansion that doesn't affect layout. */
@media (pointer: coarse) {
.size-9 { position: relative; }
.size-9::before {
content: '';
position: absolute;
inset: -4px;
}
/*
* DESIGN.md section 20: hit targets are at least 44px on touch. Every control in
* the shell measured under 44px (module collapse 16x16, bell and gear 24x24,
* density segments 36x22 / 46x22, row utilities 16x20 / 20x20, viewport controls
* 28x28), so the hit area grows to 44px tall while the visible control keeps its
* instrument size. Vertical only: these controls sit shoulder to shoulder
* horizontally, and a wider invisible target would steal taps from its neighbour.
*/
.mod-h button,
#brand button,
#controls button,
#cmd button,
#view-cube button,
[data-testid="design-row"] button {
position: relative;
}
.mod-h button::after,
#brand button::after,
#controls button::after,
#cmd button::after,
#view-cube button::after,
[data-testid="design-row"] button::after {
content: '';
position: absolute;
left: 0;
right: 0;
top: 50%;
height: 44px;
transform: translateY(-50%);
}
/* Fields and chips cannot grow their hit area with a pseudo-element: an <input>
ignores ::after, and the empty-state chips are the whole target. These grow. */
#cmd input,
#slots input,
#slots button,
[data-testid="viewport-cold-start"] button {
min-height: 44px;
}
#slots button {
min-width: 44px;
}
}
/* Footer tooltip */
.footer-metric {
position: relative;
cursor: default;
}
/* ─── Linear Design Utilities ──────────────────────────────── */
.linear-surface { background: var(--app-surface); border: 1px solid var(--app-border); }
.linear-surface-hover:hover { background: var(--app-surface-hover); }
.linear-border { border: 1px solid var(--app-border); }
.linear-focus-ring:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--app-focus-ring); }
.linear-selected { border-left: 2px solid var(--app-accent); background: var(--app-selected-bg); }
.linear-transition { transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease, opacity 0.15s ease; }
.linear-shadow-sm { box-shadow: var(--app-shadow-sm); }
.linear-shadow-md { box-shadow: var(--app-shadow-md); }
/* Typography tokens: section eyebrows (mono uppercase tracked) */
.text-eyebrow {
font-size: 11px;
font-family: var(--font-mono), ui-monospace, monospace;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.16em;
line-height: 1;
}
.cad-surface {
background: var(--cad-surface);
border: 1px solid var(--cad-border);
}
.cad-panel {
background: linear-gradient(180deg, color-mix(in srgb, var(--cad-surface) 96%, white 4%), var(--cad-surface));
border: 1px solid var(--cad-border);
border-radius: 8px;
}
.cad-chip {
display: inline-flex;
align-items: center;
gap: 0.35rem;
min-height: 24px;
padding: 0 0.55rem;
border: 1px solid var(--cad-border);
border-radius: 6px;
background: var(--cad-accent-soft);
color: var(--cad-text-secondary);
font-size: 10px;
font-family: var(--font-mono), monospace;
line-height: 1;
}
.cad-viewport-shell {
/*
* The viewport is the largest surface in the product and it was painted from the
* old palette: `--cad-bg` (#0A0D10 dark / #F4F6F8 light, a cool near-black and a
* cool grey) instead of the C2 field, `--cad-grid` for its straight grid, a 14%
* accent radial halo behind the part (a zero-offset glow: decoration, not depth)
* and a 1px legacy border with an 8px radius. The canvas is transparent, so that
* background colour is what the user actually sees around the part.
*
* Now: one field token, no halo, no inset frame. DESIGN.md section 3 makes the
* canvas full-bleed and section 4 puts the lighting on the camera, not on a
* decorative glow behind the part.
*/
background: var(--shell-canvas-deep);
}
.cad-viewport-glass {
background: color-mix(in srgb, var(--cad-surface) 82%, transparent);
border: 1px solid var(--cad-border);
backdrop-filter: blur(12px);
}
.cad-status-dot {
width: 6px;
height: 6px;
border-radius: 999px;
background: var(--cad-accent);
box-shadow: 0 0 0 3px var(--cad-accent-soft);
}
.cad-inspector-panel {
min-width: 0;
}
.cad-inspector-tabs {
scrollbar-width: none;
-webkit-overflow-scrolling: touch;
}
.cad-inspector-tabs::-webkit-scrollbar {
display: none;
}
.cad-inspector-tabs [role="tab"] {
min-width: max-content;
}
@media (max-width: 1023px) {
/*
* The docked three-column layout these rules belonged to is gone (DESIGN.md
* section 3). Keeping them alive meant that at <=1023px `.cad-left-panel`
* still matched the slots rail inside its floating module and hid it with
* `display:none !important`: the plate stayed on screen, kept its count badge,
* and rendered an empty body, so no part could be selected.
*
* The classes survive as hooks (ViewerPanel: "styling/test hook"); the layout
* media queries do not. Responsive behaviour below 960px is still phase 6.
*/
.cad-viewer-panel,
.cad-inspector-panel {
min-width: 0;
}
}
@media (max-width: 767px) {
.cad-viewer-panel,
.cad-inspector-panel {
min-width: 0;
}
}
/* ─── Breadcrumb fade-in ──────────────────────────────── */
@keyframes breadcrumbFadeIn {
0% { opacity: 0; }
100% { opacity: 1; }
}
.breadcrumb-fade-in { animation: breadcrumbFadeIn 0.2s ease-out; }
/* ─── Job Status Page Animations ──────────────────────── */
@keyframes statusPageEnter {
0% { opacity: 0; transform: translateY(12px); }
100% { opacity: 1; transform: translateY(0); }
}
.status-page-enter { animation: statusPageEnter 0.3s ease-out; }
/* Status icon pulse ring */
@keyframes statusIconPulse {
0% { box-shadow: 0 0 0 0 var(--app-accent-border); }
70% { box-shadow: 0 0 0 20px transparent; }
100% { box-shadow: 0 0 0 0 transparent; }
}
.status-icon-pulse { animation: statusIconPulse 2s ease-out infinite; }
/* Line clamp for 2 lines */
.line-clamp-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* ─── Theme Transition ──────────────────────────────────── */
html.theme-transition,
html.theme-transition *,
html.theme-transition *::before,
html.theme-transition *::after {
transition: background-color 0.3s ease, border-color 0.3s ease, color 0.2s ease, box-shadow 0.3s ease, fill 0.2s ease, stroke 0.2s ease !important;
}
/*
* Direction C2 floating module plate.
*
* The plate is owned by `Module.tsx`, which writes every visual property from the
* shell tokens (DESIGN.md section 22: one writer per element). This file used to
* carry a second, hardcoded copy of the same plate - same background, same border,
* same shadow, literals instead of tokens - which made light mode and any token
* change silently disagree between the two definitions.
*
* Only the two affordances that are pure CSS are kept here.
*/
.mod-h {
cursor: grab;
}
.mod-h:active {
cursor: grabbing;
}
e934a3ad8This file is pinned to the selected release. Download the original to open it in your design tool.