diff --git a/src/ui/ActionCard.tsx b/src/ui/ActionCard.tsx
index cf8f2e4..395d43a 100644
--- a/src/ui/ActionCard.tsx
+++ b/src/ui/ActionCard.tsx
@@ -148,6 +148,22 @@ export function ActionCard({ action }: ActionCardProps) {
) : null}
) : null}
+ {action.automationUnlocked ? (
+
+ ) : null}
);
}
diff --git a/src/ui/AutomationBar.tsx b/src/ui/AutomationBar.tsx
new file mode 100644
index 0000000..531112d
--- /dev/null
+++ b/src/ui/AutomationBar.tsx
@@ -0,0 +1,88 @@
+import { useState } from 'react';
+import { gameRuntime } from '../state/runtime';
+import { useGameStore } from '../state/store';
+
+export function AutomationBar() {
+ const automationQueueIds = useGameStore((s) => s.automationQueueIds);
+ const automationQueueNames = useGameStore((s) => s.automationQueueNames);
+ const [importText, setImportText] = useState('');
+
+ async function copyRecipe() {
+ const text = gameRuntime.exportAutomationRecipe();
+ try {
+ await navigator.clipboard?.writeText(text);
+ return;
+ } catch {
+ // Fall through to the legacy selection path.
+ }
+
+ const textarea = document.createElement('textarea');
+ textarea.value = text;
+ textarea.setAttribute('readonly', 'true');
+ textarea.style.position = 'fixed';
+ textarea.style.opacity = '0';
+ document.body.append(textarea);
+ textarea.select();
+ document.execCommand('copy');
+ textarea.remove();
+ }
+
+ function importRecipeText() {
+ gameRuntime.importAutomationRecipe(importText);
+ setImportText('');
+ }
+
+ return (
+ No automated processes.
+ Automation
+
+
+
+ {automationQueueNames.map((name, index) => (
+
+ ) : (
+