- Mark nodes unschedulable and pin blueprints to specific nodes. Sencho proposes placements; you approve them. Existing deployments are never moved without an explicit operator action.
-
-
-
+
diff --git a/frontend/src/components/fleet/FleetEmptyState.tsx b/frontend/src/components/fleet/FleetEmptyState.tsx
new file mode 100644
index 00000000..78b8be02
--- /dev/null
+++ b/frontend/src/components/fleet/FleetEmptyState.tsx
@@ -0,0 +1,61 @@
+import type { LucideIcon } from 'lucide-react';
+import type { ReactNode } from 'react';
+
+interface FleetTabHeadingProps {
+ title: string;
+ subtitle: string;
+ action?: ReactNode;
+}
+
+/**
+ * Standardized Fleet tab header: italic-serif title and muted subtitle on the
+ * left, an optional primary action on the right. Rendered in both empty and
+ * populated states so the tab chrome stays consistent.
+ */
+export function FleetTabHeading({ title, subtitle, action }: FleetTabHeadingProps) {
+ return (
+
+
+
{title}
+
{subtitle}
+
+ {action}
+
+ );
+}
+
+/**
+ * Vertical-centering shell that floats an empty-state card in the middle of the
+ * tab body, below the heading.
+ */
+export function FleetEmptyState({ children }: { children: ReactNode }) {
+ return (
+