diff --git a/resources/css/app.css b/resources/css/app.css
index 92db7297..eb623584 100644
--- a/resources/css/app.css
+++ b/resources/css/app.css
@@ -1,6 +1,8 @@
@import 'tailwindcss';
@import 'tw-animate-css';
@import 'vue-sonner/style.css';
+@import './automations.css';
+@import './json-viewer.css';
@plugin '@tailwindcss/typography';
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../storage/framework/views/*.php';
@@ -165,128 +167,3 @@ .trypost-container {
@apply relative max-w-7xl w-full flex-1 mx-auto flex flex-col justify-center;
}
-/* Automations canvas nodes — TryPost brutalist identity:
- thick ink borders, hard offset shadow, warm card background, colored header
- strip that fills the top of the card with the accent tint. */
-.automation-node {
- position: relative;
- min-width: 230px;
- max-width: 260px;
- background: var(--card);
- border: 2px solid var(--foreground);
- border-radius: 14px;
- box-shadow: 3px 3px 0 var(--foreground);
- transition: transform 120ms ease, box-shadow 120ms ease;
-}
-
-.automation-node:hover {
- transform: translate(-1px, -1px);
- box-shadow: 4px 4px 0 var(--foreground);
-}
-
-.automation-node--wide {
- min-width: 260px;
- max-width: 260px;
-}
-
-.automation-node.is-selected {
- transform: translate(-2px, -2px);
- box-shadow: 5px 5px 0 #7c3aed;
-}
-
-.automation-node__header {
- display: flex;
- align-items: center;
- gap: 0.625rem;
- padding: 0.625rem 0.875rem;
- border-bottom: 2px solid var(--foreground);
- border-top-left-radius: 12px;
- border-top-right-radius: 12px;
-}
-
-.automation-node__icon-tile {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- width: 28px;
- height: 28px;
- border: 2px solid var(--foreground);
- border-radius: 8px;
- flex-shrink: 0;
- transform: rotate(-3deg);
-}
-
-/* Header accent tint mirrors the icon tile color, applied to the whole header
- strip so the node type is identifiable at a glance from the canvas. */
-.automation-node__icon-tile--violet { background: #ede9fe; color: #5b21b6; }
-.automation-node__icon-tile--blue { background: #dbeafe; color: #1d4ed8; }
-.automation-node__icon-tile--amber { background: #fef3c7; color: #92400e; }
-.automation-node__icon-tile--rose { background: #ffe4e6; color: #be123c; }
-.automation-node__icon-tile--emerald { background: #d1fae5; color: #047857; }
-.automation-node__icon-tile--slate { background: #e2e8f0; color: #334155; }
-.automation-node__icon-tile--zinc { background: #e4e4e7; color: #27272a; }
-.automation-node__icon-tile--cyan { background: #cffafe; color: #155e75; }
-
-.automation-node--accent-violet .automation-node__header { background: #f5f3ff; }
-.automation-node--accent-blue .automation-node__header { background: #eff6ff; }
-.automation-node--accent-amber .automation-node__header { background: #fffbeb; }
-.automation-node--accent-rose .automation-node__header { background: #fff1f2; }
-.automation-node--accent-emerald .automation-node__header { background: #ecfdf5; }
-.automation-node--accent-slate .automation-node__header { background: #f1f5f9; }
-.automation-node--accent-zinc .automation-node__header { background: #f4f4f5; }
-.automation-node--accent-cyan .automation-node__header { background: #ecfeff; }
-
-.automation-node__title {
- min-width: 0;
- font-weight: 700;
- font-size: 0.875rem;
- color: var(--foreground);
- line-height: 1.2;
- letter-spacing: -0.005em;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
-.automation-node__summary {
- padding: 0.625rem 0.875rem 0.75rem 0.875rem;
- font-size: 0.75rem;
- font-weight: 500;
- color: color-mix(in srgb, var(--foreground) 70%, transparent);
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- border-bottom-left-radius: 12px;
- border-bottom-right-radius: 12px;
-}
-
-.automation-node__branches {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 0.375rem 0.875rem 0.625rem 0.875rem;
- font-size: 0.625rem;
- font-weight: 700;
- text-transform: uppercase;
- letter-spacing: 0.06em;
-}
-
-.automation-node__branch--yes { color: #047857; }
-.automation-node__branch--no { color: #be123c; }
-
-/* JsonViewer — GitHub Light palette for highlight.js JSON output. */
-
-.json-viewer__body {
- font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
- margin: 0;
- background: #ffffff;
- color: #24292f;
-}
-
-.json-viewer .hljs-attr { color: #0550ae; }
-.json-viewer .hljs-string { color: #0a3069; }
-.json-viewer .hljs-number { color: #0550ae; }
-.json-viewer .hljs-literal { color: #cf222e; }
-.json-viewer .hljs-punctuation { color: #57606a; }
-.json-viewer .hljs-comment { color: #6e7781; font-style: italic; }
-
diff --git a/resources/css/automations.css b/resources/css/automations.css
new file mode 100644
index 00000000..469d7dc7
--- /dev/null
+++ b/resources/css/automations.css
@@ -0,0 +1,103 @@
+.automation-node {
+ position: relative;
+ min-width: 230px;
+ max-width: 260px;
+ background: var(--card);
+ border: 2px solid var(--foreground);
+ border-radius: 14px;
+ box-shadow: 3px 3px 0 var(--foreground);
+ transition: transform 120ms ease, box-shadow 120ms ease;
+}
+
+.automation-node:hover {
+ transform: translate(-1px, -1px);
+ box-shadow: 4px 4px 0 var(--foreground);
+}
+
+.automation-node--wide {
+ min-width: 260px;
+ max-width: 260px;
+}
+
+.automation-node.is-selected {
+ transform: translate(-2px, -2px);
+ box-shadow: 5px 5px 0 #7c3aed;
+}
+
+.automation-node__header {
+ display: flex;
+ align-items: center;
+ gap: 0.625rem;
+ padding: 0.625rem 0.875rem;
+ border-bottom: 2px solid var(--foreground);
+ border-top-left-radius: 12px;
+ border-top-right-radius: 12px;
+}
+
+.automation-node__icon-tile {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 28px;
+ height: 28px;
+ border: 2px solid var(--foreground);
+ border-radius: 8px;
+ flex-shrink: 0;
+ transform: rotate(-3deg);
+}
+
+.automation-node__icon-tile--violet { background: #ede9fe; color: #5b21b6; }
+.automation-node__icon-tile--blue { background: #dbeafe; color: #1d4ed8; }
+.automation-node__icon-tile--amber { background: #fef3c7; color: #92400e; }
+.automation-node__icon-tile--rose { background: #ffe4e6; color: #be123c; }
+.automation-node__icon-tile--emerald { background: #d1fae5; color: #047857; }
+.automation-node__icon-tile--slate { background: #e2e8f0; color: #334155; }
+.automation-node__icon-tile--zinc { background: #e4e4e7; color: #27272a; }
+.automation-node__icon-tile--cyan { background: #cffafe; color: #155e75; }
+
+.automation-node--accent-violet .automation-node__header { background: #f5f3ff; }
+.automation-node--accent-blue .automation-node__header { background: #eff6ff; }
+.automation-node--accent-amber .automation-node__header { background: #fffbeb; }
+.automation-node--accent-rose .automation-node__header { background: #fff1f2; }
+.automation-node--accent-emerald .automation-node__header { background: #ecfdf5; }
+.automation-node--accent-slate .automation-node__header { background: #f1f5f9; }
+.automation-node--accent-zinc .automation-node__header { background: #f4f4f5; }
+.automation-node--accent-cyan .automation-node__header { background: #ecfeff; }
+
+.automation-node__title {
+ min-width: 0;
+ font-weight: 700;
+ font-size: 0.875rem;
+ color: var(--foreground);
+ line-height: 1.2;
+ letter-spacing: -0.005em;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.automation-node__summary {
+ padding: 0.625rem 0.875rem 0.75rem 0.875rem;
+ font-size: 0.75rem;
+ font-weight: 500;
+ color: color-mix(in srgb, var(--foreground) 70%, transparent);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ border-bottom-left-radius: 12px;
+ border-bottom-right-radius: 12px;
+}
+
+.automation-node__branches {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0.375rem 0.875rem 0.625rem 0.875rem;
+ font-size: 0.625rem;
+ font-weight: 700;
+ text-transform: uppercase;
+ letter-spacing: 0.06em;
+}
+
+.automation-node__branch--yes { color: #047857; }
+.automation-node__branch--no { color: #be123c; }
diff --git a/resources/css/json-viewer.css b/resources/css/json-viewer.css
new file mode 100644
index 00000000..95ee2b83
--- /dev/null
+++ b/resources/css/json-viewer.css
@@ -0,0 +1,13 @@
+.json-viewer__body {
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
+ margin: 0;
+ background: #ffffff;
+ color: #24292f;
+}
+
+.json-viewer .hljs-attr { color: #0550ae; }
+.json-viewer .hljs-string { color: #0a3069; }
+.json-viewer .hljs-number { color: #0550ae; }
+.json-viewer .hljs-literal { color: #cf222e; }
+.json-viewer .hljs-punctuation { color: #57606a; }
+.json-viewer .hljs-comment { color: #6e7781; font-style: italic; }
diff --git a/resources/js/components/automations/TestRunPanel.vue b/resources/js/components/automations/TestRunPanel.vue
index 90dba74c..1b9ad3b0 100644
--- a/resources/js/components/automations/TestRunPanel.vue
+++ b/resources/js/components/automations/TestRunPanel.vue
@@ -8,6 +8,7 @@ import { showRun as showRunRoute } from '@/actions/App/Http/Controllers/App/Auto
import JsonViewer from '@/components/JsonViewer.vue';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
+import { Label } from '@/components/ui/label';
import { useAutomationEcho } from '@/composables/echo/useAutomationEcho';
import { test as testAutomation } from '@/routes/app/automations';
@@ -152,10 +153,10 @@ const isZeroFetchResult = (nodeRun: NodeRun): boolean => {
-