diff --git a/public/claude-ide/index.html b/public/claude-ide/index.html
index 3f244f01..674ef7d8 100644
--- a/public/claude-ide/index.html
+++ b/public/claude-ide/index.html
@@ -233,7 +233,7 @@
+
diff --git a/public/claude-ide/tool-renderers.js b/public/claude-ide/tool-renderers.js
new file mode 100644
index 00000000..8f59b914
--- /dev/null
+++ b/public/claude-ide/tool-renderers.js
@@ -0,0 +1,568 @@
+/**
+ * Tool Call Renderers - Specialized rendering per tool type
+ * Inspired by CodeNomad's tool rendering system
+ * https://github.com/NeuralNomadsAI/CodeNomad
+ *
+ * Each tool type gets specialized rendering to show the most relevant information
+ * in a user-friendly, context-specific way.
+ */
+
+'use strict';
+
+// ============================================================
+// Tool Renderer Registry
+// ============================================================
+
+class ToolRendererRegistry {
+ constructor() {
+ this.renderers = new Map();
+ this.registerDefaultRenderers();
+ }
+
+ /**
+ * Register a tool renderer
+ * @param {string} toolName - Name of the tool
+ * @param {Object} renderer - Renderer object with getAction, getTitle, renderBody
+ */
+ register(toolName, renderer) {
+ this.renderers.set(toolName, renderer);
+ }
+
+ /**
+ * Get renderer for a tool
+ * @param {string} toolName - Name of the tool
+ * @returns {Object} - Renderer object
+ */
+ get(toolName) {
+ return this.renderers.get(toolName) || this.renderers.get('default');
+ }
+
+ /**
+ * Register all default tool renderers
+ */
+ registerDefaultRenderers() {
+ // Bash/Shell Commands
+ this.register('bash', {
+ icon: 'โก',
+ getAction: (input) => 'Writing command...',
+ getTitle: (input, output, metadata) => {
+ const desc = input.description || input.command || '';
+ const timeout = input.timeout ? `ยท ${input.timeout}ms` : '';
+ return desc ? `Shell ${desc} ${timeout}`.trim() : 'Shell';
+ },
+ renderBody: (input, output, metadata) => {
+ const command = input.command ? `$ ${escapeHtml(input.command)}` : '';
+ const out = metadata.output || output || '';
+ const exitCode = metadata.exitCode !== undefined ? `Exit: ${metadata.exitCode}` : '';
+
+ return `
+
+ `;
+ }
+ });
+
+ // File Edit
+ this.register('edit', {
+ icon: 'โ๏ธ',
+ getAction: () => 'Preparing edit...',
+ getTitle: (input) => {
+ const file = input.filePath?.split('/').pop() || 'file';
+ return `Edit ${file}`;
+ },
+ renderBody: (input, output, metadata) => {
+ const diff = metadata.diff || output;
+ const filePath = input.filePath || 'unknown';
+
+ if (diff) {
+ return `
+
+ `;
+ }
+
+ const stats = metadata.stats || {};
+ const statsText = stats.added || stats.removed ?
+ `${stats.added || 0} additions, ${stats.removed || 0} deletions` : '';
+
+ return `
+
+ `;
+ }
+ });
+
+ // File Write
+ this.register('write', {
+ icon: '๐',
+ getAction: () => 'Writing file...',
+ getTitle: (input) => {
+ const file = input.filePath?.split('/').pop() || 'file';
+ return `Write ${file}`;
+ },
+ renderBody: (input, output) => {
+ const filePath = input.filePath || 'unknown';
+ const content = output || '';
+ const lines = content.split('\n').length;
+ const size = new Blob([content]).size;
+
+ return `
+
+ `;
+ }
+ });
+
+ // File Read
+ this.register('read', {
+ icon: '๐',
+ getAction: () => 'Reading file...',
+ getTitle: (input) => {
+ const file = input.filePath?.split('/').pop() || 'file';
+ return `Read ${file}`;
+ },
+ renderBody: (input, output, metadata) => {
+ const preview = metadata.preview || output || '';
+ const filePath = input.filePath || 'unknown';
+
+ if (preview) {
+ const lines = preview.split('\n').slice(0, 6).join('\n');
+ const totalLines = preview.split('\n').length;
+
+ return `
+
+ `;
+ }
+
+ return `
+
+ `;
+ }
+ });
+
+ // Web Search
+ this.register('websearch', {
+ icon: '๐',
+ getAction: () => 'Searching...',
+ getTitle: (input) => {
+ const query = input.query?.substring(0, 50) || '';
+ return query ? `Search: ${query}...` : 'Search';
+ },
+ renderBody: (input, output) => {
+ if (Array.isArray(output)) {
+ return `
+
+ `;
+ }
+
+ // Fallback for string output
+ if (typeof output === 'string') {
+ return ``;
+ }
+
+ return '';
+ }
+ });
+
+ // WebFetch
+ this.register('webfetch', {
+ icon: '๐',
+ getAction: () => 'Fetching...',
+ getTitle: (input) => {
+ const url = input.url?.substring(0, 50) || '';
+ return url ? `Fetch ${url}...` : 'Fetch';
+ },
+ renderBody: (input, output, metadata) => {
+ const url = input.url || '';
+ const content = output || '';
+ const preview = content.substring(0, 300);
+
+ return `
+
+ `;
+ }
+ });
+
+ // Task/Agent Delegation
+ this.register('task', {
+ icon: '๐ค',
+ getAction: () => 'Delegating...',
+ getTitle: (input) => {
+ const type = input.subagent_type || 'agent';
+ const desc = input.description?.substring(0, 40) || '';
+ return desc ? `Task[${type}] ${desc}...` : `Task[${type}]`;
+ },
+ renderBody: (input, output, metadata) => {
+ const summary = metadata.summary || [];
+ const result = output;
+
+ if (summary.length > 0) {
+ return `
+
+ `;
+ }
+
+ if (result && typeof result === 'string') {
+ return ``;
+ }
+
+ return '';
+ }
+ });
+
+ // Todo/Plan Management
+ this.register('todowrite', {
+ icon: '๐',
+ getAction: (input) => {
+ const todos = input.todos || [];
+ const allPending = todos.every(t => t.status === 'pending');
+ const allCompleted = todos.every(t => t.status === 'completed');
+ if (allPending) return 'Creating plan...';
+ if (allCompleted) return 'Completing plan...';
+ return 'Updating plan...';
+ },
+ getTitle: (input) => {
+ const todos = input.todos || [];
+ const completed = todos.filter(t => t.status === 'completed').length;
+ const total = todos.length;
+ return `Plan (${completed}/${total})`;
+ },
+ renderBody: (input) => {
+ const todos = input.todos || [];
+ return `
+
+ `;
+ }
+ });
+
+ // Grep - Content Search
+ this.register('grep', {
+ icon: '๐',
+ getAction: () => 'Searching...',
+ getTitle: (input) => {
+ const pattern = input.pattern?.substring(0, 40) || '';
+ return pattern ? `Grep "${pattern}"` : 'Grep';
+ },
+ renderBody: (input, output) => {
+ if (Array.isArray(output)) {
+ return `
+
+ `;
+ }
+ return '';
+ }
+ });
+
+ // Glob - File Pattern Matching
+ this.register('glob', {
+ icon: '๐',
+ getAction: () => 'Searching files...',
+ getTitle: (input) => {
+ const pattern = input.pattern?.substring(0, 50) || '';
+ return pattern ? `Glob ${pattern}` : 'Glob';
+ },
+ renderBody: (input, output) => {
+ const files = output || [];
+ const count = files.length;
+
+ if (count > 0) {
+ return `
+
+ `;
+ }
+
+ return 'No files found
';
+ }
+ });
+
+ // List - Directory Listing
+ this.register('list', {
+ icon: '๐',
+ getAction: () => 'Listing directory...',
+ getTitle: (input) => {
+ const path = input.path || '';
+ return `List ${path.split('/').pop() || 'directory'}`;
+ },
+ renderBody: (input, output) => {
+ const entries = output?.entries || [];
+ return `
+
+ `;
+ }
+ });
+
+ // Patch - Apply Patch
+ this.register('patch', {
+ icon: '๐ง',
+ getAction: () => 'Applying patch...',
+ getTitle: () => 'Patch',
+ renderBody: (input, output) => {
+ return `
+
+ `;
+ }
+ });
+
+ // Default fallback for unknown tools
+ this.register('default', {
+ icon: '๐ง',
+ getAction: () => 'Processing...',
+ getTitle: (input, toolName) => {
+ return capitalize(toolName || 'tool');
+ },
+ renderBody: (input, output) => {
+ if (typeof output === 'string' && output) {
+ const preview = output.split('\n').slice(0, 10).join('\n');
+ return ``;
+ }
+ if (output && typeof output === 'object') {
+ return ``;
+ }
+ return '';
+ }
+ });
+ }
+}
+
+// ============================================================
+// Helper Functions
+// ============================================================
+
+/**
+ * Escape HTML to prevent XSS
+ */
+function escapeHtml(text) {
+ if (text === null || text === undefined) return '';
+ const div = document.createElement('div');
+ div.textContent = text;
+ return div.innerHTML;
+}
+
+/**
+ * Capitalize first letter
+ */
+function capitalize(str) {
+ if (!str) return '';
+ return str.charAt(0).toUpperCase() + str.slice(1);
+}
+
+/**
+ * Format bytes to human readable size
+ */
+function formatBytes(bytes) {
+ if (bytes === 0) return '0 B';
+ const k = 1024;
+ const sizes = ['B', 'KB', 'MB', 'GB'];
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
+}
+
+/**
+ * Format ANSI escape sequences for terminal output
+ */
+function formatAnsiOutput(text) {
+ // Simple ANSI to HTML conversion
+ // Remove ANSI codes for now (can be enhanced with proper library)
+ return text
+ .replace(/\x1b\[[0-9;]*m/g, '') // Remove ANSI color codes
+ .replace(/\x1b\[[0-9;]*K/g, ''); // Remove ANSI erase codes
+}
+
+/**
+ * Format unified diff for display
+ */
+function formatDiff(diff) {
+ if (!diff) return '';
+
+ const lines = diff.split('\n');
+ let html = '';
+
+ for (const line of lines) {
+ let className = 'diff-line';
+ if (line.startsWith('+') && !line.startsWith('+++')) {
+ className += ' diff-add';
+ } else if (line.startsWith('-') && !line.startsWith('---')) {
+ className += ' diff-remove';
+ } else if (line.startsWith('@@')) {
+ className += ' diff-hunk';
+ }
+
+ html += `${escapeHtml(line)}
`;
+ }
+
+ return html;
+}
+
+/**
+ * Get icon for tool type
+ */
+function getToolIcon(toolName) {
+ const icons = {
+ 'bash': 'โก',
+ 'edit': 'โ๏ธ',
+ 'write': '๐',
+ 'read': '๐',
+ 'websearch': '๐',
+ 'webfetch': '๐',
+ 'task': '๐ค',
+ 'todowrite': '๐',
+ 'grep': '๐',
+ 'glob': '๐',
+ 'list': '๐'
+ };
+ return icons[toolName] || '๐ง';
+}
+
+/**
+ * Get status icon for tool state
+ */
+function getStatusIcon(status) {
+ const icons = {
+ 'pending': 'โณ',
+ 'running': 'โก',
+ 'completed': 'โ',
+ 'error': 'โ'
+ };
+ return icons[status] || 'โณ';
+}
+
+// ============================================================
+// Public API
+// ============================================================
+
+/**
+ * Render a tool call with specialized renderer
+ * @param {Object} toolCall - Tool call object
+ * @param {string} status - Tool status (pending, running, completed, error)
+ * @returns {string} - HTML string
+ */
+function renderToolCall(toolCall, status = 'pending') {
+ const registry = window.toolRendererRegistry;
+ if (!registry) return '';
+
+ const renderer = registry.get(toolCall.name);
+ const input = toolCall.input || {};
+ const output = toolCall.output;
+ const metadata = toolCall.metadata || {};
+ const toolId = toolCall.id || `tool-${Date.now()}`;
+
+ const icon = renderer.icon;
+ const action = status === 'pending'
+ ? renderer.getAction(input)
+ : renderer.getTitle(input, output, metadata);
+
+ const body = status !== 'pending'
+ ? renderer.renderBody(input, output, metadata)
+ : '';
+
+ return `
+
+ `;
+}
+
+/**
+ * Toggle tool call expand/collapse
+ */
+function toggleToolCall(toolId) {
+ const body = document.getElementById(`tool-body-${toolId}`);
+ const header = body?.previousElementSibling;
+ const expand = header?.querySelector('.tool-expand');
+
+ if (body && header && expand) {
+ const isCollapsed = body.style.display === 'none';
+ body.style.display = isCollapsed ? 'block' : 'none';
+ expand.textContent = isCollapsed ? 'โผ' : 'โถ';
+ }
+}
+
+// ============================================================
+// Initialize
+// ============================================================
+
+// Create global registry
+window.toolRendererRegistry = new ToolRendererRegistry();
+
+// Export functions
+window.renderToolCall = renderToolCall;
+window.toggleToolCall = toggleToolCall;
+
+console.log('[ToolRenderers] Tool renderer registry initialized with ' +
+ window.toolRendererRegistry.renderers.size + ' renderers');
diff --git a/public/claude-ide/tool-rendering.css b/public/claude-ide/tool-rendering.css
new file mode 100644
index 00000000..4d712d96
--- /dev/null
+++ b/public/claude-ide/tool-rendering.css
@@ -0,0 +1,602 @@
+/**
+ * Tool Call Rendering Styles
+ * Inspired by CodeNomad's tool rendering
+ * https://github.com/NeuralNomadsAI/CodeNomad
+ */
+
+/* ============================================================
+ Tool Call Container
+ ============================================================ */
+
+.tool-call {
+ border: 1px solid #333;
+ border-radius: 8px;
+ margin: 8px 0;
+ overflow: hidden;
+ background: #1a1a1a;
+ transition: border-color 0.2s ease;
+}
+
+/* Status-specific border colors */
+.tool-call.tool-status-pending {
+ border-left: 3px solid #ffa500;
+}
+
+.tool-call.tool-status-running {
+ border-left: 3px solid #4a9eff;
+}
+
+.tool-call.tool-status-completed {
+ border-left: 3px solid #51cf66;
+}
+
+.tool-call.tool-status-error {
+ border-left: 3px solid #ff6b6b;
+}
+
+/* ============================================================
+ Tool Header (Toggle Button)
+ ============================================================ */
+
+.tool-header {
+ width: 100%;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 10px 12px;
+ background: #222;
+ border: none;
+ cursor: pointer;
+ color: #e0e0e0;
+ transition: background 0.2s ease;
+}
+
+.tool-header:hover {
+ background: #2a2a2a;
+}
+
+.tool-expand {
+ font-size: 10px;
+ transition: transform 0.2s ease;
+ min-width: 12px;
+ text-align: center;
+}
+
+.tool-icon {
+ font-size: 16px;
+ line-height: 1;
+}
+
+.tool-action {
+ flex: 1;
+ text-align: left;
+ font-size: 13px;
+ font-weight: 500;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.tool-status {
+ font-size: 14px;
+ line-height: 1;
+}
+
+/* ============================================================
+ Tool Body Content
+ ============================================================ */
+
+.tool-body {
+ padding: 12px;
+ border-top: 1px solid #333;
+ background: #1a1a1a;
+ font-size: 13px;
+ line-height: 1.5;
+ max-height: 400px;
+ overflow-y: auto;
+}
+
+/* Scrollbar styling */
+.tool-body::-webkit-scrollbar {
+ width: 8px;
+}
+
+.tool-body::-webkit-scrollbar-track {
+ background: #1a1a1a;
+}
+
+.tool-body::-webkit-scrollbar-thumb {
+ background: #444;
+ border-radius: 4px;
+}
+
+.tool-body::-webkit-scrollbar-thumb:hover {
+ background: #555;
+}
+
+/* ============================================================
+ Bash Tool
+ ============================================================ */
+
+.tool-bash {
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
+}
+
+.bash-command {
+ color: #51cf66;
+ margin-bottom: 8px;
+ font-weight: 500;
+}
+
+.bash-output {
+ color: #e0e0e0;
+ white-space: pre-wrap;
+ word-break: break-all;
+ margin-bottom: 8px;
+}
+
+.bash-exit {
+ color: #888;
+ font-size: 12px;
+ padding-top: 4px;
+ border-top: 1px solid #333;
+}
+
+/* ============================================================
+ Edit Tool
+ ============================================================ */
+
+.tool-edit {
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
+}
+
+.edit-file {
+ color: #4a9eff;
+ margin-bottom: 8px;
+ font-weight: 500;
+}
+
+.edit-stats {
+ color: #888;
+ font-size: 12px;
+ margin-bottom: 8px;
+}
+
+.edit-diff {
+ font-size: 12px;
+ line-height: 1.4;
+}
+
+/* Diff rendering */
+.diff-line {
+ padding: 2px 4px;
+ white-space: pre-wrap;
+ word-break: break-all;
+}
+
+.diff-add {
+ background: rgba(81, 207, 102, 0.15);
+ color: #51cf66;
+}
+
+.diff-remove {
+ background: rgba(255, 107, 107, 0.15);
+ color: #ff6b6b;
+}
+
+.diff-hunk {
+ color: #888;
+ background: rgba(136, 136, 136, 0.1);
+}
+
+/* ============================================================
+ Write Tool
+ ============================================================ */
+
+.tool-write {
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
+}
+
+.write-file {
+ color: #a78bfa;
+ margin-bottom: 8px;
+ font-weight: 500;
+}
+
+.write-stats {
+ color: #888;
+ font-size: 12px;
+ margin-bottom: 8px;
+}
+
+.write-preview {
+ margin-top: 8px;
+ padding: 8px;
+ background: #222;
+ border-radius: 4px;
+ font-size: 12px;
+}
+
+.write-preview pre {
+ margin: 0;
+ white-space: pre-wrap;
+ word-break: break-all;
+}
+
+/* ============================================================
+ Read Tool
+ ============================================================ */
+
+.tool-read {
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
+}
+
+.read-file {
+ color: #4a9eff;
+ margin-bottom: 8px;
+ font-weight: 500;
+}
+
+.read-preview {
+ margin-top: 8px;
+ padding: 8px;
+ background: #222;
+ border-radius: 4px;
+ font-size: 12px;
+}
+
+.read-preview pre {
+ margin: 0;
+ white-space: pre-wrap;
+ word-break: break-all;
+}
+
+.read-stats {
+ color: #888;
+ font-size: 12px;
+ margin-top: 4px;
+}
+
+/* ============================================================
+ Search Results (WebSearch, Grep)
+ ============================================================ */
+
+.tool-search-results,
+.tool-grep-results {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+.search-result,
+.grep-match {
+ padding: 8px;
+ background: #222;
+ border-radius: 4px;
+}
+
+.search-result a {
+ color: #4a9eff;
+ text-decoration: none;
+ font-weight: 500;
+}
+
+.search-result a:hover {
+ text-decoration: underline;
+}
+
+.result-snippet {
+ color: #888;
+ font-size: 12px;
+ margin-top: 4px;
+}
+
+.grep-file {
+ color: #4a9eff;
+ font-size: 12px;
+ font-weight: 500;
+}
+
+.grep-line {
+ color: #e0e0e0;
+ font-size: 12px;
+ margin-top: 2px;
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
+}
+
+.grep-stats {
+ color: #888;
+ font-size: 12px;
+ text-align: center;
+ padding: 4px;
+}
+
+/* ============================================================
+ WebFetch Tool
+ ============================================================ */
+
+.tool-fetch {
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
+}
+
+.fetch-url {
+ margin-bottom: 8px;
+}
+
+.fetch-url a {
+ color: #4a9eff;
+ text-decoration: none;
+ word-break: break-all;
+}
+
+.fetch-url a:hover {
+ text-decoration: underline;
+}
+
+.fetch-preview {
+ margin-top: 8px;
+ padding: 8px;
+ background: #222;
+ border-radius: 4px;
+ font-size: 12px;
+}
+
+.fetch-preview pre {
+ margin: 0;
+ white-space: pre-wrap;
+ word-break: break-all;
+}
+
+.fetch-stats {
+ color: #888;
+ font-size: 12px;
+ margin-top: 4px;
+}
+
+/* ============================================================
+ Task/Agent Delegation
+ ============================================================ */
+
+.tool-task-summary {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+}
+
+.task-item {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 6px 8px;
+ background: #222;
+ border-radius: 4px;
+ font-size: 12px;
+}
+
+.task-icon {
+ font-size: 14px;
+}
+
+.task-desc {
+ color: #e0e0e0;
+}
+
+.tool-task-result {
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
+ font-size: 12px;
+}
+
+.tool-task-result pre {
+ white-space: pre-wrap;
+ word-break: break-all;
+}
+
+/* ============================================================
+ Todo/Plan Tool
+ ============================================================ */
+
+.tool-todos {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+}
+
+.todo-item {
+ display: flex;
+ align-items: flex-start;
+ gap: 8px;
+ padding: 6px 8px;
+ background: #222;
+ border-radius: 4px;
+ font-size: 13px;
+}
+
+.todo-checkbox {
+ font-size: 14px;
+ line-height: 1.4;
+}
+
+.todo-text {
+ flex: 1;
+ word-break: break-word;
+}
+
+/* Todo states */
+.todo-completed .todo-text {
+ text-decoration: line-through;
+ color: #888;
+}
+
+.todo-in_progress .todo-text {
+ color: #4a9eff;
+ font-weight: 500;
+}
+
+/* ============================================================
+ Glob Tool
+ ============================================================ */
+
+.tool-glob-results {
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
+}
+
+.glob-stats {
+ color: #888;
+ font-size: 12px;
+ margin-bottom: 8px;
+}
+
+.glob-files {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+}
+
+.glob-file {
+ color: #e0e0e0;
+ font-size: 12px;
+ padding: 4px 8px;
+ background: #222;
+ border-radius: 4px;
+}
+
+.glob-more {
+ color: #888;
+ font-size: 12px;
+ text-align: center;
+ padding: 8px;
+}
+
+/* ============================================================
+ List Tool
+ ============================================================ */
+
+.tool-list-results {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+}
+
+.list-entry {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 6px 8px;
+ background: #222;
+ border-radius: 4px;
+ font-size: 13px;
+}
+
+.entry-icon {
+ font-size: 14px;
+}
+
+.entry-name {
+ color: #e0e0e0;
+}
+
+.list-more {
+ color: #888;
+ font-size: 12px;
+ text-align: center;
+ padding: 8px;
+}
+
+/* ============================================================
+ Patch Tool
+ ============================================================ */
+
+.tool-patch {
+ text-align: center;
+ padding: 12px;
+}
+
+.patch-applied {
+ color: #51cf66;
+ font-weight: 500;
+}
+
+/* ============================================================
+ Default Tool
+ ============================================================ */
+
+.tool-default {
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
+}
+
+.tool-default pre {
+ margin: 0;
+ white-space: pre-wrap;
+ word-break: break-all;
+ font-size: 12px;
+}
+
+/* ============================================================
+ Empty State
+ ============================================================ */
+
+.tool-empty {
+ color: #888;
+ font-style: italic;
+ text-align: center;
+ padding: 12px;
+}
+
+/* ============================================================
+ Responsive Design
+ ============================================================ */
+
+@media (max-width: 768px) {
+ .tool-header {
+ padding: 8px 10px;
+ }
+
+ .tool-action {
+ font-size: 12px;
+ }
+
+ .tool-body {
+ padding: 10px;
+ font-size: 12px;
+ }
+
+ .bash-command,
+ .edit-file,
+ .write-file,
+ .read-file {
+ font-size: 12px;
+ }
+}
+
+/* ============================================================
+ Animations
+ ============================================================ */
+
+@keyframes toolExpand {
+ from {
+ opacity: 0;
+ transform: translateY(-4px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+.tool-body {
+ animation: toolExpand 0.15s ease-out;
+}
+
+/* Status pulse for running tools */
+@keyframes statusPulse {
+ 0%, 100% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0.6;
+ }
+}
+
+.tool-status-running .tool-status {
+ animation: statusPulse 1.5s ease-in-out infinite;
+}