UNPKG

c9ai

Version:

Universal AI assistant with vibe-based workflows, hybrid cloud+local AI, and comprehensive tool integration

6,178 lines โ€ข 260 kB
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>c9ai - AI-Powered Development Assistant</title>
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <style>
    :root {
      --bg: #000000;
      --panel: #121212;
      --muted: #1a1a1a;
      --text: #ffffff;
      --sub: #b3b3b3;
      --primary: #7c83ff;
      --primary-ink: #ffffff;
      --bubble: #1a1a1a;
      --user: #7c83ff;
      --danger: #ff4d6d;
      --ok: #2ecc71;
      --border: #333333;
      --sidebar: #000000;
    }
    
    /* Light mode - clean and minimal like your test page */
    [data-theme="light"] {
      --bg: #ffffff;
      --panel: #ffffff;
      --muted: #f5f5f5;
      --text: #000000;
      --sub: #666666;
      --primary: #7c83ff;
      --primary-ink: #ffffff;
      --bubble: #f9f9f9;
      --user: #7c83ff;
      --danger: #ff4d6d;
      --ok: #2ecc71;
      --border: #dddddd;
      --sidebar: #fafafa;
    }
    
    @keyframes pulse {
      0%, 100% { opacity: 1; }
      50% { opacity: 0.5; }
    }
    
    * { box-sizing: border-box; }
    html, body { height: 100%; margin: 0; padding: 0; }
    body {
      font: 14px/1.5 ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, Helvetica Neue, Arial, "Apple Color Emoji", "Segoe UI Emoji";
      color: var(--text);
      background: var(--bg);
      display: flex;
      min-height: 100vh;
      max-height: 100vh;
      overflow: hidden;
    }
    
    /* Sidebar Navigation */
    .sidebar {
      width: 280px;
      background: var(--sidebar);
      border-right: 1px solid var(--border);
      display: flex;
      flex-direction: column;
      transition: transform 0.3s ease;
    }
    .sidebar.collapsed {
      transform: translateX(-100%);
    }
    
    .sidebar-header {
      padding: 16px;
      border-bottom: 1px solid var(--border);
      display: flex;
      align-items: center;
      gap: 12px;
    }
    
    .logo {
      font-size: 18px;
      font-weight: 700;
      background: linear-gradient(45deg, var(--primary), #b794f6);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
      background-clip: text;
    }
    
    .nav-section {
      padding: 16px 12px 8px 12px;
    }
    
    .nav-section.conversations {
      flex: 1;
      display: flex;
      flex-direction: column;
      min-height: 0;
    }
    .nav-section-title {
      font-size: 12px;
      font-weight: 600;
      color: var(--sub);
      text-transform: uppercase;
      letter-spacing: 0.5px;
      margin-bottom: 8px;
    }
    
    .nav-item {
      display: flex;
      align-items: center;
      gap: 8px;
      padding: 8px 12px;
      border-radius: 8px;
      cursor: pointer;
      transition: all 0.2s;
      margin-bottom: 4px;
      font-size: 13px;
    }
    .nav-item:hover {
      background: var(--muted);
    }
    .nav-item.active {
      background: var(--primary);
      color: var(--primary-ink);
    }
    
    .conversations-list {
      flex: 1;
      min-height: 0;  /* critical for flex scrolling */
      overflow-y: auto;
      padding: 0 12px;
    }
    
    .conversation-item {
      display: flex;
      flex-direction: column;
      padding: 8px 12px;
      border-radius: 8px;
      cursor: pointer;
      transition: all 0.2s;
      margin-bottom: 4px;
      border: 1px solid transparent;
    }
    .conversation-item:hover {
      background: var(--muted);
      border-color: var(--border);
    }
    .conversation-item.active {
      background: var(--bubble);
      border-color: var(--primary);
    }
    
    .conversation-title {
      font-size: 13px;
      font-weight: 500;
      margin-bottom: 2px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .conversation-preview {
      font-size: 11px;
      color: var(--sub);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .conversation-time {
      font-size: 10px;
      color: var(--sub);
      margin-top: 4px;
    }
    
    /* Main Content Area */
    .main-content {
      flex: 1;
      display: flex;
      flex-direction: column;
      overflow: hidden;
      /* allow inner flex children to size/scroll properly */
      min-height: 0;
    }
    
    .main-header {
      padding: 16px 20px;
      border-bottom: 1px solid var(--border);
      display: flex;
      align-items: center;
      justify-content: space-between;
      background: var(--panel);
    }
    
    .view-content {
      flex: 1;
      display: flex;
      flex-direction: column;
      overflow-y: auto;
      min-height: 0;
    }
    
    .header-left {
      display: flex;
      align-items: center;
      gap: 12px;
    }
    
    .header-right {
      display: flex;
      align-items: center;
      gap: 8px;
    }
    
    .provider-switcher {
      display: flex;
      background: var(--muted);
      border-radius: 8px;
      padding: 2px;
      gap: 2px;
    }
    
    .pill {
      padding: 6px 12px;
      border: none;
      background: var(--muted);
      color: var(--sub);
      border-radius: 20px;
      cursor: pointer;
      font-size: 12px;
      font-weight: 500;
      transition: all 0.3s ease;
      border: 1px solid var(--border);
    }
    .pill.active {
      background: #ff6b35;
      color: white;
      border-color: #ff6b35;
      box-shadow: 0 0 0 2px rgba(255, 107, 53, 0.3), 0 2px 8px rgba(255, 107, 53, 0.2);
      font-weight: 600;
      transform: translateY(-1px);
    }
    .pill:hover:not(.active) {
      background: var(--panel);
      border-color: var(--primary);
      color: var(--text);
      transform: translateY(-0.5px);
    }
    
    /* Chat Area */
    .chat-container {
      flex: 1;
      display: flex;
      flex-direction: column;
      min-height: 0;
      position: relative;
      height: 100%;
    }
    
    .chat-messages {
      flex: 1;
      min-height: 0;
      overflow-y: auto;
      overflow-x: hidden;
      padding: 20px;
      display: flex;
      flex-direction: column;
      gap: 16px;
    }
    
    .message {
      display: flex;
      align-items: flex-start;
      gap: 12px;
      max-width: 85%;
    }
    
    .message.user {
      align-self: flex-end;
      flex-direction: row-reverse;
    }
    
    .message-avatar {
      width: 32px;
      height: 32px;
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 14px;
      font-weight: 600;
      flex-shrink: 0;
    }
    .message.user .message-avatar {
      background: var(--user);
      color: var(--primary-ink);
    }
    .message.assistant .message-avatar {
      background: var(--bubble);
      color: var(--text);
    }
    
    .message-content {
      background: var(--bubble);
      padding: 12px 16px;
      border-radius: 16px;
      border: 1px solid var(--border);
      box-shadow: 0 2px 8px rgba(0,0,0,0.1);
      white-space: pre-wrap;
      word-break: break-word;
    }
    .message-content li { list-style: inside disc; margin-left: 1rem; margin-bottom: 6px; }
    /* RSS card + thumbnail styles */
    .message-content .rss-item { background: var(--bubble); border: 1px solid var(--border); border-radius: 12px; padding: 12px; margin: 12px 0; }
    .message-content .rss-thumb { width: 100%; max-width: 100%; height: auto; border-radius: 10px; display: block; margin: 6px 0 10px 0; object-fit: cover; }
    .message-content .rss-title { font-weight: 700; margin: 6px 0 4px 0; color: var(--text); }
    .message-content .rss-desc { color: var(--text); opacity: 0.9; line-height: 1.5; }
    .message-content .rss-meta-line { margin: 2px 0 8px 0; font-size: 13px; color: var(--sub); }
    .message-content .rss-meta { margin-top: 8px; font-size: 13px; color: var(--sub); display: flex; gap: 10px; align-items: center; }
    .message-content .rss-meta a.pill-read { text-decoration: none; border: 1px solid var(--border); padding: 4px 10px; border-radius: 999px; background: var(--muted); color: var(--text); }
    .message.user .message-content {
      background: var(--user);
      color: var(--primary-ink);
    }
    
    .message-time {
      font-size: 10px;
      color: var(--sub);
      margin-top: 4px;
    }
    
    /* Input Area */
    .chat-input-container {
      position: sticky;
      bottom: 0;
      padding: 12px 20px;
      border-top: 1px solid var(--border);
      background: var(--panel);
      flex-shrink: 0;
      z-index: 10;
      margin-top: auto;
    }

    /* Small footer bar pinned at the very bottom */
    .app-footer {
      background: var(--bg);
      color: var(--sub);
      font-size: 11px;
      border-top: 1px solid var(--border);
      padding: 6px 12px;
      display: flex;
      align-items: center;
      justify-content: space-between;
      flex-shrink: 0;
    }
    
    /* Debug Panel Styles */
    .debug-panel {
      position: fixed;
      top: 20px;
      right: 20px;
      width: 400px;
      max-height: 600px;
      background: var(--panel);
      border: 1px solid var(--border);
      border-radius: 8px;
      box-shadow: 0 4px 20px rgba(0,0,0,0.3);
      z-index: 1000;
      display: none;
      flex-direction: column;
    }
    
    .debug-header {
      padding: 12px 16px;
      background: var(--muted);
      border-bottom: 1px solid var(--border);
      display: flex;
      align-items: center;
      justify-content: space-between;
      border-radius: 8px 8px 0 0;
    }
    
    .debug-title {
      font-weight: 600;
      font-size: 14px;
      color: var(--text);
    }
    
    .debug-close {
      background: none;
      border: none;
      color: var(--sub);
      cursor: pointer;
      padding: 4px;
      border-radius: 4px;
      font-size: 16px;
    }
    
    .debug-close:hover {
      background: var(--border);
      color: var(--text);
    }
    
    .debug-content {
      flex: 1;
      overflow-y: auto;
      padding: 12px;
      font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
      font-size: 12px;
      line-height: 1.4;
    }
    
    .debug-entry {
      margin-bottom: 8px;
      padding: 6px 8px;
      border-radius: 4px;
      border-left: 3px solid var(--border);
    }
    
    .debug-entry.info { 
      background: rgba(124, 131, 255, 0.1); 
      border-left-color: var(--primary);
    }
    .debug-entry.success { 
      background: rgba(46, 204, 113, 0.1); 
      border-left-color: var(--ok);
    }
    .debug-entry.warning { 
      background: rgba(255, 193, 7, 0.1); 
      border-left-color: #ffc107;
    }
    .debug-entry.error { 
      background: rgba(255, 77, 109, 0.1); 
      border-left-color: var(--danger);
    }
    .debug-entry.tool { 
      background: rgba(156, 39, 176, 0.1); 
      border-left-color: #9c27b0;
    }
    
    .debug-timestamp {
      color: var(--sub);
      font-size: 10px;
      margin-right: 8px;
    }
    
    .debug-icon {
      margin-right: 6px;
    }
    
    .debug-message {
      color: var(--text);
    }
    
    .debug-toggle {
      position: fixed;
      bottom: 20px;
      left: 20px;
      right: auto;
      width: 50px;
      height: 50px;
      border-radius: 50%;
      background: var(--primary);
      color: white;
      border: none;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 18px;
      box-shadow: 0 2px 10px rgba(0,0,0,0.3);
      z-index: 999;
      transition: all 0.3s ease;
    }
    
    .debug-toggle:hover {
      transform: scale(1.1);
      box-shadow: 0 4px 20px rgba(0,0,0,0.4);
    }
    
    .debug-toggle.active {
      background: var(--ok);
    }
    
    /* Progress indicator for executive requests */
    .progress-bar {
      height: 3px;
      background: var(--border);
      border-radius: 2px;
      overflow: hidden;
      margin: 8px 0;
    }
    
    .progress-fill {
      height: 100%;
      background: var(--primary);
      transition: width 0.3s ease;
      border-radius: 2px;
    }

    /* Mobile responsive adjustments */
    @media (max-width: 768px) {
      .sidebar {
        transform: translateX(-100%);
      }
      
      .debug-panel {
        width: 300px;
        right: 10px;
        top: 10px;
        max-height: 400px;
      }
      
      .debug-toggle {
        width: 45px;
        height: 45px;
        bottom: 15px;
        right: 15px;
      }
      .sidebar.show {
        transform: translateX(0);
      }
    }
    
    .chat-input-wrapper {
      display: flex;
      align-items: center;
      gap: 8px;
      max-width: 1000px;
      margin: 0 auto;
    }
    
    .chat-input {
      flex: 1;
      background: var(--muted);
      border: 1px solid var(--border);
      border-radius: 12px;
      padding: 10px 14px;
      color: var(--text);
      font-family: inherit;
      font-size: 14px;
      resize: none;
      min-height: 36px;
      max-height: 80px;
      line-height: 1.4;
    }
    .chat-input:focus {
      outline: none;
      border-color: var(--primary);
    }
    .chat-input::placeholder {
      color: var(--sub);
    }
    
    .input-actions {
      display: flex;
      align-items: center;
      gap: 6px;
      flex-wrap: wrap;
    }
    
    .btn {
      background: var(--primary);
      color: white;
      border: none;
      padding: 6px 12px;
      border-radius: 6px;
      cursor: pointer;
      font-weight: 500;
      font-size: 12px;
      transition: all 0.2s;
      white-space: nowrap;
    }
    .btn:hover {
      background: #6c7ce0;
      transform: translateY(-1px);
    }
    .btn:disabled {
      opacity: 0.6;
      cursor: not-allowed;
      transform: none;
    }
    .btn.secondary {
      background: var(--muted);
      color: var(--text);
      border: 1px solid var(--border);
    }
    .btn.secondary:hover {
      background: var(--border);
    }
    .btn.ghost {
      background: transparent;
      border: 1px solid var(--border);
    }
    
    /* Mobile Toggle */
    .mobile-toggle {
      display: none;
      background: none;
      border: none;
      color: var(--text);
      cursor: pointer;
      font-size: 18px;
    }
    
    /* Welcome Screen */
    .welcome-screen {
      flex: 1;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      padding: 40px;
      text-align: center;
    }
    
    .welcome-title {
      font-size: 28px;
      font-weight: 700;
      margin-bottom: 12px;
      background: linear-gradient(45deg, var(--primary), #b794f6);
      -webkit-background-clip: text;
      -webkit-text-fill-color: transparent;
      background-clip: text;
    }
    
    .welcome-subtitle {
      font-size: 16px;
      color: var(--sub);
      margin-bottom: 32px;
      max-width: 500px;
    }
    
    .quick-actions {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
      gap: 16px;
      max-width: 600px;
      width: 100%;
    }
    
    .quick-action {
      background: var(--panel);
      border: 1px solid var(--border);
      border-radius: 12px;
      padding: 20px;
      cursor: pointer;
      transition: all 0.2s;
      text-align: center;
    }
    .quick-action:hover {
      border-color: var(--primary);
      transform: translateY(-2px);
    }
    
    .quick-action-icon {
      font-size: 24px;
      margin-bottom: 8px;
    }
    .quick-action-title {
      font-weight: 600;
      margin-bottom: 4px;
    }
    .quick-action-desc {
      font-size: 12px;
      color: var(--sub);
    }
    
    /* Modal Styles */
    .modal {
      position: fixed;
      inset: 0;
      background: rgba(0, 0, 0, 0.5);
      display: none;
      align-items: center;
      justify-content: center;
      z-index: 1000;
      padding: 20px;
    }
    
    .modal-content {
      background: var(--panel);
      border: 1px solid var(--border);
      border-radius: 16px;
      width: 100%;
      max-width: 500px;
      max-height: 80vh;
      overflow-y: auto;
    }
    
    .modal-header {
      padding: 20px;
      border-bottom: 1px solid var(--border);
      display: flex;
      align-items: center;
      justify-content: space-between;
    }
    
    .modal-body {
      padding: 20px;
    }
    
    .form-group {
      margin-bottom: 16px;
    }
    
    .form-label {
      display: block;
      font-size: 13px;
      font-weight: 600;
      color: var(--text);
      margin-bottom: 6px;
    }
    
    .form-input, .form-select {
      width: 100%;
      background: var(--muted);
      color: var(--text);
      border: 1px solid var(--border);
      border-radius: 8px;
      padding: 10px 12px;
      font-family: inherit;
      font-size: 14px;
    }
    .form-input:focus, .form-select:focus {
      outline: none;
      border-color: var(--primary);
    }
    
    .form-hint {
      font-size: 12px;
      color: var(--sub);
      margin-top: 4px;
    }
    
    /* Status indicator */
    .status-indicator {
      display: inline-flex;
      align-items: center;
      gap: 4px;
      font-size: 11px;
      color: var(--sub);
      margin-left: 8px;
    }
    .status-dot {
      width: 6px;
      height: 6px;
      border-radius: 50%;
      background: var(--ok);
    }
    .status-dot.error { background: var(--danger); }
    .status-dot.loading { 
      background: var(--primary);
      animation: pulse 1.5s infinite;
    }
    
    @keyframes pulse {
      0%, 100% { opacity: 1; }
      50% { opacity: 0.5; }
    }
    
    /* Responsive */
    @media (max-width: 768px) {
      .sidebar {
        position: absolute;
        left: 0;
        top: 0;
        height: 100%;
        z-index: 100;
      }
      .mobile-toggle {
        display: block;
      }
      .provider-switcher {
        display: none;
      }
    }
    
    /* Code action buttons styling */
    .code-actions {
      display: flex;
      gap: 8px;
      margin-top: 12px;
      padding-top: 12px;
      border-top: 1px solid var(--border);
      flex-wrap: wrap;
    }
    
    .save-code-btn, .run-code-btn, .copy-code-btn {
      background: var(--muted);
      color: var(--text);
      border: 1px solid var(--border);
      border-radius: 6px;
      padding: 6px 12px;
      font-size: 12px;
      cursor: pointer;
      transition: all 0.2s ease;
      display: flex;
      align-items: center;
      gap: 4px;
      white-space: nowrap;
    }
    
    .save-code-btn:hover {
      background: var(--primary);
      color: var(--primary-ink);
      border-color: var(--primary);
      transform: translateY(-1px);
    }
    
    .run-code-btn:hover {
      background: var(--ok);
      color: white;
      border-color: var(--ok);
      transform: translateY(-1px);
    }
    
    .copy-code-btn:hover {
      background: var(--border);
      transform: translateY(-1px);
    }
    
    .save-code-btn:active, .run-code-btn:active, .copy-code-btn:active {
      transform: translateY(0);
    }
    
    /* Theme toggle button */
    .theme-toggle {
      position: fixed;
      top: 20px;
      right: 20px;
      width: 50px;
      height: 28px;
      background: var(--muted);
      border: 1px solid var(--border);
      border-radius: 20px;
      cursor: pointer;
      display: flex;
      align-items: center;
      padding: 2px;
      z-index: 1000;
      transition: all 0.3s ease;
    }
    
    .theme-toggle:hover {
      background: var(--border);
    }
    
    .theme-toggle-slider {
      width: 24px;
      height: 24px;
      background: var(--primary);
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 12px;
      transition: all 0.3s ease;
      color: white;
    }
    
    [data-theme="light"] .theme-toggle-slider {
      transform: translateX(22px);
    }
    /* Make header links readable in both themes */
    .message .message-content h1 a,
    .message .message-content h2 a,
    .message .message-content h3 a {
      color: var(--text);
      text-decoration: none;
    }
    .message .message-content h1 a:hover,
    .message .message-content h2 a:hover,
    .message .message-content h3 a:hover {
      text-decoration: underline;
    }

    
    /* Smooth transitions for theme switching */
    body, .sidebar, .main-content, .chat-messages, .chat-input, .btn, .nav-item, .debug-panel {
      transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
    }
  </style>
  <style>
    /* Context menu */
    .context-menu { position: fixed; background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 6px 20px rgba(0,0,0,0.4); display: none; z-index: 1200; min-width: 160px; }
    .context-menu .item { padding: 8px 12px; cursor: pointer; font-size: 13px; border-bottom: 1px solid var(--border); }
    .context-menu .item:last-child { border-bottom: none; }
    .context-menu .item:hover { background: var(--muted); }
  </style>
</head>
<body>
  <style>
    /* Floating chat panel */
    .float-chat-btn { position: fixed; right: 20px; bottom: 20px; z-index: 1100; }
    .float-chat-panel { position: fixed; right: 20px; bottom: 70px; width: 360px; max-height: 60vh; background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.4); display: none; flex-direction: column; overflow: hidden; z-index: 1100; }
    .float-chat-panel.expanded { left: 20px; right: 20px; top: 70px; bottom: 70px; width: auto; max-height: none; }
    .float-chat-header { padding: 10px 12px; border-bottom: 1px solid var(--border); display:flex; justify-content: space-between; align-items:center; font-weight: 600; gap: 8px; }
    .float-chat-header .actions { display:flex; gap:8px; }
    .float-chat-messages { padding: 10px 12px; overflow-y: auto; flex: 1; font-size: 13px; }
    .float-chat-input { display:flex; gap:6px; padding: 8px; border-top:1px solid var(--border); }
    .float-chat-input input { flex:1; }
    .bubble { margin: 6px 0; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--bubble); }
    .bubble.user { background: var(--muted); }
  </style>
  <!-- Theme Toggle Button -->
  <div class="theme-toggle" onclick="toggleTheme()" title="Toggle light/dark mode">
    <div class="theme-toggle-slider">๐ŸŒ™</div>
  </div>

  <!-- Sidebar -->
  <div class="sidebar" id="sidebar">
    <div class="sidebar-header">
      <div class="logo">๐Ÿค– c9ai</div>
      <div class="status-indicator">
        <div class="status-dot" id="statusDot"></div>
        <span id="statusText">Ready</span>
      </div>
    </div>
    
    <div class="nav-section">
      <div class="nav-section-title">Navigation</div>
      <div class="nav-item active" data-view="chat">
        <span>๐Ÿ’ฌ</span> Smart Chat
      </div>
            <div class="nav-item" data-view="help">
        <span>โ“</span> Help
      </div>
      <div class="nav-item" data-view="settings">
        <span>โš™๏ธ</span> Settings
      </div>
      <div class="nav-item" data-view="system">
        <span>๐Ÿ› ๏ธ</span> System
      </div>
      <div class="nav-item" data-view="calculators">
        <span>๐Ÿงฎ</span> Calculators
      </div>
      <div class="nav-item" data-view="workflows">
        <span>๐Ÿ”€</span> Workflows
      </div>
      <div class="nav-item" data-view="terminal">
        <span>๐Ÿ’ป</span> Terminal
      </div>
    </div>
    
    <div class="nav-section conversations">
      <div class="nav-section-title">Recent Conversations</div>
      <div class="conversations-list" id="conversationsList">
        <!-- Conversations will be populated here -->
      </div>
    </div>
    
    <div class="nav-section">
      <button class="btn secondary" id="newConversationBtn" style="width: 100%;" onclick="startNewConversation()">
        โž• New Conversation
      </button>
    </div>
  </div>
  
  <!-- Main Content -->
  <div class="main-content">
    <div class="main-header">
      <div class="header-left">
        <button class="mobile-toggle" onclick="toggleSidebar()">โ˜ฐ</button>
        <h2 id="viewTitle">AI Chat</h2>
      </div>
      <div class="header-right"></div>
    </div>
    
    <!-- Smart Chat View -->
    <div class="view-content" id="chatView">
      <div class="chat-container">
        <div class="chat-messages" id="chatMessages">
          <div class="welcome-screen" id="welcomeScreen">
            <h1 class="welcome-title">Welcome to Smart Chat</h1>
            <p class="welcome-subtitle">Enhanced execution environment with XML-Lisp transpiler. Create functions, run calculations, and build your personal function library.</p>
            <div class="quick-actions">
              <div class="quick-action" onclick="startNewConversation()" style="border: 2px solid var(--primary); background: var(--primary); color: var(--primary-ink);">
                <div class="quick-action-icon">๐Ÿ’ฌ</div>
                <div class="quick-action-title">Start Chatting</div>
                <div class="quick-action-desc">Begin a new conversation</div>
              </div>
              <div class="quick-action" onclick="showView('calculators')">
                <div class="quick-action-icon">๐Ÿงฎ</div>
                <div class="quick-action-title">Open Calculators</div>
                <div class="quick-action-desc">Deterministic business calculators</div>
              </div>
              <div class="quick-action" onclick="showView('workflows')">
                <div class="quick-action-icon">๐Ÿ”€</div>
                <div class="quick-action-title">Open Workflows</div>
                <div class="quick-action-desc">Run or build task pipelines</div>
              </div>
              <div class="quick-action" onclick="loadQuickAction('Help me write a professional email')">
                <div class="quick-action-icon">โœ‰๏ธ</div>
                <div class="quick-action-title">Write Email</div>
                <div class="quick-action-desc">Craft professional messages</div>
              </div>
              <div class="quick-action" onclick="loadQuickAction('Create a social media post')">
                <div class="quick-action-icon">๐Ÿ“ฑ</div>
                <div class="quick-action-title">Social Content</div>
                <div class="quick-action-desc">Generate engaging posts</div>
              </div>
              <div class="quick-action" onclick="loadQuickAction('Plan my project or task')">
                <div class="quick-action-icon">๐Ÿ“‹</div>
                <div class="quick-action-title">Project Planning</div>
                <div class="quick-action-desc">Organize and break down tasks</div>
              </div>
              <div class="quick-action" onclick="loadQuickAction('Help me learn something new')">
                <div class="quick-action-icon">๐ŸŽ“</div>
                <div class="quick-action-title">Learn & Explore</div>
                <div class="quick-action-desc">Get explanations and tutorials</div>
              </div>
            </div>
          </div>
        </div>
        <div class="chat-input-container">
          <div class="chat-input-wrapper">
            <textarea 
              class="chat-input" 
              id="chatInput" 
              placeholder="Chat naturally or use @calc, @todo, @email, @search for tasks... (Ctrl+Enter to send)"
              rows="1"
            ></textarea>
            <div class="input-actions">
              <button class="btn" id="sendBtn" onclick="sendMessage()">Send</button>
              <button class="btn secondary" onclick="switchToAgent()">Agent</button>
              <label style="display:flex;gap:4px;align-items:center;font-size:11px;color:var(--sub)">
                <input id="toAgent" type="checkbox" />
                <span>Tools</span>
              </label>
            </div>
          </div>
        </div>
      </div>
    </div>
    
    <!-- Agent View -->
    <div class="view-content" id="agentView" style="display: none;">
      <div style="padding: 20px; max-width: 1000px; margin: 0 auto; min-height: 100%; box-sizing: border-box;">
        <h2 style="margin-bottom: 20px;">๐Ÿš€ Agentic Tools</h2>
        
        <div style="background: var(--bubble); padding: 20px; border-radius: 12px; margin-bottom: 24px; border: 1px solid var(--border);">
          <h3 style="margin-top: 0; color: var(--primary);">๐ŸŽฏ Task-Focused AI Interface</h3>
          <p style="margin-bottom: 16px; line-height: 1.6;">
            The Agentic Tools interface is designed for complex task execution with local AI models. 
            It provides a dedicated environment for tool-based operations, file management, and automation.
          </p>
          <div style="background: var(--muted); padding: 12px; border-radius: 6px; font-size: 13px; color: var(--sub);">
            <strong>โœจ Key Features:</strong> Local AI execution โ€ข Tool-based commands โ€ข Task persistence โ€ข File operations โ€ข API integrations
          </div>
        </div>

        <div class="form-group">
          <h3>๐ŸŒ Launch Agentic Interface</h3>
          <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 24px;">
            
            <div style="background: var(--panel); border: 1px solid var(--border); border-radius: 8px; padding: 16px;">
              <h4 style="margin-top: 0; margin-bottom: 8px;">๐Ÿ› ๏ธ Main Agentic Tools</h4>
              <p style="font-size: 12px; color: var(--sub); margin-bottom: 12px;">
                Dedicated interface for task execution and tool operations
              </p>
              <button class="btn primary" onclick="window.open('http://localhost:8787', '_blank')" style="width: 100%;">
                Launch Agentic UI (Port 8787)
              </button>
            </div>

            <div style="background: var(--panel); border: 1px solid var(--border); border-radius: 8px; padding: 16px;">
              <h4 style="margin-top: 0; margin-bottom: 8px;">โšก Quick Test Interface</h4>
              <p style="font-size: 12px; color: var(--sub); margin-bottom: 12px;">
                Current embedded agent interface for testing
              </p>
              <button class="btn secondary" onclick="showEmbeddedAgent()" style="width: 100%;">
                Show Embedded Agent
              </button>
            </div>
          </div>
        </div>

        <div class="form-group">
          <h3>๐Ÿ”ง Configuration</h3>
          <div style="background: var(--muted); padding: 15px; border-radius: 8px;">
            <p style="margin: 0 0 8px 0; font-size: 13px;">
              <strong>Provider Settings:</strong> AI provider selection is managed in the main chat interface.
            </p>
            <p style="margin: 0; font-size: 13px; color: var(--sub);">
              <strong>Communication:</strong> The agentic tools interface will communicate with this hub via shared task files.
            </p>
          </div>
        </div>

        <div id="embeddedAgentContainer" style="display: none; margin-top: 24px;">
          <h3>Embedded Agent Interface</h3>
          <div style="border: 1px solid var(--border); border-radius: 8px; height: 500px;">
            <iframe id="embeddedAgentFrame" src="" style="width: 100%; height: 100%; border: none; border-radius: 8px;"></iframe>
          </div>
          <button class="btn secondary" onclick="hideEmbeddedAgent()" style="margin-top: 8px;">
            Hide Embedded Agent
          </button>
        </div>
      </div>
    </div>
    
    <!-- CLI Access View -->
    <div class="view-content" id="cliView" style="display: none;">
      <div style="padding: 20px; max-width: 1000px; margin: 0 auto; min-height: 100%; box-sizing: border-box;">
        <h2 style="margin-bottom: 20px;">โŒจ๏ธ CLI Access</h2>
        
        <div class="form-group">
          <h3>Available CLI Commands</h3>
          <div style="background: var(--muted); padding: 15px; border-radius: 8px; margin-bottom: 20px;">
            <div style="font-family: monospace; font-size: 14px; line-height: 1.6;">
              <div style="margin-bottom: 8px;"><strong># Interactive Mode</strong></div>
              <div style="color: var(--primary);">c9ai</div>
              <div style="margin: 8px 0; opacity: 0.7;"># Launches interactive shell with your current provider settings</div>
              
              <div style="margin: 16px 0 8px 0;"><strong># Direct Agent Commands</strong></div>
              <div style="color: var(--primary);">c9ai agent "list files in current directory"</div>
              <div style="color: var(--primary);">c9ai-agent "create a Python script for fibonacci"</div>
              <div style="margin: 8px 0; opacity: 0.7;"># Execute specific tasks with full tool access</div>
              
              <div style="margin: 16px 0 8px 0;"><strong># Provider Management</strong></div>
              <div style="color: var(--primary);">c9ai models list</div>
              <div style="color: var(--primary);">c9ai switch claude-hybrid</div>
              <div style="margin: 8px 0; opacity: 0.7;"># List and switch between providers</div>
              
              <div style="margin: 16px 0 8px 0;"><strong># Local Stack</strong></div>
              <div style="color: var(--primary);">c9ai stack</div>
              <div style="color: var(--primary);">c9ai stack --model ./my-model.gguf --port 8081</div>
              <div style="margin: 8px 0; opacity: 0.7;"># Start local llama.cpp server + Agent API</div>
            </div>
          </div>
        </div>
        
        <div class="form-group">
          <h3>Quick CLI Launcher</h3>
          <p style="margin-bottom: 15px; color: var(--sub);">Launch CLI with your current UI provider settings</p>
          
          <div style="display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 20px;">
            <button class="btn" onclick="launchCLI('interactive')" style="display: flex; align-items: center; gap: 8px;">
              <span>๐Ÿ–ฅ๏ธ</span> Interactive Mode
            </button>
            <button class="btn" onclick="launchCLI('agent')" style="display: flex; align-items: center; gap: 8px;">
              <span>๐Ÿค–</span> Agent Mode
            </button>
            <button class="btn" onclick="launchCLI('models')" style="display: flex; align-items: center; gap: 8px;">
              <span>๐Ÿ“‹</span> List Models
            </button>
            <button class="btn" onclick="launchCLI('stack')" style="display: flex; align-items: center; gap: 8px;">
              <span>๐Ÿš€</span> Start Stack
            </button>
          </div>
        </div>
        
        <div class="form-group">
          <h3>CLI Installation</h3>
          <p style="margin-bottom: 15px; color: var(--sub);">Install C9AI CLI globally for system-wide access</p>
          
          <div style="background: var(--muted); padding: 15px; border-radius: 8px;">
            <div style="font-family: monospace; font-size: 14px; line-height: 1.6;">
              <div style="margin-bottom: 8px;"><strong># Install globally</strong></div>
              <div style="color: var(--primary);">npm install -g .</div>
              <div style="margin: 8px 0; opacity: 0.7;"># Run from project directory</div>
              
              <div style="margin: 16px 0 8px 0;"><strong># Or use scripts</strong></div>
              <div style="color: var(--primary);">./install.sh</div>
              <div style="color: var(--primary);">install-windows.bat</div>
              <div style="margin: 8px 0; opacity: 0.7;"># Platform-specific installers</div>
            </div>
          </div>
        </div>
        
        <div class="form-group">
          <h3>CLI Sessions</h3>
          <p style="margin-bottom: 15px; color: var(--sub);">Track and view CLI command history</p>
          
          <div id="cliSessions" style="background: var(--muted); padding: 15px; border-radius: 8px; min-height: 200px;">
            <div style="text-align: center; color: var(--sub); padding: 40px;">
              No CLI sessions tracked yet. CLI sessions will appear here once you start using the CLI.
            </div>
          </div>
          
          <div style="margin-top: 15px; display: flex; gap: 12px;">
            <button class="btn secondary" onclick="refreshCLISessions()">๐Ÿ”„ Refresh Sessions</button>
            <button class="btn secondary" onclick="clearCLISessions()">๐Ÿ—‘๏ธ Clear History</button>
          </div>
        </div>
      </div>
    </div>
    
    <!-- Tools View -->
    <div class="view-content" id="toolsView" style="display: none;">
      <div style="padding: 20px; max-width: 1200px; margin: 0 auto; min-height: 100%; box-sizing: border-box;">
        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
          <h2 style="margin: 0;">๐Ÿ”ง Tool Package Manager</h2>
          <div style="display: flex; gap: 12px;">
            <button class="btn secondary" onclick="refreshToolData()">๐Ÿ”„ Refresh</button>
            <button class="btn secondary" onclick="showBatchInstall()">๐Ÿ“ฆ Batch Install</button>
          </div>
        </div>
        
        <!-- Tool Source Tabs -->
        <div style="display: flex; gap: 8px; margin-bottom: 20px;">
          <button class="btn pill active" data-source="curated" onclick="switchToolSource('curated')">๐Ÿ“š Curated Tools</button>
          <button class="btn pill" data-source="packages" onclick="switchToolSource('packages')">๐Ÿ“ฆ System Packages</button>
          <button class="btn pill" data-source="installed" onclick="switchToolSource('installed')">โœ… Installed</button>
        </div>
        
        <!-- Tool Statistics -->
        <div id="toolStats" style="display: flex; gap: 15px; margin-bottom: 25px;">
          <div style="background: var(--panel); padding: 15px; border-radius: 8px; flex: 1; border: 1px solid var(--border);">
            <div style="font-size: 24px; font-weight: bold; color: var(--primary);" id="totalTools">-</div>
            <div style="font-size: 12px; color: var(--sub);">Total Tools</div>
          </div>
          <div style="background: var(--panel); padding: 15px; border-radius: 8px; flex: 1; border: 1px solid var(--border);">
            <div style="font-size: 24px; font-weight: bold; color: var(--ok);" id="installedTools">-</div>
            <div style="font-size: 12px; color: var(--sub);">Installed</div>
          </div>
          <div style="background: var(--panel); padding: 15px; border-radius: 8px; flex: 1; border: 1px solid var(--border);">
            <div style="font-size: 24px; font-weight: bold; color: var(--primary);" id="availableTools">-</div>
            <div style="font-size: 12px; color: var(--sub);">Available</div>
          </div>
          <div style="background: var(--panel); padding: 15px; border-radius: 8px; flex: 1; border: 1px solid var(--border);">
            <div style="font-size: 24px; font-weight: bold; color: var(--sub);" id="builtinTools">-</div>
            <div style="font-size: 12px; color: var(--sub);">Built-in</div>
          </div>
        </div>

        <!-- Category Filter -->
        <div style="margin-bottom: 20px;">
          <div style="display: flex; gap: 8px; flex-wrap: wrap;" id="categoryFilters">
            <button class="btn pill active" data-category="all">All Tools</button>
            <button class="btn pill" data-category="available">Available</button>
            <button class="btn pill" data-category="installed">Installed</button>
          </div>
        </div>

        <!-- Package Search (visible when packages tab is active) -->
        <div id="packageSearch" style="display: none; margin-bottom: 25px;">
          <div style="display: flex; gap: 12px; margin-bottom: 15px;">
            <div style="flex: 1; position: relative;">
              <input 
                type="text" 
                id="packageSearchInput" 
                placeholder="Search for packages (e.g., pandoc, ffmpeg, python packages...)" 
                style="width: 100%; padding: 12px 16px; border: 1px solid var(--border); border-radius: 6px; background: var(--panel); color: var(--text);"
                onkeydown="if(event.key === 'Enter') searchPackages()"
              />
            </div>
            <button class="btn primary" onclick="searchPackages()">๐Ÿ” Search</button>
          </div>
          
          <!-- Package Manager Status -->
          <div id="packageManagerStatus" style="display: flex; gap: 10px; margin-bottom: 15px; flex-wrap: wrap;">
            Loading package managers...
          </div>
          
          <div id="searchResults" style="display: none;">
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
              <h3 style="margin: 0;">Search Results</h3>
              <div id="searchResultsCount" style="color: var(--sub); font-size: 14px;"></div>
            </div>
            <div id="packageResults" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); gap: 15px;">
              <!-- Search results will be populated here -->
            </div>
          </div>
        </div>

        <!-- Tool Grid -->
        <div id="toolGrid" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); gap: 20px;">
          <!-- Tools will be populated here -->
          <div style="grid-column: 1 / -1; text-align: center; padding: 40px; color: var(--sub);">
            Loading tools...
          </div>
        </div>
      </div>
    </div>
    
    <!-- Settings View -->
    <div class="view-content" id="settingsView" style="display: none;">
      <div style="padding: 20px; max-width: 600px; margin: 0 auto; min-height: 100%; box-sizing: border-box;">
        <h2 style="margin-bottom: 20px;">Settings</h2>
        <div class="form-group">
          <label class="form-label">Default Provider</label>
          <select class="form-select" id="settingsProvider">
            <optgroup label="๐Ÿ  Local Models">
              <option value="llamacpp">Llama.cpp (Local)</option>
              <option value="ollama">Ollama (Local)</option>
            </optgroup>
            <optgroup label="โ˜๏ธ Cloud Models (No Tools)">
              <option value="claude">Claude AI</option>
              <option value="gemini">Gemini AI</option>
              <option value="openai">OpenAI GPT</option>
              <option value="deepseek">DeepSeek AI</option>
            </optgroup>
            <optgroup label="๐Ÿ”€ Hybrid (Cloud + Local Tools)">
              <option value="claude-hybrid">Claude AI + Local Tools</option>
              <option value="gemini-hybrid">Gemini AI + Local Tools</option>
              <option value="openai-hybrid">OpenAI GPT + Local Tools</option>
              <option value="deepseek-hybrid">DeepSeek AI + Local Tools</option>
            </optgroup>
          </select>
          <div class="form-hint">Choose your preferred AI model provider</div>
        </div>
        <div class="form-group">
          <label class="form-label">Mode</label>
          <select class="form-select" id="settingsMode">
            <option value="local">Local Only</option>
            <option value="hybrid" selected>Hybrid (default)</option>
            <option value="cloud">Cloud Only</option>
          </select>
          <div class="form-hint">Route tasks between local llama.cpp and cloud</div>
        </div>
        <div class="form-group">
          <label class="form-label">Privacy Profile</label>
          <select class="form-select" id="settingsPrivacy">
            <option value="strict_local">Strict Local (never use cloud)</option>
            <option value="ask_before_cloud" selected>Ask Before Cloud</option>
            <option value="cloud_preferred">Cloud Preferred</option>
          </select>
          <div class="form-hint">Controls cloud escalation behavior</div>
        </div>
        <div class="form-group">
          <label class="form-label">Coding Provider</label>
          <select class="form-select" id="settingsCodingProvider">
            <option value="llamacpp">Local (llama.cpp)</option>
            <option value="claude">Claude</option>
            <option value="openai">OpenAI</option>
            <option value="gemini">Gemini</option>
            <option value="deepseek">DeepSeek</option>
          </select>
          <div class="form-hint">Preferred model for code tasks</div>
        </div>
        <div class="form-group">
          <label class="form-label">Confirmation Threshold</label>
          <input type="number" class="form-input" id="settingsThreshold" min="0" max="1" step="0.1" value="0.6">
          <div class="form-hint">Threshold for automatic task execution (0-1)</div>
        </div>
        <div class="form-group">
          <label class="form-label">Allowed Tools</label>
          <input type="text" class="form-input" id="settingsTools" placeholder="shell.run,script.run,fs.read,fs.write">
          <div class="form-hint">Comma-separated list of allowed tools</div>
        </div>
        <div class="form-group">
          <label class="form-label">API Keys</label>
          
          <div style="margin-bottom: 15px;">
            <label class="form-label" style="font-size: 14px; margin-bottom: 5px;">Claude (Anthropic)</label>
            <input type="password" class="form-input" id="settingsClaudeApi" placeholder="ANTHROPIC_API_KEY">
            <div class="form-hint">Required for Claude AI provider fallback</div>
          </div>
          
          <div style="margin-bottom: 15px;">
            <label class="form-label" style="font-size: 14px; margin-bottom: 5px;">Gemini (Google)</label>
            <input type="password" class="form-input" id="settingsGeminiApi" placeholder="GEMINI_API_KEY">
            <div class="form-hint">For Google's Gemini AI models</div>
          </div>
          
          <div style="margin-bottom: 15px;">
            <label class="form-label" style="font-size: 14px; margin-bottom: 5px;">OpenAI</label>
            <input type="password" class="form-input" id="settingsOpenAIApi" placeholder="OPENAI_API_KEY">
            <div class="form-hint">For GPT models</div>
          </div>
          
          <div style="margin-bottom: 15px;">
            <label class="form-label" style="font-size: 14px; margin-bottom: 5px;">DeepSeek</label>
            <input type="password" class="form-input" id="settingsDeepSeekApi" placeholder="DEEPSEEK_API_KEY">
            <div class="form-hint">Cost-effective AI alternative</div>
          </div>
          
          <div style="margin-bottom: 15px;">
            <label class="form-label" style="font-size: 14px; margin-bottom: 5px;">KnoblyCream API</label>
            <input type="password" class="form-input" id="settingsCreamApi" placeholder="CREAM_API_KEY">
            <div class="form-hint">For RSS feeds, posts, and email functionality</div>
          </div>
          
          <div style="margin-bottom: 15px;">
            <label class="form-label" style="font-size: 14px; margin-bottom: 5px;">YouTube API</label>
            <input type="password" class="form-input" id="settingsYouTubeApi" placeholder="YOUTUBE_API_KEY">
            <div class="form-hint">For YouTube video search and trending videos</div>
          </div>
          
          <div style="margin-bottom: 15px;">
            <label class="form-label" style="font-size: 14px; margin-bottom: 5px;">SerpAPI (Web Search)</label>
            <input type="password" class="form-input" id="settingsSerpApi" placeholder="SERPAPI_KEY">
            <div class="form-hint">For web search functionality</div>
          </div>
        </div>
        <button class="btn" id="saveSettingsBtn" onclick="saveSettings()">Save Settings</button>
        <div style="height: 40px;"></div> <!-- Spacer for scroll -->
      </div>
    </div>

    <!-- Workflows View -->
    <div class="view-content" id="workflowsView" style="display:none;">
      <div style="padding: 20px; max-width: 1100px; margin: 0 auto;">
        <h2 style="margin-bottom:16px;">Workflow Builder</h2>
        <div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap:16px;">
          <!-- Analyze Document -->
          <div style="border:1px solid var(--border); border-radius:10px; padding:14px; background:var(--panel);">
            <h3 style="margin:0 0 10px 0;">Analyze Document/Spreadsheet</h3>
            <div class="form-group"><label class="form-label">Path</label><input id="wfAnalyzePath" class="form-input" type="text" placeholder="/path/to/file.csv"/></div>
            <button class="btn" onclick="runWorkflowAnalyze(document.getElementById('wfAnalyzePath').value)">Run</button>
            <div id="workflowAnalyzeResult" style="margin-top:10px; font-size:13px; max-height:220px; overflow:auto;"></div>
          </div>
          <!-- Build Document -->
          <div style="border:1px solid var(--border); border-radius:10px; padding:14px; background:var(--panel);">
            <h3 style="margin:0 0 10px 0;">Build New Document</h3>
            <div class="form-group"><label class="form-label">Title</label><input id="wfBuildTitle" class="form-input" type="text" placeholder="Quarterly Summary"/></div>
            <div class="form-group"><label class="form-label">Sections (bullets)</label><textarea id="wfBuildSections" class="form-input" style="min-height:100px;" placeholder="โ€ข Revenue trends\nโ€ข Key risks\nโ€ข Next steps"></textarea></div>
            <div class="form-group"><label class="form-label">Format</label><select id="wfBuildFormat" class="form-select"><option>markdown</option><option>latex</option></select></div>
            <button class="btn" onclick="runWorkflowBuild(document.getElementById('wfBuildTitle').value, document.getElementById('wfBuildSections').value, document.getElementById('wfBuildFormat').value)">Run</button>
            <div id="workflowBuildResult" style="margin-top:10px; font-size:13px; max-height:220px; overflow:auto;"></div>
          </div>
          <!-- Convert Document -->
          <div style="border:1px solid var(--border); border-radius:10px; padding:14px; background:var(--panel);">
            <h3 style="margin:0 0 10px 0;">Convert Document</h3>
            <div class="form-group"><label class="form-label">Source Path</label><input id="wfConvSource" class="form-input" type="text" placeholder="/path/to/main.tex"/></div>
            <div class="form-group"><label class="form-label">Target Format</label><input id="wfConvTarget" class="form-input" type="text" placeholder="pdf"/></div>
            <button class="btn" onclick="runWorkflowConvert(document.getElementById('wfConvSource').value, document.getElementById('wfConvTarget').value)">Run</button>
            <div id="workflowConvertResult" style="margin-top:10px; font-size:13px; max-height:220px; overflow:auto;"></div>
          </div>

          <!-- Custom Workflow Builder -->
          <div style="grid-column: 1 / -1; border:1px solid var(--border); border-radius:10px; padding:14px; background:var(--panel);">
            <h3 style="margin:0 0 10px 0;">Custom Workflow</h3>
            <div class="form-group"><label class="form-label">Name</label><input id="wfName" class="form-input" type="text" placeholder="My Workflow"/></div>
            <div style="display:flex; gap:8px; align-items:flex-start; flex-wrap:wrap;">
              <div style="min-width:220px; flex:1;">
                <label class="form-label">Step Type</label>
                <select id="wfStepType" class="form-select">
                  <option>shell.run</option>
                  <option>fs.read</option>
                  <option>fs.write</option>
                  <option>web.search</option>
                  <option>jit</option>
                  <option>tex.compile</option>
                </select>
              </div>
              <div style="min-width:220px; flex:1;">
                <label class="form-label">OS (optional)</label>
                <select id="wfStepOs" class="form-select">
                  <option value="any">Any</option>
                  <option value="linux">Linux</option>
                  <option value="darwin">macOS</option>
                  <option value="win32">Windows</option>
                </select>
              </div>
              <div style="min-width:320px; flex:2;">
                <label class="form-label">Args (JSON)</label>
                <textarea id="wfStepArgs" class="form-input" style="min-height:80px;" placeholder='{"cmd":"ls -la"}'></textarea>
                <div class="form-hint">Use "$prev" or "$prev.stdout" to pass output from previous step.</div>
              </div>
              <div style="min-width:220px; flex:1;">
                <label class="form-label">Shell (shell.run)</label>
                <select id="wfStepShell" class="form-select">
                  <option value="">Default</option>
                  <option value="bash">bash</option>
                  <option value="zsh">zsh</option>
                  <option value="sh">sh</option>
                  <option value="powershell">powershell</option>
                  <option value="cmd">cmd</option>
                </select>
              </div>
              <div style="align-self:flex-end;">
                <button class="btn" onclick="wfAddStep()">+ Add Step</button>
              </div>
            </div>
            <div id="wfSteps" style="margin-top:12px; display:grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap:10px;"></div>
            <div style="display:flex; gap:8px; margin-top:12px;">
              <button class="btn" onclick="wfRun(false)">Run</button>
              <button class="btn secondary" onclick="wfRun(true)">Dry Run</button>
              <button class="btn" onclick="wfSave()">Save</button>
            </div>
            <pre id="wfRunOut" style="margin-top:12px; background:var(--muted); border:1px solid var(--border); padding:10px; border-radius:8px; max-height:300px; overflow:auto;"></pre>
            <div style="margin-top:14px;">
              <h4>Saved Workflows</h4>
              <div id="wfSaved" style="display:grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap:10px;"></div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- System View -->
    <div class="view-content" id="systemView" style="display:none;">
      <div style="padding: 20px; max-width: 700px; margin: 0 auto;">
        <h2>System</h2>
        <p style="color:var(--sub);">Model connectivity and environment checks.</p>
        <button class="btn" onclick="loadSystemStatus()">Refresh Status</button>
        <div id="systemStatus" style="margin-top:12px; font-size:13px;"></div>

        <div style="margin-top:24px; border-top:1px solid var(--border); padding-top:16px;">
          <h3 style="margin:0 0 10px 0;">Cream API Quick Actions</h3>
          <div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap:12px;">
            <!-- Fetch Posts -->
            <div style="border:1px solid var(--border); border-radius:10px; padding:12px; background:var(--panel);">
              <h4 style="margin:0 0 8px 0;">Fetch Recent Posts</h4>
              <div class="form-group"><label class="form-label">Limit</label><input id="creamFetchLimit" class="form-input" type="number" value="5"/></div>
              <div class="form-group"><label class="form-label"><input type="checkbox" id="creamFetchRaw"/> Show raw JSON</label></div>
              <button class="btn" onclick="systemCreamFetch()">Fetch</button>
            </div>
            <!-- Send Test Email -->
            <div style="border:1px solid var(--border); border-radius:10px; padding:12px; background:var(--panel);">
              <h4 style="margin:0 0 8px 0;">Send Test Email</h4>
              <div class="form-group"><label class="form-label">From Email</label><input id="creamMailFrom" class="form-input" type="email" placeholder="me@example.com"/></div>
              <div class="form-group"><label class="form-label">To Email</label><input id="creamMailTo" class="form-input" type="email" placeholder="you@example.com"/></div>
              <div class="form-group"><label class="form-label">Subject</label><input id="creamMailSubject" class="form-input" type="text" placeholder="Hello"/></div>
              <div class="form-group"><label class="form-label">Body</label><textarea id="creamMailBody" class="form-input" style="min-height:70px;" placeholder="Hi there"></textarea></div>
              <button class="btn" onclick="systemCreamMail()">Send</button>
            </div>
            <!-- Create Post -->
            <div style="border:1px solid var(--border); border-radius:10px; padding:12px; background:var(--panel);">
              <h4 style="margin:0 0 8px 0;">Create Post</h4>
              <div class="form-group"><label class="form-label">Content</label><textarea id="creamPostContent" class="form-input" style="min-height:70px;" placeholder="Hello from C9AI"></textarea></div>
              <div class="form-group"><label class="form-label">Visibility</label><select id="creamPostVisibility" class="form-select"><option>public</option><option>private</option></select></div>
              <button class="btn" onclick="systemCreamPost()">Post</button>
            </div>
          </div>
          <pre id="creamOut" style="margin-top:12px; background:var(--muted); border:1px solid var(--border); padding:10px; border-radius:8px; max-height:300px; overflow:auto;"></pre>
          <div style="margin-top:12px;">
            <button class="btn secondary" onclick="systemCreamDiagnose()">Diagnose Cream APIs</button>
            <button class="btn secondary" onclick="systemCreamDiagMail()">Diagnose Mail</button>
            <button class="btn secondary" onclick="systemCreamDiagPost()">Diagnose Post</button>
          </div>
        </div>
      </div>
    </div>

    <!-- Terminal View -->
    <div class="view-content" id="terminalView" style="display:none;">
      <div style="padding: 20px; max-width: 900px; margin: 0 auto;">
        <h2>System Terminal (Quick Runner)</h2>
        <div class="form-group"><label class="form-label">Command</label><input id="termCmd" class="form-input" type="text" placeholder="claude --help or gemini --help"/></div>
        <button class="btn" onclick="runTerminalCmd()">Run</button>
        <pre id="termOut" style="margin-top:12px; background:var(--muted); border:1px solid var(--border); padding:10px; border-radius:8px; max-height:400px; overflow:auto;"></pre>
      </div>
    </div>

    <!-- Calculators View -->
    <div class="view-content" id="calculatorsView" style="display: none;">
      <div style="padding: 20px; max-width: 1000px; margin: 0 auto;">
        <h2 style="margin-bottom:8px;">Executive Calculators</h2>
        <div style="margin-bottom:16px; font-size:13px;">
          <a href="#savedCalcsAnchor">Jump to Saved Calculators โ†“</a>
        </div>
        <div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap:16px;">
          <!-- Investment -->
          <div style="border:1px solid var(--border); border-radius:10px; padding:14px; background:var(--panel);">
            <h3 style="margin:0 0 10px 0;">Investment</h3>
            <div class="form-group"><label class="form-label">Amount</label><input id="calcInvAmount" class="form-input" type="text" placeholder="250000"/></div>
            <div class="form-group"><label class="form-label">Upside %</label><input id="calcInvUpside" class="form-input" type="text" placeholder="12%"/></div>
            <div class="form-group"><label class="form-label">Downside % (optional)</label><input id="calcInvDown" class="form-input" type="text" placeholder="0%"/></div>
            <div class="form-group"><label class="form-label">Years</label><input id="calcInvYears" class="form-input" type="number" placeholder="2"/></div>
            <div class="form-group"><label class="form-label">Probability % (optional)</label><input id="calcInvProb" class="form-input" type="text" placeholder="50%"/></div>
            <button class="btn" onclick="runInvestmentCalc()">Calculate</button>
            <div id="calcInvResult" style="margin-top:10px; font-size:13px;"></div>
          </div>
          <!-- Vendor Discount -->
          <div style="border:1px solid var(--border); border-radius:10px; padding:14px; background:var(--panel);">
            <h3 style="margin:0 0 10px 0;">Vendor Discount</h3>
            <div class="form-group"><label class="form-label">Amount</label><input id="calcVDAmount" class="form-input" type="text" placeholder="50000"/></div>
            <div class="form-group"><label class="form-label">Discount %</label><input id="calcVDDisc" class="form-input" type="text" placeholder="2%"/></div>
            <div class="form-group"><label class="form-label">Days Early (optional)</label><input id="calcVDDays" class="form-input" type="number" placeholder="20"/></div>
            <button class="btn" onclick="runVendorDiscountCalc()">Calculate</button>
            <div id="calcVDResult" style="margin-top:10px; font-size:13px;"></div>
          </div>
          <!-- Depreciation -->
          <div style="border:1px solid var(--border); border-radius:10px; padding:14px; background:var(--panel);">
            <h3 style="margin:0 0 10px 0;">Depreciation</h3>
            <div class="form-group"><label class="form-label">Cost</label><input id="calcDepCost" class="form-input" type="text" placeholder="100000"/></div>
            <div class="form-group"><label class="form-label">Method</label><select id="calcDepMethod" class="form-select"><option value="SLM">SLM</option><option value="WDV">WDV</option></select></div>
            <div class="form-group"><label class="form-label">Useful Life (years, optional for WDV)</label><input id="calcDepLife" class="form-input" type="number" placeholder="15"/></div>
            <div class="form-group"><label class="form-label">Residual Value % (optional)</label><input id="calcDepResidual" class="form-input" type="text" placeholder="5%"/></div>
            <div class="form-group"><label class="form-label">Rate % (WDV optional)</label><input id="calcDepRate" class="form-input" type="text" placeholder="(derive)"/></div>
            <div class="form-group"><label class="form-label">Date Ready (YYYY-MM-DD)</label><input id="calcDepReady" class="form-input" type="text" placeholder="2025-06-01"/></div>
            <div class="form-group"><label class="form-label">Year End (YYYY-MM-DD)</label><input id="calcDepYE" class="form-input" type="text" placeholder="2026-03-31"/></div>
            <button class="btn" onclick="runDepreciationCalc()">Calculate</button>
            <div id="calcDepResult" style="margin-top:10px; font-size:13px;"></div>
          </div>
          <!-- Custom (Expression) -->
          <div style="border:1px solid var(--border); border-radius:10px; padding:14px; background:var(--panel);">
            <h3 style="margin:0 0 10px 0;">Custom (Expression)</h3>
            <div class="form-group"><label class="form-label">Expression</label><input id="calcExpr" class="form-input" type="text" placeholder="amount * (1 + rate)^years"/></div>
            <div class="form-group"><label class="form-label">Variables (key=value, comma separated)</label><input id="calcVars" class="form-input" type="text" placeholder="amount=100000, rate=0.12, years=2"/></div>
            <div style="display:flex; gap:10px;">
              <button class="btn" onclick="runCustomCalc()">Calculate</button>
              <button class="btn secondary" onclick="saveCustomCalcDialog()">Saveโ€ฆ</button>
            </div>
            <div id="calcExprResult" style="margin-top:10px; font-size:13px;"></div>
          </div>
          <!-- Saved Calculators -->
          <div style="grid-column: 1 / -1;">
            <a id="savedCalcsAnchor"></a>
            <h3>Saved Calculators</h3>
            <div id="savedCalcs" style="display:grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap:16px;"></div>
          </div>
        </div>
      </div>
    </div>
    
    <!-- Vibe Sessions View -->
    <div class="view-content" id="vibeView" style="display: none;">
      <div style="padding: 20px; max-width: 1000px; margin: 0 auto; min-height: 100%; box-sizing: border-box;">
        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px;">
          <h2 style="margin: 0;">๐ŸŽญ Universal Vibe Task Manager</h2>
          <div style="font-size: 13px; color: var(--sub);">Match your energy with perfect workflows</div>
        </div>

        <!-- Vibe Detection Card -->
        <div style="background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 25px; margin-bottom: 25px;">
          <div style="display: flex; justify-content: between; align-items: center; margin-bottom: 20px;">
            <h3 style="margin: 0; color: var(--primary);">๐ŸŽฏ What's Your Current Vibe?</h3>
            <button id="detectVibeBtn" class="btn primary" onclick="detectCurrentVibe()">
              <span>๐Ÿ”</span> Detect My Vibe
            </button>
          </div>
          
          <div id="vibeDetectionForm" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 20px;">
            <div>
              <label style="display: block; margin-bottom: 8px; font-weight: 500;">Energy Level</label>
              <select id="energyLevel" style="width: 100%; padding: 10px; border: 1px solid var(--border); border-radius: 6px; background: var(--muted); color: var(--text);">
                <option value="">Select energy...</option>
                <option value="high">๐Ÿš€ High Energy</option>
                <option value="focused">๐ŸŽฏ Focused</option>
                <option value="medium">โšก Medium</option>
                <option value="low">๐ŸŒ™ Low Energy</option>
              </select>
            </div>
            
            <div>
              <label style="display: block; margin-bottom: 8px; font-weight: 500;">Current Mood</label>
              <select id="currentMood" style="width: 100%; padding: 10px; border: 1px solid var(--border); border-radius: 6px; background: var(--muted); color: var(--text);">
                <option value="">Select mood...</option>
                <option value="creative">๐ŸŽจ Creative</option>
                <option value="analytical">๐Ÿ”ฌ Analytical</option>
                <option value="productive">โšก Productive</option>
                <option value="exploratory">๐Ÿ—บ๏ธ Exploratory</option>
                <option value="collaborative">๐Ÿ‘ฅ Collaborative</option>
                <option value="steady">๐Ÿ“Š Steady</option>
              </select>
            </div>
            
            <div>
              <label style="display: block; margin-bottom: 8px; font-weight: 500;">Available Time</label>
              <select id="availableTime" style="width: 100%; padding: 10px; border: 1px solid var(--border); border-radius: 6px; background: var(--muted); color: var(--text);">
                <option value="">Select time...</option>
                <option value="30">30 minutes</option>
                <option value="60">1 hour</option>
                <option value="90">90 minutes</option>
                <option value="120">2 hours</option>
                <option value="180">3+ hours</option>
              </select>
            </div>
            
            <div>
              <label style="display: block; margin-bottom: 8px; font-weight: 500;">Work Context</label>
              <select id="workContext" style="width: 100%; padding: 10px; border: 1px solid var(--border); border-radius: 6px; background: var(--muted); color: var(--text);">
                <option value="">Select context...</option>
                <option value="home-office">๐Ÿ  Home Office</option>
                <option value="quiet-space">๐Ÿคซ Quiet Space</option>
                <option value="collaborative">๐Ÿ‘ฅ Team Environment</option>
                <option value="dual-monitor">๐Ÿ’ป Dual Monitors</option>
                <option value="mobile">๐Ÿ“ฑ On the Go</option>
              </select>
            </div>
          </div>
          
          <div id="vibeResult" style="display: none; background: var(--muted); border-radius: 8px; padding: 15px; margin-top: 15px;">
            <div id="detectedVibe" style="font-weight: 600; margin-bottom: 10px;"></div>
            <div id="vibeDescription" style="color: var(--sub); margin-bottom: 10px;"></div>
            <div id="vibeConfidence" style="font-size: 12px; color: var(--sub);"></div>
          </div>
        </div>

        <!-- Quick Vibe Actions -->
        <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;">
          <div style="background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 20px;">
            <div style="display: flex; align-items: center; margin-bottom: 15px;">
              <span style="font-size: 24px; margin-right: 12px;">๐ŸŒ…</span>
              <div>
                <h4 style="margin: 0; color: var(--primary);">Morning Creative</h4>
                <div style="font-size: 12px; color: var(--sub);">Fresh energy, content creation</div>
              </div>
            </div>
            <button class="btn secondary" onclick="startVibeSession('morning-content-creator')" style="width: 100%;">
              Start Creative Session
            </button>
          </div>
          
          <div style="background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 20px;">
            <div style="display: flex; align-items: center; margin-bottom: 15px;">
              <span style="font-size: 24px; margin-right: 12px;">๐Ÿ”ฌ</span>
              <div>
                <h4 style="margin: 0; color: var(--primary);">Deep Analysis</h4>
                <div style="font-size: 12px; color: var(--sub);">Data diving, systematic thinking</div>
              </div>
            </div>
            <button class="btn secondary" onclick="startVibeSession('data-detective')" style="width: 100%;">
              Start Analysis Session
            </button>
          </div>
          
          <div style="background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 20px;">
            <div style="display: flex; align-items: center; margin-bottom: 15px;">
              <span style="font-size: 24px; margin-right: 12px;">โšก</span>
              <div>
                <h4 style="margin: 0; color: var(--primary);">Rapid Prototype</h4>
                <div style="font-size: 12px; color: var(--sub);">Fast building, experimentation</div>
              </div>
            </div>
            <button class="btn secondary" onclick="startVibeSession('rapid-prototype')" style="width: 100%;">
              Start Prototype Sprint
            </button>
          </div>
        </div>

        <!-- Workflow Templates -->
        <div style="background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 25px;">
          <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; gap: 8px;">
            <h3 style="margin: 0;">๐ŸŽจ Available Workflow Templates</h3>
            <div style="display:flex; gap:8px;">
              <button class="btn" onclick="showGenerateWorkflowModal()" title="Use a cloud model to draft a new workflow from a prompt">
                <span>โœจ</span> Generate Workflow
              </button>
              <button class="btn primary" onclick="refreshTemplates()">
                <span>๐Ÿ”„</span> Refresh Templates
              </button>
            </div>
          </div>
          
          <div id="workflowTemplates" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 16px;">
            <!-- Templates will be loaded here -->
            <div style="text-align: center; color: var(--sub); padding: 40px;">
              <div style="font-size: 48px; margin-bottom: 16px;">๐ŸŽญ</div>
              <div>Click "Refresh Templates" to load available workflows</div>
            </div>
          </div>
        </div>

        <!-- Slides Library -->
        <div style="background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 25px; margin-top: 20px;">
          <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; gap: 8px;">
            <h3 style="margin: 0;">๐Ÿ–ฅ๏ธ Slides Library</h3>
            <div style="display:flex; gap:8px;">
              <button class="btn secondary" onclick="refreshSlides()">
                <span>๐Ÿ”„</span> Refresh Slides
              </button>
            </div>
          </div>
          <div id="slidesGrid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px;">
            <div style="text-align: center; color: var(--sub); padding: 40px; grid-column: 1 / -1;">
              <div style="font-size: 42px; margin-bottom: 16px;">๐Ÿ—‚๏ธ</div>
              <div>No slides found yet. Generate one from Markdown, then refresh.</div>
            </div>
          </div>
        </div>

        <!-- Interactive Workflow Session -->
        <div id="interactiveSessionCard" style="display: none; background: var(--panel); border: 1px solid var(--primary); border-radius: 12px; padding: 25px; margin-top: 25px;">
          <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
            <div>
              <h3 style="margin: 0; color: var(--primary);" id="sessionTitle">๐ŸŽฏ Interactive Workflow Session</h3>
              <div style="font-size: 13px; color: var(--sub); margin-top: 4px;" id="sessionSubtitle">Step-by-step tool execution with your inputs</div>
            </div>
            <div style="display: flex; gap: 12px;">
              <button class="btn secondary" onclick="saveWorkflowProgress()" style="font-size: 13px;">
                <span>๐Ÿ’พ</span> Save Progress
              </button>
              <button class="btn danger" onclick="endInteractiveSession()">
                <span>โน๏ธ</span> End Session
              </button>
            </div>
          </div>
          
          <!-- Workflow Progress Overview -->
          <div style="background: var(--muted); border-radius: 8px; padding: 15px; margin-bottom: 20px;">
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
              <span style="font-weight: 500;">Workflow Progress</span>
              <span id="workflowProgressText" style="font-size: 13px; color: var(--sub);">0 of 0 steps completed</span>
            </div>
            <div style="background: var(--panel); border-radius: 4px; height: 8px; overflow: hidden;">
              <div id="workflowProgressBar" style="background: var(--primary); height: 100%; width: 0%; transition: width 0.3s;"></div>
            </div>
          </div>
          
          <!-- Interactive Workflow Steps -->
          <div id="workflowStepsContainer" style="display: flex; flex-direction: column; gap: 20px;">
            <!-- Steps will be populated here -->
          </div>
          
          <!-- Workflow Results -->
          <div id="workflowResults" style="display: none; background: var(--muted); border-radius: 8px; padding: 20px; margin-top: 20px;">
            <h4 style="margin: 0 0 15px 0; color: var(--primary);">๐ŸŽ‰ Workflow Results</h4>
            <div id="workflowResultsContent"></div>
          </div>
        </div>
      </div>
    </div>

    <!-- Help View -->
    <div class="view-content" id="helpView" style="display: none;">
      <div style="padding: 40px; max-width: 900px; margin: 0 auto;">
        <h2 style="margin-bottom: 20px;">Help & Documentation</h2>

        <div style="background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 20px; margin-bottom: 16px;">
          <h3 style="margin-bottom: 12px;">๐Ÿš€ Getting Started</h3>
          <ul style="color: var(--sub); line-height: 1.6; padding-left: 18px;">
            <li>Chat: ask anything; use sigils (e.g., <code>@email</code>, <code>@post</code>, <code>@calc</code>) for actions.</li>
            <li>AskAI (floating): quick Q&A with provider dropdown and expand.</li>
            <li>Calculators: deterministic business calculators + custom expressions.</li>
            <li>Workflows: chain steps (shell.run, fs.read/write, jit, tex.compile, cream.*).</li>
            <li>System: connectivity + Cream API quick actions and diagnostics.</li>
            <li>Terminal: run one-off system commands (non-interactive).</li>
          </ul>
        </div>

        <div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(280px,1fr)); gap:16px;">
          <div style="background: var(--panel); border:1px solid var(--border); border-radius:12px; padding:16px;">
            <h3>๐Ÿ’ฌ Chat & Sigils</h3>
            <ul style="color: var(--sub); line-height:1.6; padding-left:18px;">
              <li>Send: Ctrl/Cmd + Enter</li>
              <li><code>@email</code> <em>"to@example.com"</em> subject: <em>Text</em> content: <em>Body</em></li>
              <li><code>@post</code> <em>"Hello world"</em> visibility: public</li>
              <li><code>@calc</code> <em>22/7</em> or saved function calls</li>
              <li><code>@executive</code> domains (Investment, Vendor Discount, Depreciation...)</li>
            </ul>
          </div>

          <div style="background: var(--panel); border:1px solid var(--border); border-radius:12px; padding:16px;">
            <h3>๐Ÿงฎ Calculators</h3>
            <ul style="color: var(--sub); line-height:1.6; padding-left:18px;">
              <li>Built-ins: Investment, Vendor Discount, Depreciation, SaaS Breakeven, Finance.</li>
              <li>Custom (Expression): enter formula + variables, Calculate; Save to reuse.</li>
              <li>Saved Calculators: collapsible list; Run/Edit/Rename/Delete.</li>
            </ul>
          </div>

          <div style="background: var(--panel); border:1px solid var(--border); border-radius:12px; padding:16px;">
            <h3>๐Ÿ”€ Workflows</h3>
            <ul style="color: var(--sub); line-height:1.6; padding-left:18px;">
              <li>Steps: shell.run, fs.read/write, web.search, jit, tex.compile, cream.*</li>
              <li>Data flow: use <code>"$prev"</code> or <code>"$prev.stdout"</code> in step args.</li>
              <li>Portability: set OS filter (Any/Linux/macOS/Windows), choose shell (bash/zsh/sh/powershell/cmd).</li>
              <li>Save/Load/Run/Dry Run from the Workflows tab.</li>
            </ul>
          </div>

          <div style="background: var(--panel); border:1px solid var(--border); border-radius:12px; padding:16px;">
            <h3>๐Ÿ› ๏ธ System & Cream API</h3>
            <ul style="color: var(--sub); line-height:1.6; padding-left:18px;">
              <li>Set API keys in Settings (Cream token/key, OpenAI, Gemini, etc.).</li>
              <li>Quick Actions: fetch posts, send mail, create post.</li>
              <li>Diagnostics: <em>Diagnose Cream APIs/Mail/Post</em> to see status/elapsed/sample.</li>
              <li>RSS/Stream handle slow endpoints with long timeouts + retries.</li>
            </ul>
          </div>

          <div style="background: var(--panel); border:1px solid var(--border); border-radius:12px; padding:16px;">
            <h3>๐Ÿ’พ Conversations</h3>
            <ul style="color: var(--sub); line-height:1.6; padding-left:18px;">
              <li>Rightโ€‘click a conversation โ†’ Rename / Save / Delete.</li>
              <li>Local autosave to browser; optional server save for persistence.</li>
            </ul>
          </div>
        </div>

        <div style="background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 16px; margin-top:16px;">
          <h3>โŒจ๏ธ Shortcuts</h3>
          <div style="display:grid; grid-template-columns: 1fr 2fr; gap:10px; color: var(--sub);">
            <div><kbd style="background: var(--muted); padding: 4px 8px; border-radius: 4px;">Ctrl/Cmd + Enter</kbd></div>
            <div>Send message</div>
            <div><kbd style="background: var(--muted); padding: 4px 8px; border-radius: 4px;">Ctrl/Cmd + N</kbd></div>
            <div>New conversation</div>
          </div>
        </div>

        <div style="background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 16px; margin-top:16px;">
          <h3>๐Ÿงฐ Available Tools</h3>
          <div id="toolsList" style="color: var(--sub); line-height: 1.6;">Loading tools...</div>
        </div>
      </div>
    </div>
    
    <!-- Functions View -->
    <div class="view-content" id="functionsView" style="display: none;">
      <div style="padding: 40px; max-width: 1000px; margin: 0 auto;">
        <h2 style="margin-bottom: 20px;">๐Ÿ“ Function Library</h2>
        
        <div style="background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 20px; margin-bottom: 24px;">
          <h3 style="margin-bottom: 12px;">๐Ÿš€ Quick Actions</h3>
          <div style="display: flex; gap: 12px; flex-wrap: wrap;">
            <button class="btn" onclick="showCreateFunction()">โœจ Create Function</button>
            <button class="btn secondary" onclick="refreshFunctions()">๐Ÿ”„ Refresh</button>
            <button class="btn secondary" onclick="openFunctionsDirectory()">๐Ÿ“ Open Directory</button>
          </div>
        </div>

        <div style="background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 20px; margin-bottom: 24px;">
          <h3 style="margin-bottom: 12px;">๐Ÿ“Š Function Statistics</h3>
          <div id="functionStats" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 16px;">
            <div style="text-align: center;">
              <div style="font-size: 24px; font-weight: bold; color: var(--primary);" id="totalFunctions">-</div>
              <div style="color: var(--sub); font-size: 14px;">Total Functions</div>
            </div>
            <div style="text-align: center;">
              <div style="font-size: 24px; font-weight: bold; color: var(--ok);" id="activeFunctions">-</div>
              <div style="color: var(--sub); font-size: 14px;">Active</div>
            </div>
            <div style="text-align: center;">
              <div style="font-size: 24px; font-weight: bold; color: var(--sub);" id="storageUsed">-</div>
              <div style="color: var(--sub); font-size: 14px;">Storage Used</div>
            </div>
          </div>
        </div>

        <div style="background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 20px;">
          <h3 style="margin-bottom: 12px;">๐Ÿ“š Function List</h3>
          <div id="functionsList" style="min-height: 200px;">
            <div style="text-align: center; color: var(--sub); padding: 40px;">
              Loading functions...
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- Floating Chat -->
  <button class="btn float-chat-btn" onclick="toggleFloatChat()">๐Ÿ’ก Ask AI</button>
  <div class="float-chat-panel" id="floatChat">
    <div class="float-chat-header">
      <div style="display:flex; align-items:center; gap:8px;">
        <div>AskAI</div>
        <select id="floatChatProvider" class="form-select" style="height:28px; padding:2px 6px; font-size:12px;">
          <option value="llamacpp">llamacpp</option>
          <option value="claude">claude</option>
          <option value="gemini">gemini</option>
          <option value="openai">openai</option>
          <option value="deepseek">deepseek</option>
        </select>
      </div>
      <div class="actions">
        <button class="btn secondary" onclick="toggleFloatChatExpand()" title="Expand/Collapse">โคข</button>
        <button class="btn secondary" onclick="toggleFloatChat()" title="Close">โœ•</button>
      </div>
    </div>
    <div class="float-chat-messages" id="floatChatMessages"></div>
    <div class="float-chat-input">
      <input id="floatChatInput" class="form-input" type="text" placeholder="Ask for a formulaโ€ฆ" onkeydown="if(event.key==='Enter'){sendFloatChat()}" />
      <button class="btn" onclick="sendFloatChat()">Send</button>
    </div>
  </div>

  <!-- Conversation Context Menu -->
  <div class="context-menu" id="convMenu">
    <div class="item" onclick="convMenuRename()">โœ๏ธ Rename</div>
    <div class="item" onclick="convMenuSave()">๐Ÿ’พ Save</div>
    <div class="item" onclick="convMenuDelete()">๐Ÿ—‘๏ธ Delete</div>
  </div>

  <script>
    // Global state
    let currentView = 'chat';
    let currentProvider = 'llamacpp';
    let conversations = JSON.parse(localStorage.getItem('c9ai-conversations') || '[]');
    let currentConversationId = null;
    let settings = {};
    
    // DOM elements
    const sidebar = document.getElementById('sidebar');
    const chatInput = document.getElementById('chatInput');
    const chatMessages = document.getElementById('chatMessages');
    const welcomeScreen = document.getElementById('welcomeScreen');
    const sendBtn = document.getElementById('sendBtn');
    const statusDot = document.getElementById('statusDot');
    const statusText = document.getElementById('statusText');
    const conversationsList = document.getElementById('conversationsList');
    
    // Initialize app
    document.addEventListener('DOMContentLoaded', async function() {
      await loadSettings();
      loadConversations();
      setupEventListeners();
      updateProviderButtons();
      loadSavedTheme(); // Load the saved theme preference
    });
    
    // Settings management
    async function loadSettings() {
      try {
        const response = await fetch('/api/settings');
        settings = await response.json();
        currentProvider = settings.provider || 'llamacpp';
        
        // Update UI elements
        const providerSelect = document.getElementById('settingsProvider');
        const thresholdInput = document.getElementById('settingsThreshold');
        const toolsInput = document.getElementById('settingsTools');
        const modeSelect = document.getElementById('settingsMode');
        const privacySelect = document.getElementById('settingsPrivacy');
        const codingProviderSelect = document.getElementById('settingsCodingProvider');
        const claudeApiInput = document.getElementById('settingsClaudeApi');
        const geminiApiInput = document.getElementById('settingsGeminiApi');
        const openAIApiInput = document.getElementById('settingsOpenAIApi');
        const deepSeekApiInput = document.getElementById('settingsDeepSeekApi');
        const creamApiInput = document.getElementById('settingsCreamApi');
        const youTubeApiInput = document.getElementById('settingsYouTubeApi');
        const serpApiInput = document.getElementById('settingsSerpApi');
        
        if (providerSelect) providerSelect.value = settings.provider || 'llamacpp';
        if (thresholdInput) thresholdInput.value = settings.confirmThreshold || 0.6;
        if (toolsInput) toolsInput.value = (settings.allowedTools || []).join(',');
        if (modeSelect) modeSelect.value = settings.defaultMode || 'hybrid';
        if (privacySelect) privacySelect.value = settings.privacyProfile || 'ask_before_cloud';
        if (codingProviderSelect) codingProviderSelect.value = settings.codingProvider || 'claude';
        if (claudeApiInput) claudeApiInput.value = settings.apiKeys?.ANTHROPIC_API_KEY || '';
        if (geminiApiInput) geminiApiInput.value = settings.apiKeys?.GEMINI_API_KEY || '';
        if (openAIApiInput) openAIApiInput.value = settings.apiKeys?.OPENAI_API_KEY || '';
        if (deepSeekApiInput) deepSeekApiInput.value = settings.apiKeys?.DEEPSEEK_API_KEY || '';
        if (creamApiInput) creamApiInput.value = settings.apiKeys?.CREAM_API_KEY || '';
        if (youTubeApiInput) youTubeApiInput.value = settings.apiKeys?.YOUTUBE_API_KEY || '';
        if (serpApiInput) serpApiInput.value = settings.apiKeys?.SERPAPI_KEY || '';
        
        setStatus('ready', 'Ready');
      } catch (error) {
        console.warn('Failed to load settings:', error);
        setStatus('error', 'Settings Error');
      }
    }
    
    async function saveSettings() {
      const saveBtn = document.getElementById('saveSettingsBtn');
      const originalText = saveBtn.textContent;
      
      // Visual feedback: disable button and show loading
      saveBtn.disabled = true;
      saveBtn.textContent = 'Saving...';
      saveBtn.style.backgroundColor = '#4a5568';
      
      const providerSelect = document.getElementById('settingsProvider');
      const thresholdInput = document.getElementById('settingsThreshold');
      const toolsInput = document.getElementById('settingsTools');
      const modeSelect = document.getElementById('settingsMode');
      const privacySelect = document.getElementById('settingsPrivacy');
      const codingProviderSelect = document.getElementById('settingsCodingProvider');
      const claudeApiInput = document.getElementById('settingsClaudeApi');
      const geminiApiInput = document.getElementById('settingsGeminiApi');
      const openAIApiInput = document.getElementById('settingsOpenAIApi');
      const deepSeekApiInput = document.getElementById('settingsDeepSeekApi');
      const creamApiInput = document.getElementById('settingsCreamApi');
      const youTubeApiInput = document.getElementById('settingsYouTubeApi');
      const serpApiInput = document.getElementById('settingsSerpApi');
      
      const newSettings = {
        provider: providerSelect.value,
        confirmThreshold: parseFloat(thresholdInput.value),
        allowedTools: toolsInput.value.split(',').map(s => s.trim()).filter(Boolean),
        defaultMode: modeSelect.value,
        privacyProfile: privacySelect.value,
        codingProvider: codingProviderSelect.value,
        apiKeys: {
          ANTHROPIC_API_KEY: document.getElementById('settingsClaudeApi').value || '',
          GEMINI_API_KEY: document.getElementById('settingsGeminiApi').value || '',
          OPENAI_API_KEY: document.getElementById('settingsOpenAIApi').value || '',
          DEEPSEEK_API_KEY: document.getElementById('settingsDeepSeekApi').value || '',
          CREAM_API_KEY: document.getElementById('settingsCreamApi').value || '',
          YOUTUBE_API_KEY: document.getElementById('settingsYouTubeApi').value || '',
          SERPAPI_KEY: document.getElementById('settingsSerpApi').value || ''
        }
      };
      
      try {
        await fetch('/api/settings', {
          method: 'PUT',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(newSettings)
        });
        
        settings = newSettings;
        currentProvider = settings.provider;
        updateProviderButtons();
        
        // Success feedback
        saveBtn.textContent = 'โœ… Saved!';
        saveBtn.style.backgroundColor = '#38a169';
        setStatus('ready', 'Settings Saved');
        
        // Reset button after delay
        setTimeout(() => {
          saveBtn.disabled = false;
          saveBtn.textContent = originalText;
          saveBtn.style.backgroundColor = '';
          setStatus('ready', 'Ready');
        }, 2000);
        
      } catch (error) {
        console.error('Failed to save settings:', error);
        
        // Error feedback
        saveBtn.textContent = 'โŒ Failed';
        saveBtn.style.backgroundColor = '#e53e3e';
        setStatus('error', 'Save Failed');
        
        // Reset button after delay
        setTimeout(() => {
          saveBtn.disabled = false;
          saveBtn.textContent = originalText;
          saveBtn.style.backgroundColor = '';
        }, 2000);
      }
    }
    
    // Status management
    function renderMarkdown(text) {
      if (!text) return '';
      
      // Extract and preserve code action buttons before escaping
      const codeActionRegex = /<div class="code-actions"[^>]*>.*?<\/div>/gs;
      const codeActions = [];
      let textWithPlaceholders = text.replace(codeActionRegex, (match) => {
        const placeholder = `__CODE_ACTIONS_${codeActions.length}__`;
        codeActions.push(match);
        return placeholder;
      });
      
      // Escape HTML to prevent XSS (but preserve our placeholders)
      const escaped = textWithPlaceholders
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;');
      
      // Normalize common bullet styles before HTML escaping
      // Convert lines starting with "- " to use the bullet dot so we render them as list items
      textWithPlaceholders = textWithPlaceholders.replace(/^\-\s+/gm, 'โ€ข ');

      // Simple markdown rendering
      let rendered = escaped
        // Images: ![alt](url)
        .replace(/!\[([^\]]*)\]\(([^)]+)\)/g, (m, alt, url) => {
          // RSS thumbnails should span the container; others stay compact
          if (String(alt).toLowerCase() === 'thumbnail') {
            return `<img src="${url}" alt="${alt}" class="rss-thumb"/>`;
          }
          return `<img src="${url}" alt="${alt}" style="max-width:140px; width:140px; height:auto; border-radius:8px; margin:8px 12px 8px 0; display:inline-block; vertical-align:top;"/>`;
        })
        // Links: [text](url)
        .replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener noreferrer">$1<\/a>')
        // Bold text: **text** -> <strong>text</strong>
        .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
        // Italic text: *text* -> <em>text</em>
        .replace(/(?<!\*)\*([^*]+?)\*(?!\*)/g, '<em>$1</em>')
        // Code blocks: ```code``` -> <pre><code>code</code></pre>
        .replace(/```(.*?)```/gs, '<pre><code>$1</code></pre>')
        // Inline code: `code` -> <code>code</code>
        .replace(/`([^`]+?)`/g, '<code>$1</code>')
        // Headers: ## text -> <h2>text</h2>
        .replace(/^### (.+)$/gm, '<h3>$1</h3>')
        .replace(/^## (.+)$/gm, '<h2>$1</h2>')
        .replace(/^# (.+)$/gm, '<h1>$1</h1>')
        // Bullet points: โ€ข text -> <li>text</li>
        .replace(/^โ€ข (.+)$/gm, '<li>$1</li>')
        // Line breaks
        .replace(/\n/g, '<br>')
        // collapse excessive breaks that can cause large gaps
        .replace(/(?:<br>\s*){3,}/g, '<br><br>')
        // Style 'Read more' as a pill
        .replace(/<a href=\"([^\"]+)\">Read more<\/a>/g, '<a class="pill-read" href="$1" target="_blank" rel="noopener noreferrer">Read more<\/a>');
        
      // Restore code action buttons
      codeActions.forEach((codeAction, index) => {
        rendered = rendered.replace(`__CODE_ACTIONS_${index}__`, codeAction);
      });
      
      return rendered;
    }

    function setStatus(type, message) {
      // Don't update status pane for progress messages - those go to chat now
      const progressMessages = [
        'analyzing request', 'planning action', 'executing', 'generating response',
        'thinking', 'planning', 'executing', 'synthesizing', 'using',
        '๐Ÿ”', '๐Ÿ“‹', 'โšก', 'โœจ', '๐Ÿค– using'
      ];
      
      if (progressMessages.some(pm => message.toLowerCase().includes(pm.toLowerCase()))) {
        return; // Skip status pane updates for progress
      }
      
      statusDot.className = 'status-dot ' + (type === 'ready' ? '' : type);
      
      // Show current provider name in status when ready
      if (type === 'ready' && currentProvider) {
        const providerName = getProviderDisplayName(currentProvider);
        statusText.textContent = `${providerName} - Ready`;
      } else {
        statusText.textContent = message;
      }
    }
    
    // Navigation
    function showView(viewName) {
      document.querySelectorAll('.view-content').forEach(view => {
        view.style.display = 'none';
      });
      
      document.querySelectorAll('.nav-item').forEach(item => {
        item.classList.remove('active');
      });
      
      document.getElementById(viewName + 'View').style.display = 'block';
      document.querySelector(`[data-view="${viewName}"]`).classList.add('active');
      
      currentView = viewName;
      updateViewTitle();
      
      if (viewName === 'help') {
        loadToolsList();
      } else if (viewName === 'calculators') {
        loadSavedCalculators && loadSavedCalculators();
      } else if (viewName === 'system') {
        loadSystemStatus && loadSystemStatus();
      } else if (viewName === 'workflows') {
        if (typeof wfLoadSaved === 'function') wfLoadSaved();
        // Auto-refresh templates and slides when entering Workflows view
        try { refreshTemplates(); } catch(e){}
        try { refreshSlides(); } catch(e){}
      }
    }
    
    function updateViewTitle() {
      const titles = {
        chat: 'Smart Chat - Enhanced Execution',
        functions: 'Function Library Manager',
        settings: 'Settings',
        help: 'Help & Documentation'
      };
      document.getElementById('viewTitle').textContent = titles[currentView] || 'c9ai';
    }
    
    function toggleSidebar() {
      sidebar.classList.toggle('collapsed');
    }

    // Theme Toggle Management
    function toggleTheme() {
      const body = document.body;
      const slider = document.querySelector('.theme-toggle-slider');
      const currentTheme = body.getAttribute('data-theme');
      
      if (currentTheme === 'light') {
        // Switch to dark mode
        body.removeAttribute('data-theme');
        slider.textContent = '๐ŸŒ™';
        localStorage.setItem('theme', 'dark');
      } else {
        // Switch to light mode  
        body.setAttribute('data-theme', 'light');
        slider.textContent = 'โ˜€๏ธ';
        localStorage.setItem('theme', 'light');
      }
    }
    
    // Load saved theme on page load
    function loadSavedTheme() {
      const savedTheme = localStorage.getItem('theme');
      if (savedTheme === 'light') {
        document.body.setAttribute('data-theme', 'light');
        document.querySelector('.theme-toggle-slider').textContent = 'โ˜€๏ธ';
      }
    }

    // Debug Panel Management
    let debugPanelVisible = false;

    function toggleDebugPanel() {
      const debugPanel = document.getElementById('debugPanel');
      const debugToggle = document.getElementById('debugToggle');
      
      debugPanelVisible = !debugPanelVisible;
      
      if (debugPanelVisible) {
        debugPanel.style.display = 'flex';
        debugToggle.classList.add('active');
        debugToggle.innerHTML = '๐Ÿ”ฌ';
        addDebugEntry('info', '๐Ÿ‘๏ธ', 'Debug panel opened - monitoring executive requests');
      } else {
        debugPanel.style.display = 'none';
        debugToggle.classList.remove('active');
        debugToggle.innerHTML = '๐Ÿ”ฌ';
      }
    }

    function addDebugEntry(type, icon, message, data = null) {
      const debugContent = document.getElementById('debugContent');
      const entry = document.createElement('div');
      entry.className = `debug-entry ${type}`;
      
      const timestamp = new Date().toLocaleTimeString();
      let displayMessage = message;
      
      // Format data if provided
      if (data && typeof data === 'object') {
        displayMessage += '\n' + JSON.stringify(data, null, 2);
      }
      
      entry.innerHTML = `
        <span class="debug-timestamp">${timestamp}</span>
        <span class="debug-icon">${icon}</span>
        <span class="debug-message">${displayMessage}</span>
      `;
      
      debugContent.appendChild(entry);
      
      // Auto-scroll to bottom
      debugContent.scrollTop = debugContent.scrollHeight;
      
      // Keep only last 50 entries for performance
      const entries = debugContent.querySelectorAll('.debug-entry');
      if (entries.length > 50) {
        entries[0].remove();
      }
    }

    function clearDebugLog() {
      const debugContent = document.getElementById('debugContent');
      debugContent.innerHTML = `
        <div class="debug-entry info">
          <span class="debug-timestamp">Cleared</span>
          <span class="debug-icon">๐Ÿงน</span>
          <span class="debug-message">Debug log cleared</span>
        </div>
      `;
    }

    // Progress tracking for multi-step executive requests
    let currentWorkflowSteps = 0;
    let completedWorkflowSteps = 0;

    // Interpret calculation results for executive clarity
    function interpretCalculationResult(expression, result) {
      if (!expression) return '';
      
      // Vendor discount patterns
      if (expression.includes('*') && expression.includes('0.01')) {
        return `(Discount Amount: โ‚น${result} savings if paid immediately)`;
      }
      if (expression.includes('10000') && expression.includes('-')) {
        return `(Final Amount to Pay: โ‚น${result} after discount)`;
      }
      
      // Investment patterns  
      if (expression.includes('365') && expression.includes('500')) {
        return `(Total Maturity Value: โ‚น${result} after 1 year)`;
      }
      
      // Compound interest patterns
      if (expression.includes('^') && expression.includes('365')) {
        return `(Compound Interest Calculation: โ‚น${result})`;
      }
      
      // ROI patterns
      if (expression.includes('/') && result < 100 && result > -100) {
        return `(ROI: ${result}%)`;
      }
      
      // Percentage patterns
      if (result < 1 && result > 0) {
        return `(${(result * 100).toFixed(2)}%)`;
      }
      
      // Large amounts (likely currency)
      if (result > 1000) {
        return `(โ‚น${result.toLocaleString('en-IN')})`;
      }
      
      return '';
    }

    function startWorkflowProgress(totalSteps, description) {
      currentWorkflowSteps = totalSteps;
      completedWorkflowSteps = 0;
      
      addDebugEntry('info', '๐ŸŽฏ', `Started workflow: ${description} (${totalSteps} steps)`);
      
      const progressBar = document.createElement('div');
      progressBar.className = 'progress-bar';
      progressBar.id = 'workflowProgress';
      progressBar.innerHTML = '<div class="progress-fill" style="width: 0%"></div>';
      
      document.getElementById('debugContent').appendChild(progressBar);
    }

    function updateWorkflowProgress(step, description) {
      completedWorkflowSteps = step;
      const percentage = (step / currentWorkflowSteps) * 100;
      
      const progressFill = document.querySelector('#workflowProgress .progress-fill');
      if (progressFill) {
        progressFill.style.width = `${percentage}%`;
      }
      
      addDebugEntry('success', 'โœ…', `Step ${step}/${currentWorkflowSteps}: ${description}`);
      
      if (step === currentWorkflowSteps) {
        setTimeout(() => {
          const progressBar = document.getElementById('workflowProgress');
          if (progressBar) progressBar.remove();
        }, 2000);
      }
    }
    
    function showSettings() {
      showView('settings');
    }
    
    // Provider management
    function updateProviderButtons() {
      document.querySelectorAll('[data-provider]').forEach(btn => {
        btn.classList.toggle('active', btn.dataset.provider === currentProvider);
      });
    }

    // Calculators - client helpers
    async function execCalc(domain, params) {
      const r = await fetch('/api/calculators/execute', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ domain, params })
      });
      const j = await r.json();
      if (!r.ok || j.success === false) throw new Error(j.error || 'Calculation failed');
      return j;
    }

    function fmtNum(x) { if (x == null) return ''; return typeof x === 'number' ? x.toLocaleString() : String(x); }

    async function runInvestmentCalc() {
      const params = {
        amount: document.getElementById('calcInvAmount').value,
        upside: document.getElementById('calcInvUpside').value,
        downside: document.getElementById('calcInvDown').value,
        years: document.getElementById('calcInvYears').value,
        probability: document.getElementById('calcInvProb').value,
      };
      const el = document.getElementById('calcInvResult');
      el.textContent = 'Calculatingโ€ฆ';
      try {
        const out = await execCalc('INVESTMENT', params);
        const r = out.results || {};
        el.innerHTML = `
          <div>Expected Value: <strong>${fmtNum(r.expected)}</strong></div>
          <div>ROI: <strong>${fmtNum(r.roiPercent)}%</strong></div>
          <div style="margin-top:6px; color:var(--sub);">${out.explanation || ''}</div>
        `;
      } catch (e) { el.textContent = 'Error: ' + e.message; }
    }

    async function runVendorDiscountCalc() {
      const params = {
        amount: document.getElementById('calcVDAmount').value,
        discount: document.getElementById('calcVDDisc').value,
        days: document.getElementById('calcVDDays').value,
      };
      const el = document.getElementById('calcVDResult');
      el.textContent = 'Calculatingโ€ฆ';
      try {
        const out = await execCalc('VENDOR_DISCOUNT', params);
        const r = out.results || {};
        el.innerHTML = `
          <div>Savings: <strong>${fmtNum(r.savings)}</strong></div>
          <div>Pay Amount: <strong>${fmtNum(r.discountedPrice)}</strong></div>
          ${r.effectiveAnnualRatePercent != null ? `<div>Effective Annualized Rate: <strong>${fmtNum(Number(r.effectiveAnnualRatePercent).toFixed(2))}%</strong></div>` : ''}
          <div style="margin-top:6px; color:var(--sub);">${out.explanation || ''}</div>
        `;
      } catch (e) { el.textContent = 'Error: ' + e.message; }
    }

    async function runDepreciationCalc() {
      const params = {
        cost: document.getElementById('calcDepCost').value,
        method: document.getElementById('calcDepMethod').value,
        useful_life_years: document.getElementById('calcDepLife').value,
        residual_percent: document.getElementById('calcDepResidual').value,
        rate: document.getElementById('calcDepRate').value,
        date_ready: document.getElementById('calcDepReady').value,
        year_end: document.getElementById('calcDepYE').value,
      };
      const el = document.getElementById('calcDepResult');
      el.textContent = 'Calculatingโ€ฆ';
      try {
        const out = await execCalc('DEPRECIATION', params);
        const r = out.results || {};
        el.innerHTML = `
          ${r.annualDepreciation != null ? `<div>Annual Depreciation: <strong>${fmtNum(r.annualDepreciation)}</strong></div>` : ''}
          <div>First Period Depreciation: <strong>${fmtNum(r.firstPeriodDepreciation)}</strong></div>
          <div>Closing Carrying Amount: <strong>${fmtNum(r.closingCarryingAmount)}</strong></div>
          ${r.ratePercent != null ? `<div>Rate: <strong>${fmtNum(Number(r.ratePercent).toFixed(2))}%</strong></div>` : ''}
          <div style="margin-top:6px; color:var(--sub);">${out.explanation || ''}</div>
        `;
      } catch (e) { el.textContent = 'Error: ' + e.message; }
    }

    async function runCustomCalc() {
      const expr = document.getElementById('calcExpr').value;
      const varsText = document.getElementById('calcVars').value || '';
      const el = document.getElementById('calcExprResult');
      el.textContent = 'Calculatingโ€ฆ';
      try {
        const vars = {};
        // Parse key=value pairs separated by comma
        varsText.split(',').forEach(pair => {
          const p = pair.trim();
          if (!p) return;
          const [k, v] = p.split('=');
          if (k && v != null) vars[k.trim()] = v.trim();
        });
        const r = await fetch('/api/calculators/custom/execute', {
          method: 'POST', headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ expression: expr, vars })
        });
        const j = await r.json();
        if (!r.ok || j.success === false) throw new Error(j.error || 'Calculation failed');
        el.innerHTML = `<div>Result: <strong>${fmtNum(j.result)}</strong></div>`;
      } catch (e) { el.textContent = 'Error: ' + e.message; }
    }

    function saveCustomCalcDialog() {
      const overlay = document.createElement('div');
      overlay.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.5);display:flex;align-items:center;justify-content:center;z-index:9999;';
      const dialog = document.createElement('div');
      dialog.style.cssText = 'background:var(--panel);color:var(--text);border:1px solid var(--border);border-radius:12px;width:420px;max-width:92vw;box-shadow:0 10px 30px rgba(0,0,0,0.4);';
      dialog.innerHTML = `
        <div style="padding:14px 16px;border-bottom:1px solid var(--border);font-weight:600;">Save Calculator</div>
        <div style="padding:14px 16px;">
          <div class="form-group"><label class="form-label">Name</label><input id="calcSaveName" class="form-input" type="text" placeholder="My ROI Calculator"/></div>
        </div>
        <div style="display:flex;gap:10px;justify-content:flex-end;padding:12px 16px;border-top:1px solid var(--border);">
          <button id="dlgCancel" class="btn secondary">Cancel</button>
          <button id="dlgSave" class="btn">Save</button>
        </div>`;
      overlay.appendChild(dialog);
      document.body.appendChild(overlay);
      overlay.querySelector('#dlgCancel').addEventListener('click', () => document.body.removeChild(overlay));
      overlay.querySelector('#dlgSave').addEventListener('click', async () => {
        const name = document.getElementById('calcSaveName').value.trim();
        const expression = document.getElementById('calcExpr').value.trim();
        if (!name || !expression) { alert('Please provide a name and expression'); return; }
        try {
          const r = await fetch('/api/calculators/custom/save', {
            method: 'POST', headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ name, expression })
          });
          const j = await r.json();
          if (!r.ok || j.success === false) throw new Error(j.error || 'Save failed');
          await loadSavedCalculators();
          document.body.removeChild(overlay);
        } catch (e) { alert('Error: ' + e.message); }
      });
    }

    async function loadSavedCalculators() {
      try {
        const r = await fetch('/api/calculators/custom/list');
        const j = await r.json();
        const cont = document.getElementById('savedCalcs');
        if (!r.ok || j.success === false) { cont.textContent = 'Failed to load saved calculators'; return; }
        const items = j.items || [];
        if (!items.length) { cont.innerHTML = '<div style="color:var(--sub);">No saved calculators yet</div>'; return; }
        cont.innerHTML = items.map((it, idx) => {
          const exprEsc = (it.expression || '').replace(/</g, '&lt;');
          const nameEsc = (it.name || '').replace(/</g, '&lt;');
          return `
          <div style="border:1px solid var(--border); border-radius:10px; background:var(--panel);">
            <button class="btn" style="width:100%; text-align:left; border:none; border-bottom:1px solid var(--border); border-radius:10px 10px 0 0; background:transparent; padding:12px;" onclick="toggleSavedCalc(${idx})">
              โ–ธ ${nameEsc}
            </button>
            <div id="savedBody_${idx}" style="display:none; padding:12px;">
              <div style="font-size:12px;color:var(--sub);margin-bottom:8px;">${exprEsc}</div>
              <div class="form-group"><label class="form-label">Variables</label><input id="savedVars_${idx}" class="form-input" type="text" placeholder="a=1, b=2"/></div>
              <div style="display:flex; gap:8px; flex-wrap:wrap;">
                <button class="btn" onclick="runSavedCalc(${idx}, ${JSON.stringify(it).replace(/"/g,'&quot;')})">Run</button>
                <button class="btn secondary" onclick="editSavedCalc(${idx}, '${it.id}', '${it.name.replace(/'/g, "&#39;")}', ${JSON.stringify(it.expression).replace(/"/g,'&quot;')})">Edit</button>
                <button class="btn secondary" onclick="renameSavedCalc('${it.id}', '${it.name.replace(/'/g, "&#39;")}')">Rename</button>
                <button class="btn secondary" onclick="deleteSavedCalc('${it.id}')">Delete</button>
              </div>
              <div id="savedOut_${idx}" style="margin-top:10px; font-size:13px;"></div>
            </div>
          </div>`;
        }).join('');
      } catch (e) {
        const cont = document.getElementById('savedCalcs');
        cont.textContent = 'Error loading saved calculators';
      }
    }

    async function runSavedCalc(idx, it) {
      const el = document.getElementById('savedOut_' + idx);
      const vst = document.getElementById('savedVars_' + idx).value || '';
      el.textContent = 'Calculatingโ€ฆ';
      try {
        const vars = {};
        vst.split(',').forEach(pair => { const p = pair.trim(); if (!p) return; const [k,v] = p.split('='); if (k && v!=null) vars[k.trim()] = v.trim(); });
        const r = await fetch('/api/calculators/custom/execute', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ expression: it.expression, vars }) });
        const j = await r.json();
        if (!r.ok || j.success === false) throw new Error(j.error || 'Calculation failed');
        el.innerHTML = `<div>Result: <strong>${fmtNum(j.result)}</strong></div>`;
      } catch (e) { el.textContent = 'Error: ' + e.message; }
    }

    function toggleSavedCalc(idx) {
      const body = document.getElementById('savedBody_' + idx);
      if (!body) return;
      const isHidden = (body.style.display === 'none' || !body.style.display);
      body.style.display = isHidden ? 'block' : 'none';
      // Update arrow in button
      const parent = body.parentElement;
      if (parent) {
        const btn = parent.querySelector('button.btn');
        if (btn) btn.innerHTML = (isHidden ? 'โ–พ ' : 'โ–ธ ') + btn.textContent.replace(/^โ–ธ\s|^โ–พ\s/, '');
      }
    }

    async function editSavedCalc(idx, id, name, expression) {
      const overlay = document.createElement('div');
      overlay.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.5);display:flex;align-items:center;justify-content:center;z-index:9999;';
      const dialog = document.createElement('div');
      dialog.style.cssText = 'background:var(--panel);color:var(--text);border:1px solid var(--border);border-radius:12px;width:520px;max-width:92vw;box-shadow:0 10px 30px rgba(0,0,0,0.4);';
      dialog.innerHTML = `
        <div style=\"padding:14px 16px;border-bottom:1px solid var(--border);font-weight:600;\">Edit Calculator</div>
        <div style=\"padding:14px 16px;\">
          <div class=\"form-group\"><label class=\"form-label\">Name</label><input id=\"editCalcName\" class=\"form-input\" type=\"text\" value=\"${name}\"/></div>
          <div class=\"form-group\"><label class=\"form-label\">Expression</label><textarea id=\"editCalcExpr\" class=\"form-input\" style=\"min-height:120px;\">${expression.replace(/</g,'&lt;')}</textarea></div>
        </div>
        <div style=\"display:flex;gap:10px;justify-content:flex-end;padding:12px 16px;border-top:1px solid var(--border);\">
          <button id=\"dlgCancel\" class=\"btn secondary\">Cancel</button>
          <button id=\"dlgSave\" class=\"btn\">Save</button>
        </div>`;
      overlay.appendChild(dialog);
      document.body.appendChild(overlay);
      overlay.querySelector('#dlgCancel').addEventListener('click', () => document.body.removeChild(overlay));
      overlay.querySelector('#dlgSave').addEventListener('click', async () => {
        const newName = document.getElementById('editCalcName').value.trim();
        const newExpr = document.getElementById('editCalcExpr').value.trim();
        if (!newName || !newExpr) { alert('Please provide name and expression'); return; }
        try {
          const r = await fetch(`/api/calculators/custom/${id}`, { method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ name: newName, expression: newExpr }) });
          const j = await r.json();
          if (!r.ok || j.success === false) throw new Error(j.error || 'Update failed');
          await loadSavedCalculators();
          document.body.removeChild(overlay);
        } catch (e) { alert('Error: ' + e.message); }
      });
    }

    async function renameSavedCalc(id, currentName) {
      const name = prompt('New name for calculator', currentName || '');
      if (!name) return;
      try {
        const r = await fetch(`/api/calculators/custom/${id}`, { method:'PUT', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ name }) });
        const j = await r.json();
        if (!r.ok || j.success === false) throw new Error(j.error || 'Rename failed');
        await loadSavedCalculators();
      } catch (e) { alert('Error: ' + e.message); }
    }

    async function deleteSavedCalc(id) {
      if (!confirm('Delete this calculator?')) return;
      try {
        const r = await fetch(`/api/calculators/custom/${id}`, { method:'DELETE' });
        const j = await r.json();
        if (!r.ok || j.success === false) throw new Error(j.error || 'Delete failed');
        await loadSavedCalculators();
      } catch (e) { alert('Error: ' + e.message); }
    }

    function toggleFloatChat() {
      const pane = document.getElementById('floatChat');
      const show = (pane.style.display === 'none' || !pane.style.display);
      pane.style.display = show ? 'flex' : 'none';
      if (show) {
        // Default provider to currentProvider
        const sel = document.getElementById('floatChatProvider');
        if (sel) sel.value = currentProvider;
      }
    }

    function toggleFloatChatExpand() {
      const pane = document.getElementById('floatChat');
      pane.classList.toggle('expanded');
    }

    async function sendFloatChat() {
      const input = document.getElementById('floatChatInput');
      const msg = input.value.trim();
      if (!msg) return;
      input.value = '';
      const box = document.getElementById('floatChatMessages');
      const add = (role, text) => {
        const div = document.createElement('div');
        div.className = 'bubble ' + (role === 'user' ? 'user' : 'assistant');
        if (role === 'assistant') {
          // Use existing markdown renderer for formatting
          div.innerHTML = renderMarkdown(text);
        } else {
          div.textContent = text;
        }
        box.appendChild(div);
        box.scrollTop = box.scrollHeight;
      };
      add('user', msg);
      try {
        const providerOverride = (document.getElementById('floatChatProvider') && document.getElementById('floatChatProvider').value) || currentProvider;
        const r = await fetch('/api/chat', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ provider: providerOverride, messages: [{ role:'user', content: msg }], max_tokens: 512 }) });
        const j = await r.json();
        if (!r.ok || j.error) throw new Error(j.error || 'Chat failed');
        add('assistant', j.text || '(no response)');
      } catch (e) {
        add('assistant', 'Error: ' + e.message);
      }
    }
    
    // Conversation management
    function loadConversations() {
      conversationsList.innerHTML = '';
      
      if (conversations.length === 0) {
        conversationsList.innerHTML = '<div style="color: var(--sub); font-size: 12px; text-align: center; padding: 20px;">No conversations yet</div>';
        return;
      }
      
      conversations.forEach(conv => {
        const item = document.createElement('div');
        item.className = 'conversation-item';
        if (conv.id === currentConversationId) item.classList.add('active');

        const preview = conv.messages.length > 0 
          ? conv.messages[conv.messages.length - 1].content.substring(0, 50) + '...'
          : 'New conversation';
        const sourceIcon = conv.source === 'cli' ? 'โŒจ๏ธ' : '๐Ÿ’ฌ';
        const providerInfo = conv.provider ? ` (${getProviderDisplayName(conv.provider)})` : '';

        // Build inner content; actions via context menu (right-click)
        item.innerHTML = `
          <div class="conversation-title">${sourceIcon} ${conv.title}</div>
          <div class="conversation-preview">${preview}</div>
          <div class="conversation-time">${new Date(conv.updated).toLocaleDateString()}${providerInfo}</div>
        `;
        item.onclick = () => loadConversation(conv.id);
        item.oncontextmenu = (ev) => { ev.preventDefault(); openConversationMenu(ev, '${conv.id}'); };
        conversationsList.appendChild(item);
      });
    }
    
    function startNewConversation() {
      const btn = document.getElementById('newConversationBtn');
      const originalText = btn.textContent;
      
      // Visual feedback
      btn.textContent = 'โœจ Creating...';
      btn.disabled = true;
      
      const newConv = {
        id: Date.now().toString(),
        title: 'New Conversation',
        messages: [],
        created: new Date().toISOString(),
        updated: new Date().toISOString()
      };
      
      conversations.unshift(newConv);
      currentConversationId = newConv.id;
      saveConversations();
      loadConversations();
      clearChat();
      showView('chat');
      
      // Reset button with success feedback
      setTimeout(() => {
        btn.textContent = 'โœ… Created!';
        setTimeout(() => {
          btn.textContent = originalText;
          btn.disabled = false;
        }, 1000);
      }, 200);
    }
    
    function loadConversation(id) {
      const conv = conversations.find(c => c.id === id);
      if (!conv) return;
      
      currentConversationId = id;
      clearChat();
      
      conv.messages.forEach(msg => {
        addMessage(msg.role, msg.content, false);
      });
      
      loadConversations();
      showView('chat');
    }
    
    function saveConversations() {
      localStorage.setItem('c9ai-conversations', JSON.stringify(conversations));
    }

    async function saveConversationServer(id) {
      try {
        const conv = conversations.find(c => c.id === id);
        if (!conv) return;
        const r = await fetch('/api/conversations', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(conv) });
        const j = await r.json();
        if (!r.ok) throw new Error(j.error || 'Save failed');
        // store server id for future updates
        if (j.conversation && j.conversation.id) {
          conv.serverId = j.conversation.id;
          saveConversations();
        }
        // Optional: show a small toast
        alert('Conversation saved');
      } catch (e) {
        alert('Save failed: ' + e.message);
      }
    }

    function renameConversation(id) {
      const conv = conversations.find(c => c.id === id);
      if (!conv) return;
      const name = prompt('Rename conversation', conv.title || '');
      if (!name) return;
      conv.title = name.trim();
      conv.updated = new Date().toISOString();
      // Update on server if known there
      if (conv.serverId) {
        fetch('/api/conversations/' + encodeURIComponent(conv.serverId), {
          method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: conv.title })
        }).catch(() => {});
      }
      saveConversations();
      loadConversations();
      alert('Renamed');
    }

    function deleteConversation(id) {
      if (!confirm('Delete this conversation?')) return;
      const idx = conversations.findIndex(c => c.id === id);
      if (idx === -1) return;
      conversations.splice(idx, 1);
      if (currentConversationId === id) {
        currentConversationId = conversations[0]?.id || null;
        clearChat();
        if (currentConversationId) loadConversation(currentConversationId);
      }
      saveConversations();
      loadConversations();
    }

    // Context menu logic
    let convMenuTargetId = null;
    function openConversationMenu(ev, id) {
      convMenuTargetId = id;
      const menu = document.getElementById('convMenu');
      if (!menu) return;
      // Position near cursor with viewport bounds check
      const pad = 6;
      const rect = { w: menu.offsetWidth || 200, h: menu.offsetHeight || 120 };
      let x = ev.clientX, y = ev.clientY;
      if (x + rect.w + pad > window.innerWidth) x = window.innerWidth - rect.w - pad;
      if (y + rect.h + pad > window.innerHeight) y = window.innerHeight - rect.h - pad;
      menu.style.left = x + 'px';
      menu.style.top = y + 'px';
      menu.style.display = 'block';
      // Close on outside click
      const close = (e) => { if (!menu.contains(e.target)) { menu.style.display = 'none'; document.removeEventListener('mousedown', close); } };
      document.addEventListener('mousedown', close);
    }
    function convMenuRename() { if (convMenuTargetId) { renameConversation(convMenuTargetId); hideConvMenu(); } }
    function convMenuSave() { if (convMenuTargetId) { saveConversationServer(convMenuTargetId); hideConvMenu(); } }
    function convMenuDelete() { if (convMenuTargetId) { deleteConversation(convMenuTargetId); hideConvMenu(); } }
    function hideConvMenu() { const menu = document.getElementById('convMenu'); if (menu) menu.style.display = 'none'; }
    
    function updateCurrentConversation(role, content) {
      if (!currentConversationId) {
        startNewConversation();
      }
      
      const conv = conversations.find(c => c.id === currentConversationId);
      if (!conv) return;
      
      conv.messages.push({ role, content, timestamp: new Date().toISOString() });
      conv.updated = new Date().toISOString();
      
      // Update title based on first user message
      if (conv.messages.length === 1 && role === 'user') {
        conv.title = content.substring(0, 30) + (content.length > 30 ? '...' : '');
      }
      
      saveConversations();
      loadConversations();
    }
    
    // Chat functionality
    function clearChat() {
      chatMessages.innerHTML = '';
      welcomeScreen.style.display = 'flex';
    }
    
    function addMessage(role, content, save = true) {
      if (welcomeScreen.style.display !== 'none') {
        welcomeScreen.style.display = 'none';
      }
      
      const messageDiv = document.createElement('div');
      messageDiv.className = `message ${role}`;
      
      const avatar = document.createElement('div');
      avatar.className = 'message-avatar';
      avatar.textContent = role === 'user' ? 'U' : '๐Ÿค–';
      
      const messageContent = document.createElement('div');
      messageContent.className = 'message-content';
      messageContent.innerHTML = renderMarkdown(content);
      
      const messageTime = document.createElement('div');
      messageTime.className = 'message-time';
      messageTime.textContent = new Date().toLocaleTimeString();
      
      messageDiv.appendChild(avatar);
      const contentWrapper = document.createElement('div');
      contentWrapper.appendChild(messageContent);
      contentWrapper.appendChild(messageTime);
      messageDiv.appendChild(contentWrapper);
      
      chatMessages.appendChild(messageDiv);
      chatMessages.scrollTop = chatMessages.scrollHeight;
      
      if (save) {
        updateCurrentConversation(role, content);
      }
    }
    
    function addProgressMessage(statusText) {
      console.log('Adding progress message:', statusText); // Debug log
      
      const messageId = 'progress-' + Date.now();
      const messageDiv = document.createElement('div');
      messageDiv.id = messageId;
      messageDiv.className = 'message assistant progress';
      messageDiv.style.cssText = 'opacity: 0.7; font-style: italic; background: var(--muted);';
      
      const avatar = document.createElement('div');
      avatar.className = 'message-avatar';
      avatar.textContent = 'โšก'; // Progress indicator
      avatar.style.cssText = 'animation: pulse 1.5s infinite;';
      
      const messageContent = document.createElement('div');
      messageContent.className = 'message-content';
      messageContent.innerHTML = `<span style="color: var(--primary);">${statusText}</span>`;
      
      const messageTime = document.createElement('div');
      messageTime.className = 'message-time';
      messageTime.textContent = new Date().toLocaleTimeString();
      
      messageDiv.appendChild(avatar);
      const contentWrapper = document.createElement('div');
      contentWrapper.appendChild(messageContent);
      contentWrapper.appendChild(messageTime);
      messageDiv.appendChild(contentWrapper);
      
      if (welcomeScreen.style.display !== 'none') {
        welcomeScreen.style.display = 'none';
      }
      
      chatMessages.appendChild(messageDiv);
      chatMessages.scrollTop = chatMessages.scrollHeight;
      
      return messageId;
    }
    
    // Cloud escalation confirmation helpers
    function detectIntentLocal(text) {
      const t = String(text || '').toLowerCase();
      if (t.startsWith('@executive') || t.startsWith('@business')) return 'exec';
      if (t.includes('```') || /(refactor|compile|build|test|unit test|patch|pr|typescript|python|javascript|java|golang|rust|function\s|class\s|import\s)/i.test(t)) return 'code';
      if (/(calc|calculate|sum|average|percent|roi|breakeven|interest)/i.test(t)) return 'math';
      return 'simple';
    }

    function predictCloudUse(message) {
      try {
        const mode = (settings && settings.defaultMode) ? settings.defaultMode : 'hybrid';
        const privacy = (settings && settings.privacyProfile) ? settings.privacyProfile : 'ask_before_cloud';
        const coding = (settings && settings.codingProvider) ? settings.codingProvider : 'claude';
        const defaultProv = (settings && settings.provider) ? settings.provider : 'llamacpp';
        const userOverrode = currentProvider !== defaultProv;
        const intent = detectIntentLocal(message);

        // Strict local blocks any cloud
        if (privacy === 'strict_local' || mode === 'local') {
          return { willUse: false, provider: 'llamacpp', reason: 'Strict local mode' };
        }

        // If user manually chose a cloud/hybrid provider, ask
        if (userOverrode) {
          const p = currentProvider;
          const isCloudy = ['claude','openai','gemini','deepseek'].some(x => p === x || p.startsWith(x));
          const isHybrid = /-hybrid$/.test(p);
          if (isCloudy || isHybrid) {
            return { willUse: true, provider: p, reason: isHybrid ? 'Hybrid planning via cloud' : 'User-selected cloud provider' };
          }
        }

        // Auto routing: Hybrid + code intent โ†’ cloud-hybrid unless codingProvider is local
        if (mode === 'cloud') {
          return { willUse: true, provider: coding, reason: 'Cloud-only mode' };
        }
        if (mode === 'hybrid' && intent === 'code' && coding !== 'llamacpp') {
          return { willUse: true, provider: coding + '-hybrid', reason: 'Code task in Hybrid mode' };
        }
        return { willUse: false, provider: 'llamacpp', reason: 'Local-first routing' };
      } catch (e) {
        return { willUse: false, provider: 'llamacpp', reason: 'Routing error' };
      }
    }

    function showCloudConfirm(provider, reason, message) {
      return new Promise((resolve) => {
        const overlay = document.createElement('div');
        overlay.style.cssText = 'position:fixed;inset:0;background:rgba(0,0,0,0.5);display:flex;align-items:center;justify-content:center;z-index:9999;';
        const dialog = document.createElement('div');
        dialog.style.cssText = 'background:var(--panel);color:var(--text);border:1px solid var(--border);border-radius:12px;width:520px;max-width:92vw;box-shadow:0 10px 30px rgba(0,0,0,0.4);';
        dialog.innerHTML = `
          <div style="padding:16px 18px;border-bottom:1px solid var(--border);font-weight:600;">Confirm Cloud Escalation</div>
          <div style="padding:16px 18px;">
            <div style="margin-bottom:10px;">
              <div style="font-size:14px;color:var(--sub);margin-bottom:6px;">Provider</div>
              <div style="font-size:14px;">${provider}</div>
            </div>
            <div style="margin-bottom:10px;">
              <div style="font-size:14px;color:var(--sub);margin-bottom:6px;">Reason</div>
              <div style="font-size:14px;">${reason}</div>
            </div>
            <div>
              <div style="font-size:14px;color:var(--sub);margin-bottom:6px;">Snippet to be sent</div>
              <pre style="white-space:pre-wrap;background:var(--muted);border:1px solid var(--border);padding:10px;border-radius:8px;max-height:180px;overflow:auto;">${message.slice(0,300).replace(/[&<>"']/g,(c)=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;','\'':'&#39;'}[c]))}${message.length>300?'โ€ฆ':''}</pre>
              <div style="font-size:12px;color:var(--sub);margin-top:8px;">Only minimal task text is sent for planning; tools execute locally.</div>
            </div>
          </div>
          <div style="display:flex;gap:10px;justify-content:flex-end;padding:12px 18px;border-top:1px solid var(--border);">
            <button id="cloudCancel" class="btn secondary">Cancel</button>
            <button id="cloudProceed" class="btn">Proceed</button>
          </div>`;
        overlay.appendChild(dialog);
        document.body.appendChild(overlay);
        const cleanup = () => { try { document.body.removeChild(overlay); } catch {} };
        overlay.querySelector('#cloudCancel').addEventListener('click', () => { cleanup(); resolve(false); });
        overlay.querySelector('#cloudProceed').addEventListener('click', () => { cleanup(); resolve(true); });
      });
    }

    async function sendMessage() {
      const message = chatInput.value.trim();
      if (!message) return;

      const toAgentEl = document.getElementById('toAgent');
      const isChecked = toAgentEl.checked;
      // Sigil-based task detection - clean and explicit
      const trimmedMessage = message.trim();
      const hasSigil = trimmedMessage.startsWith('@');

      // Debug logging for message tracking
      if (hasSigil) {
        if (trimmedMessage.startsWith('@executive') || trimmedMessage.startsWith('@business')) {
          addDebugEntry('info', '๐ŸŽฏ', 'Executive request detected', { message: trimmedMessage });
          // Show debug panel automatically for executive requests
          if (!debugPanelVisible) {
            toggleDebugPanel();
          }
        } else {
          addDebugEntry('info', '๐Ÿ”ง', 'Sigil command detected', { sigil: trimmedMessage.split(' ')[0] });
        }
      } else {
        addDebugEntry('info', '๐Ÿ’ญ', 'Regular chat message sent');
      }
      
      // Supported sigils for different task types
      const taskSigils = [
        '@calc', '@todo', '@task', '@email', '@search', '@compile', '@tex', 
        '@file', '@run', '@shell', '@pdf', '@image', '@video', '@github', 
        '@whatsapp', '@sms', '@create', '@write', '@read', '@convert', '@build',
        '@executive', '@business', '@generate', '@transpile', '@xml', '@xmljs'
      ];
      
      const isTask = isChecked || hasSigil;
      
      chatInput.value = '';
      sendBtn.disabled = true;
      
      addMessage('user', message);
      
      try {
        const api = 'http://127.0.0.1:8787';
        if (isTask) {
          // Ask-before-cloud confirmation (client-side prediction)
          const privacy = (settings && settings.privacyProfile) ? settings.privacyProfile : 'ask_before_cloud';
          if (privacy === 'ask_before_cloud') {
            const pred = predictCloudUse(message);
            if (pred.willUse) {
              const ok = await showCloudConfirm(pred.provider, pred.reason, message);
              if (!ok) {
                // user cancelled
                addMessage('assistant', 'โŽ Cloud escalation cancelled. You can switch to Local mode in Settings.');
                sendBtn.disabled = false;
                return;
              }
            }
          }
          // Agent SSE via GET query
          const allow = encodeURIComponent(JSON.stringify(["shell.run","script.run","fs.read","fs.write","web.search","jit"]));
          // Smart routing: if user hasn't manually overridden provider and mode allows,
          // omit provider to let server route by intent
          let providerToSend = currentProvider;
          try {
            const userSelectedProvider = currentProvider;
            const defaultProvider = (settings && settings.provider) ? settings.provider : 'llamacpp';
            const mode = (settings && settings.defaultMode) ? settings.defaultMode : 'hybrid';
            const privacy = (settings && settings.privacyProfile) ? settings.privacyProfile : 'ask_before_cloud';
            const userOverrode = userSelectedProvider !== defaultProvider;
            if (!userOverrode && mode !== 'local' && privacy !== 'strict_local') {
              providerToSend = '';
            }
          } catch (e) { /* ignore */ }
          const url = `${api}/api/agent?prompt=${encodeURIComponent(message)}${providerToSend ? `&provider=${encodeURIComponent(providerToSend)}` : ''}&allow=${allow}`;
          const es = new EventSource(url);
          let progressMessageId = null;
          
          es.onmessage = (ev) => {
            addDebugEntry('info', '๐Ÿ’ฌ', 'SSE Message received', ev.data);
            addMessage('assistant', ev.data);
          };
          
          es.addEventListener("status", (ev) => {
            addDebugEntry('info', '๐Ÿ”„', 'SSE Status update', ev.data);
            if (progressMessageId) {
              const prevMsg = document.getElementById(progressMessageId);
              if (prevMsg) prevMsg.remove();
            }
            progressMessageId = addProgressMessage(ev.data);
            
            // Parse status for executive request tracking
            try {
              const statusText = ev.data;
              if (statusText.includes('๐Ÿง  Generating function')) {
                addDebugEntry('tool', '๐Ÿง ', 'AI Function Generation started');
              } else if (statusText.includes('๐Ÿ”ง Running tool:')) {
                const toolMatch = statusText.match(/๐Ÿ”ง Running tool: (\w+)/);
                if (toolMatch) {
                  addDebugEntry('tool', '๐Ÿ”ง', `Tool execution: ${toolMatch[1]}`);
                }
              } else if (statusText.includes('Calculator execution for:')) {
                const exprMatch = statusText.match(/Calculator execution for: (.+)/);
                if (exprMatch) {
                  addDebugEntry('success', '๐Ÿงฎ', `Calculator: ${exprMatch[1]}`);
                }
              } else if (statusText.includes('Calculator result:')) {
                const resultMatch = statusText.match(/Calculator result: (.+)/);
                if (resultMatch) {
                  try {
                    const resultData = JSON.parse(resultMatch[1]);
                    const interpretation = interpretCalculationResult(resultData.expression, resultData.result);
                    addDebugEntry('success', 'โœ…', `Result: ${resultData.formatted} ${interpretation}`);
                  } catch (e) {
                    addDebugEntry('success', 'โœ…', `Result: ${resultMatch[1]}`);
                  }
                }
              } else if (statusText.includes('functions to registry')) {
                const funcMatch = statusText.match(/(\d+) functions to registry/);
                if (funcMatch) {
                  addDebugEntry('success', '๐Ÿ’พ', `Saved ${funcMatch[1]} functions to registry`);
                }
              }
            } catch (e) {
              // Silent fail for status parsing
            }
          });
          
          es.addEventListener("final", (ev) => { 
            addDebugEntry('success', '๐ŸŽ‰', 'SSE Final result received');
            if (progressMessageId) {
              const prevMsg = document.getElementById(progressMessageId);
              if (prevMsg) prevMsg.remove();
            }
            try {
              const j = JSON.parse(ev.data); 
              addMessage('assistant', j.text || ev.data);
              
              // Track executive request completion
              if (j.text && j.text.includes('Executive request processed')) {
                addDebugEntry('success', '๐ŸŽฏ', 'Executive request completed successfully');
              }
            } catch { 
              addMessage('assistant', ev.data); 
            } 
            es.close();
            setStatus('ready', 'Ready');
          });
          
          es.addEventListener("error", (ev) => {
            addDebugEntry('error', 'โŒ', 'SSE Error occurred', ev?.data);
            if (progressMessageId) {
              const prevMsg = document.getElementById(progressMessageId);
              if (prevMsg) prevMsg.remove();
            }
            addMessage('assistant', "Agent error: " + (ev?.data || "check server logs"));
            es.close();
            setStatus('error', 'Error');
          });
        } else {
          // Regular chat
          const chatProgressId = addProgressMessage('๐Ÿค– Thinking...');
          const r = await fetch(api + "/api/chat", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ provider: currentProvider, messages: [{ role:"user", content:message }] })
          });
          
          const progressMsg = document.getElementById(chatProgressId);
          if (progressMsg) progressMsg.remove();
          
          const j = await r.json().catch(()=>({}));
          if (!r.ok || j?.error) {
            addMessage('assistant', `Chat error (${currentProvider}): ${j?.error || r.statusText}`);
            setStatus('error', 'Provider Error');
          } else {
            addMessage('assistant', j?.text || j?.content || JSON.stringify(j));
          }
        }
        setStatus('ready', 'Ready');
      } catch (error) {
        addMessage('assistant', 'Sorry, an error occurred. Please check the server logs.');
        setStatus('error', 'Error');
      } finally {
        sendBtn.disabled = false;
      }
    }
    
    // Simulate AI response (replace with actual AI service call)
    async function simulateAIResponse(message) {
      await new Promise(resolve => setTimeout(resolve, 1000)); // Simulate delay
      
      const responses = [
        "I understand you're asking about: " + message.substring(0, 50) + "... Let me help you with that.",
        "That's an interesting question. Based on what you've asked, here's what I think...",
        "I can help you with that. Let me break this down for you...",
        "Great question! Here's how I would approach this problem..."
      ];
      
      return responses[Math.floor(Math.random() * responses.length)];
    }
    
    function loadQuickAction(prompt) {
      chatInput.value = prompt;
      sendMessage();
    }
    
    // Load tools list for help page
    async function loadToolsList() {
      try {
        const response = await fetch('/api/tools');
        const data = await response.json();
        const toolsList = document.getElementById('toolsList');
        
        if (data.tools && data.tools.length > 0) {
          toolsList.innerHTML = data.tools.map(tool => 
            `<div style="margin-bottom: 8px;"><strong>${tool.name}</strong>: ${tool.description || 'No description'}</div>`
          ).join('');
        } else {
          toolsList.innerHTML = 'No tools available';
        }
      } catch (error) {
        console.error('Failed to load tools:', error);
        document.getElementById('toolsList').innerHTML = 'Failed to load tools';
      }
    }
    
    // Functions view
    async function loadFunctionsList() {
      try {
        // Load function statistics
        document.getElementById('totalFunctions').textContent = '-';
        document.getElementById('activeFunctions').textContent = '-';
        document.getElementById('storageUsed').textContent = '-';
        
        // For now, show placeholder until we create the API endpoints
        document.getElementById('functionsList').innerHTML = `
          <div style="text-align: center; color: var(--sub); padding: 40px;">
            <div style="margin-bottom: 16px;">๐Ÿ“</div>
            <div style="margin-bottom: 8px;">Function management interface coming soon!</div>
            <div style="font-size: 14px;">Functions are currently managed through Smart Chat with @transpile commands.</div>
          </div>
        `;
        
        updateFunctionStats();
      } catch (error) {
        console.error('Failed to load functions:', error);
        document.getElementById('functionsList').innerHTML = '<div style="color: var(--danger); text-align: center;">Failed to load functions</div>';
      }
    }
    
    async function updateFunctionStats() {
      try {
        // This would make an API call to get function stats
        // For now, show placeholder data
        document.getElementById('totalFunctions').textContent = '2';
        document.getElementById('activeFunctions').textContent = '2';
        document.getElementById('storageUsed').textContent = '1.2KB';
      } catch (error) {
        console.error('Failed to update function stats:', error);
      }
    }
    
    function showCreateFunction() {
      // Switch to Smart Chat view and show a helpful message
      showView('chat');
      addMessage('assistant', `
        ๐Ÿš€ **Create a new function with XML-Lisp**
        
        Use the @transpile command to create functions. Here's an example:
        
        \`\`\`
        @transpile <function name="square">
          <params>
            <param name="n" type="number"/>
          </params>
          <body>
            <multiply>
              <ref>n</ref>
              <ref>n</ref>
            </multiply>
          </body>
        </function>
        \`\`\`
        
        After transpiling, you can use it with: \`@calc square(5)\`
      `);
    }
    
    function refreshFunctions() {
      if (currentView === 'functions') {
        loadFunctionsList();
      }
    }
    
    function openFunctionsDirectory() {
      addMessage('assistant', `๐Ÿ“ Functions are stored at: \`~/.c9ai/functions/\`
      
You can access them directly with:
\`\`\`bash
ls ~/.c9ai/functions/
cat ~/.c9ai/functions/test.xmlp
\`\`\`

Each function consists of:
- \`.xmlp\` file (XML-Lisp source)
- \`.js\` file (transpiled JavaScript)
- \`registry.json\` (metadata)`);
    }
    
    // Event listeners
    function setupEventListeners() {
      // Quick health check
      document.getElementById('btnHealth')?.addEventListener('click', async ()=>{
        try {
          const r = await fetch('/api/health');
          const j = await r.json();
          addMessage('assistant', `llama: ${j.llama ? 'ok' : 'down'} ยท claude key: ${j.claude} ยท gemini key: ${j.gemini} ยท openai key: ${j.openai}`);
        } catch(e) {
          addMessage('assistant', 'Health check failed');
        }
      });
      // Navigation
      document.querySelectorAll('.nav-item').forEach(item => {
        item.addEventListener('click', function() {
          const view = this.dataset.view;
          if (view) showView(view);
        });
      });
      
      // Provider switcher
      document.querySelectorAll('[data-provider]').forEach(btn => {
        btn.addEventListener('click', function() {
          currentProvider = this.dataset.provider;
          updateProviderButtons();
          setStatus('ready', 'Ready'); // This will show the provider name
        });
      });
      
      // Chat input
      chatInput.addEventListener('keydown', function(e) {
        if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
          e.preventDefault();
          sendMessage();
        }
      });
      
      chatInput.addEventListener('input', function() {
        this.style.height = 'auto';
        this.style.height = Math.min(this.scrollHeight, 120) + 'px';
      });
      
      // Keyboard shortcuts
      document.addEventListener('keydown', function(e) {
        if (e.ctrlKey || e.metaKey) {
          switch(e.key) {
            case 'n':
              e.preventDefault();
              startNewConversation();
              break;
            case ',':
              e.preventDefault();
              showSettings();
              break;
            case 'd':
              e.preventDefault();
              toggleDebugPanel();
              addDebugEntry('info', 'โŒจ๏ธ', 'Debug panel toggled via keyboard shortcut (Ctrl+D)');
              break;
          }
        }
        
        // Function key shortcuts
        switch(e.key) {
          case 'F12':
            e.preventDefault();
            toggleDebugPanel();
            addDebugEntry('info', '๐Ÿ”ง', 'Debug panel toggled via F12');
            break;
        }
      });
    }
    
    // CLI Access Functions
    function launchCLI(mode) {
      // Get current provider from settings
      const currentProvider = settings.provider || 'llamacpp';
      
      let command;
      const providerFlag = currentProvider !== 'llamacpp' ? ` --provider ${currentProvider}` : '';
      
      switch(mode) {
        case 'interactive':
          command = `c9ai${providerFlag}`;
          break;
        case 'agent':
          command = `c9ai agent${providerFlag}`;
          break;
        case 'models':
          command = 'c9ai models list';
          break;
        case 'stack':
          command = 'c9ai stack';
          break;
        default:
          command = `c9ai${providerFlag}`;
      }
      
      // Create instruction modal
      const modal = document.createElement('div');
      modal.style.cssText = `
        position: fixed; top: 0; left: 0; right: 0; bottom: 0;
        background: rgba(0,0,0,0.8); display: flex; align-items: center; justify-content: center;
        z-index: 10000;
      `;
      
      const content = document.createElement('div');
      content.style.cssText = `
        background: var(--panel); border-radius: 12px; padding: 30px;
        max-width: 600px; width: 90%; border: 1px solid var(--border);
      `;
      
      content.innerHTML = `
        <h3 style="margin-bottom: 20px;">๐Ÿ–ฅ๏ธ Launch CLI</h3>
        <p style="margin-bottom: 15px;">Open your terminal and run:</p>
        <div style="background: var(--muted); padding: 15px; border-radius: 8px; font-family: monospace; font-size: 14px; margin-bottom: 20px; color: var(--primary);">
          ${command}
        </div>
        <div style="margin-bottom: 20px; padding: 12px; background: var(--primary-muted); border-radius: 6px; border-left: 4px solid var(--primary);">
          <strong>Provider:</strong> ${getProviderDisplayName(currentProvider)}<br>
          <small style="opacity: 0.8;">CLI will use your current UI provider settings</small>
        </div>
        <div style="margin-bottom: 20px; font-size: 14px; color: var(--sub);">
          <strong>Installation required?</strong> If the command doesn't work, you may need to install the CLI globally:
          <code style="background: var(--muted); padding: 2px 6px; border-radius: 3px; margin: 0 4px;">npm install -g .</code>
        </div>
        ${currentProvider !== 'llamacpp' ? `
          <div style="margin-bottom: 20px; padding: 12px; background: var(--muted); border-radius: 8px; font-size: 13px;">
            <strong>โš ๏ธ API Key Required:</strong> Your CLI will use <strong>${getProviderDisplayName(currentProvider)}</strong>. 
            Make sure you have the appropriate API key set as an environment variable or the CLI will fall back to local models.
            <br><br>
            <strong>Environment variables needed:</strong>
            ${currentProvider === 'claude' || currentProvider.includes('claude') ? '<br>โ€ข ANTHROPIC_API_KEY' : ''}
            ${currentProvider === 'openai' || currentProvider.includes('openai') ? '<br>โ€ข OPENAI_API_KEY' : ''}
            ${currentProvider === 'gemini' || currentProvider.includes('gemini') ? '<br>โ€ข GEMINI_API_KEY' : ''}
            ${currentProvider === 'deepseek' || currentProvider.includes('deepseek') ? '<br>โ€ข DEEPSEEK_API_KEY' : ''}
          </div>
        ` : ''}
        <div style="display: flex; gap: 12px; justify-content: flex-end;">
          <button class="btn secondary" onclick="this.closest('[style*=fixed]').remove()">Close</button>
          ${currentProvider !== 'llamacpp' ? `
            <button class="btn secondary" onclick="showEnvSetup('${currentProvider}')">๐Ÿ”ง Setup Env</button>
          ` : ''}
          <button class="btn" onclick="copyCLICommand('${command}')">๐Ÿ“‹ Copy Command</button>
        </div>
      `;
      
      modal.appendChild(content);
      document.body.appendChild(modal);
      
      // Track CLI launch with enhanced conversation sync
      trackCLISessionEnhanced({
        command: command,
        provider: currentProvider,
        timestamp: new Date().toISOString(),
        launchedFrom: 'ui'
      });
    }
    
    function copyCLICommand(command) {
      navigator.clipboard.writeText(command).then(() => {
        // Show feedback
        const btn = event.target;
        const originalText = btn.textContent;
        btn.textContent = 'โœ… Copied!';
        setTimeout(() => {
          btn.textContent = originalText;
        }, 2000);
      });
    }
    
    function getProviderDisplayName(id) {
      if (id.endsWith('-hybrid')) {
        const base = id.replace('-hybrid', '');
        return `${base.charAt(0).toUpperCase() + base.slice(1)} AI + Local Tools`;
      }
      switch(id) {
        case 'claude': return 'Claude AI';
        case 'gemini': return 'Gemini AI';
        case 'openai': return 'OpenAI';
        case 'deepseek': return 'DeepSeek AI';
        case 'llamacpp': return 'Local Model (llama.cpp)';
        case 'ollama': return 'Local Model (Ollama)';
        default: return id;
      }
    }
    
    function showEnvSetup(provider) {
      const apiKey = getApiKeyFromSettings(provider);
      const envVars = getEnvironmentVariables(provider);
      
      const modal = document.createElement('div');
      modal.style.cssText = `
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0, 0, 0, 0.8);
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 10000;
      `;
      
      const content = document.createElement('div');
      content.style.cssText = `
        background: var(--panel);
        border: 1px solid var(--border);
        border-radius: 12px;
        padding: 24px;
        max-width: 600px;
        width: 90%;
        max-height: 80vh;
        overflow-y: auto;
      `;
      
      content.innerHTML = `
        <h3 style="margin-bottom: 16px;">๐Ÿ”ง Environment Setup for ${getProviderDisplayName(provider)}</h3>
        
        ${apiKey ? `
          <div style="margin-bottom: 20px; padding: 12px; background: var(--ok); color: white; border-radius: 8px; font-size: 14px;">
            โœ… API key is configured in UI settings. You can copy the export commands below to use the same key in your terminal.
          </div>
        ` : `
          <div style="margin-bottom: 20px; padding: 12px; background: var(--danger); color: white; border-radius: 8px; font-size: 14px;">
            โš ๏ธ No API key found in UI settings. Please add it in Settings first, or set up environment variables manually.
          </div>
        `}
        
        <div style="margin-bottom: 20px;">
          <h4 style="margin-bottom: 10px;">Terminal Commands:</h4>
          <p style="color: var(--sub); font-size: 14px; margin-bottom: 12px;">
            Copy and paste these commands in your terminal before running the CLI:
          </p>
          
          ${envVars.map(env => `
            <div style="margin-bottom: 12px;">
              <strong>${env.name}:</strong>
              <div style="background: var(--bg); padding: 12px; border-radius: 6px; font-family: monospace; margin-top: 4px; position: relative;">
                <span style="font-size: 12px; color: var(--sub);">Bash/Zsh:</span>
                <br>
                <code>export ${env.name}="${apiKey || 'your_api_key_here'}"</code>
                <br><br>
                <span style="font-size: 12px; color: var(--sub);">PowerShell:</span>
                <br>
                <code>$env:${env.name}="${apiKey || 'your_api_key_here'}"</code>
                <button onclick="copyEnvCommand('export ${env.name}=\\\"${apiKey || 'your_api_key_here'}\\\"')" 
                        style="position: absolute; top: 8px; right: 8px; background: var(--primary); color: white; border: none; padding: 4px 8px; border-radius: 4px; font-size: 11px; cursor: pointer;">
                  ๐Ÿ“‹ Copy
                </button>
              </div>
            </div>
          `).join('')}
        </div>
        
        <div style="margin-bottom: 20px; padding: 12px; background: var(--muted); border-radius: 8px; font-size: 13px;">
          <strong>๐Ÿ’ก Pro Tip:</strong> Add these export commands to your shell profile (.bashrc, .zshrc, or PowerShell profile) 
          to make them permanent.
        </div>
        
        <div style="display: flex; gap: 12px; justify-content: flex-end;">
          <button class="btn secondary" onclick="this.closest('[style*=fixed]').remove()">Close</button>
          ${apiKey ? `
            <button class="btn" onclick="copyAllEnvCommands('${provider}')">๐Ÿ“‹ Copy All Commands</button>
          ` : ''}
        </div>
      `;
      
      modal.appendChild(content);
      document.body.appendChild(modal);
    }
    
    function getApiKeyFromSettings(provider) {
      const cleanProvider = provider.replace('-hybrid', '');
      switch(cleanProvider) {
        case 'claude': return settings.apiKeys?.ANTHROPIC_API_KEY;
        case 'openai': return settings.apiKeys?.OPENAI_API_KEY;
        case 'gemini': return settings.apiKeys?.GEMINI_API_KEY;
        case 'deepseek': return settings.apiKeys?.DEEPSEEK_API_KEY;
        default: return null;
      }
    }
    
    function getEnvironmentVariables(provider) {
      const cleanProvider = provider.replace('-hybrid', '');
      switch(cleanProvider) {
        case 'claude': return [{ name: 'ANTHROPIC_API_KEY', description: 'Claude AI API key' }];
        case 'openai': return [{ name: 'OPENAI_API_KEY', description: 'OpenAI API key' }];
        case 'gemini': return [{ name: 'GEMINI_API_KEY', description: 'Google Gemini API key' }];
        case 'deepseek': return [{ name: 'DEEPSEEK_API_KEY', description: 'DeepSeek API key' }];
        default: return [];
      }
    }
    
    function copyEnvCommand(command) {
      navigator.clipboard.writeText(command).then(() => {
        const btn = event.target;
        const originalText = btn.textContent;
        btn.textContent = 'โœ… Copied!';
        setTimeout(() => {
          btn.textContent = originalText;
        }, 2000);
      });
    }
    
    function copyAllEnvCommands(provider) {
      const apiKey = getApiKeyFromSettings(provider);
      const envVars = getEnvironmentVariables(provider);
      const commands = envVars.map(env => `export ${env.name}="${apiKey}"`).join('\n');
      
      navigator.clipboard.writeText(commands).then(() => {
        const btn = event.target;
        const originalText = btn.textContent;
        btn.textContent = 'โœ… All Copied!';
        setTimeout(() => {
          btn.textContent = originalText;
        }, 2000);
      });
    }
    
    // CLI Session Tracking
    let cliSessions = [];
    
    function trackCLISession(session) {
      cliSessions.unshift(session);
      // Keep only last 50 sessions
      if (cliSessions.length > 50) {
        cliSessions = cliSessions.slice(0, 50);
      }
      saveCLISessions();
      refreshCLISessions();
    }
    
    function saveCLISessions() {
      try {
        localStorage.setItem('c9ai-cli-sessions', JSON.stringify(cliSessions));
      } catch (e) {
        console.warn('Failed to save CLI sessions:', e);
      }
    }
    
    function loadCLISessions() {
      try {
        const saved = localStorage.getItem('c9ai-cli-sessions');
        if (saved) {
          cliSessions = JSON.parse(saved);
        }
      } catch (e) {
        console.warn('Failed to load CLI sessions:', e);
        cliSessions = [];
      }
    }
    
    function refreshCLISessions() {
      const container = document.getElementById('cliSessions');
      if (!container) return;
      
      if (cliSessions.length === 0) {
        container.innerHTML = `
          <div style="text-align: center; color: var(--sub); padding: 40px;">
            No CLI sessions tracked yet. CLI sessions will appear here once you start using the CLI.
          </div>
        `;
        return;
      }
      
      const sessionsHTML = cliSessions.map(session => {
        const statusColor = session.status === 'active' ? 'var(--ok)' : session.status === 'launched' ? 'var(--primary)' : 'var(--sub)';
        const statusText = session.status || 'completed';
        const hasConversation = conversations.find(c => c.sessionId === session.sessionId);
        
        return `
          <div style="border-bottom: 1px solid var(--border); padding: 12px 0;">
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px;">
              <code style="background: var(--bg); padding: 4px 8px; border-radius: 4px; font-size: 13px;">${session.command}</code>
              <small style="color: var(--sub);">${new Date(session.timestamp).toLocaleString()}</small>
            </div>
            <div style="display: flex; justify-content: space-between; align-items: center;">
              <div style="font-size: 12px; color: var(--sub);">
                Provider: ${getProviderDisplayName(session.provider)} | Source: ${session.launchedFrom}
                <span style="color: ${statusColor}; margin-left: 8px;">โ— ${statusText}</span>
              </div>
              ${hasConversation ? `
                <button onclick="loadConversation('cli-${session.sessionId}')" style="background: var(--primary); color: white; border: none; padding: 4px 8px; border-radius: 4px; font-size: 11px; cursor: pointer;">
                  View Chat
                </button>
              ` : ''}
            </div>
          </div>
        `;
      }).join('');
      
      container.innerHTML = sessionsHTML;
    }
    
    function clearCLISessions() {
      if (confirm('Clear all CLI session history?')) {
        cliSessions = [];
        saveCLISessions();
        refreshCLISessions();
      }
    }
    
    // Load CLI sessions on page load
    loadCLISessions();
    
    // CLI Conversation Sync Functions
    function createCLIConversation(sessionId, command, provider) {
      const newConv = {
        id: `cli-${sessionId}`,
        title: `CLI: ${command}`,
        messages: [],
        created: new Date().toISOString(),
        updated: new Date().toISOString(),
        source: 'cli',
        provider: provider,
        sessionId: sessionId
      };
      
      conversations.unshift(newConv);
      saveConversations();
      loadConversations();
      return newConv;
    }
    
    function syncCLIMessage(sessionId, role, content) {
      let conv = conversations.find(c => c.sessionId === sessionId && c.source === 'cli');
      
      if (!conv) {
        // Create CLI conversation if it doesn't exist
        const session = cliSessions.find(s => s.sessionId === sessionId);
        if (session) {
          conv = createCLIConversation(sessionId, session.command, session.provider);
        } else {
          return; // Can't sync without session info
        }
      }
      
      conv.messages.push({ 
        role, 
        content, 
        timestamp: new Date().toISOString(),
        source: 'cli'
      });
      conv.updated = new Date().toISOString();
      
      saveConversations();
      loadConversations();
      
      // If this CLI conversation is currently active, update the display
      if (currentConversationId === conv.id) {
        displayConversation(conv);
      }
    }
    
    function pollCLIConversations() {
      // This would connect to a WebSocket or polling endpoint to get CLI conversations
      // For now, this is a placeholder for future implementation
      fetch('/api/cli/conversations')
        .then(response => response.json())
        .then(data => {
          if (data.conversations) {
            data.conversations.forEach(cliConv => {
              syncCLIMessage(cliConv.sessionId, cliConv.role, cliConv.content);
            });
          }
        })
        .catch(error => {
          // Silently handle errors - CLI might not be running
          console.debug('CLI conversation sync not available:', error);
        });
    }
    
    function markCLISessionActive(sessionId) {
      // Update CLI session to track when it becomes active
      const session = cliSessions.find(s => s.sessionId === sessionId);
      if (session) {
        session.status = 'active';
        session.lastActivity = new Date().toISOString();
        saveCLISessions();
        refreshCLISessions();
        
        // Create conversation entry immediately
        createCLIConversation(sessionId, session.command, session.provider);
      }
    }
    
    // Enhanced CLI session tracking with conversation sync
    function trackCLISessionEnhanced(session) {
      // Add unique session ID for tracking
      session.sessionId = session.sessionId || `cli-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
      session.status = 'launched';
      
      trackCLISession(session);
      
      // Start polling for this session's conversations after a brief delay
      setTimeout(() => {
        markCLISessionActive(session.sessionId);
      }, 2000);
      
      return session.sessionId;
    }
    
    // Start polling for CLI conversations every 5 seconds (when in CLI view)
    setInterval(() => {
      if (currentView === 'cli') {
        pollCLIConversations();
      }
    }, 5000);
    
    // =================================
    // TOOL PACKAGE MANAGER UI FUNCTIONS
    // =================================
    
    let toolsData = { catalog: null, stats: null };
    let currentToolFilter = 'all';

    // Load tools data when tools view is opened
    // Package Manager Functions
    let currentToolSource = 'curated';
    let packageManagers = [];
    
    async function switchToolSource(source) {
      currentToolSource = source;
      
      // Update active tab
      document.querySelectorAll('[data-source]').forEach(btn => {
        btn.classList.toggle('active', btn.dataset.source === source);
      });
      
      // Show/hide relevant sections
      const packageSearch = document.getElementById('packageSearch');
      const categoryFilters = document.querySelector('.category-filters');
      const toolGrid = document.getElementById('toolGrid');
      
      if (source === 'packages') {
        packageSearch.style.display = 'block';
        categoryFilters.style.display = 'none';
        await loadPackageManagers();
        toolGrid.innerHTML = `
          <div style="grid-column: 1 / -1; text-align: center; padding: 40px; color: var(--sub);">
            Use the search box above to find packages across all available package managers.
            <br><br>
            Examples: "pandoc", "ffmpeg", "python requests", "node express"
          </div>
        `;
      } else if (source === 'installed') {
        packageSearch.style.display = 'none';
        categoryFilters.style.display = 'none';
        await loadInstalledPackages();
      } else {
        packageSearch.style.display = 'none';
        categoryFilters.style.display = 'block';
        await loadToolsData();
      }
    }
    
    async function loadPackageManagers() {
      try {
        const response = await fetch('/api/packages/managers');
        if (response.ok) {
          const data = await response.json();
          packageManagers = data.managers;
          displayPackageManagerStatus(data);
        } else {
          throw new Error('Failed to load package managers');
        }
      } catch (error) {
        console.error('Error loading package managers:', error);
        document.getElementById('packageManagerStatus').innerHTML = `
          <div style="color: var(--danger);">โŒ Failed to load package managers</div>
        `;
      }
    }
    
    function displayPackageManagerStatus(data) {
      const statusDiv = document.getElementById('packageManagerStatus');
      const { managers, stats, totalEstimatedPackages } = data;
      
      if (managers.length === 0) {
        statusDiv.innerHTML = `
          <div style="color: var(--danger); text-align: center; padding: 20px;">
            โŒ No package managers detected. Please install Homebrew, npm, pip, or other package managers.
          </div>
        `;
        return;
      }
      
      const managerTags = managers.map(m => {
        const typeColors = {
          system: 'var(--primary)',
          language: 'var(--ok)', 
          universal: 'var(--sub)'
        };
        
        return `
          <span style="
            display: inline-flex; 
            align-items: center; 
            gap: 6px; 
            padding: 6px 12px; 
            background: var(--muted); 
            border-radius: 16px; 
            border: 1px solid ${typeColors[m.type] || 'var(--border)'};
            font-size: 12px;
            color: var(--text);
          ">
            <span style="color: ${typeColors[m.type]};">โ—</span>
            ${m.name} v${m.version}
            <span style="opacity: 0.7;">(${m.ecosystem})</span>
          </span>
        `;
      }).join('');
      
      statusDiv.innerHTML = `
        <div style="display: flex; flex-wrap: wrap; gap: 8px; align-items: center;">
          ${managerTags}
          <span style="margin-left: 12px; padding: 6px 12px; background: var(--primary); color: white; border-radius: 16px; font-size: 12px; font-weight: 500;">
            ~${totalEstimatedPackages.toLocaleString()} packages available
          </span>
        </div>
      `;
    }
    
    async function searchPackages() {
      const query = document.getElementById('packageSearchInput').value.trim();
      if (!query) return;
      
      const resultsDiv = document.getElementById('searchResults');
      const packageResults = document.getElementById('packageResults');
      const countDiv = document.getElementById('searchResultsCount');
      
      // Show loading state
      resultsDiv.style.display = 'block';
      packageResults.innerHTML = `
        <div style="grid-column: 1 / -1; text-align: center; padding: 40px; color: var(--sub);">
          ๐Ÿ” Searching for "${query}" across all package managers...
        </div>
      `;
      
      try {
        const response = await fetch(`/api/packages/search?q=${encodeURIComponent(query)}&limit=20`);
        if (response.ok) {
          const data = await response.json();
          displaySearchResults(data);
        } else {
          throw new Error('Search failed');
        }
      } catch (error) {
        console.error('Package search error:', error);
        packageResults.innerHTML = `
          <div style="grid-column: 1 / -1; text-align: center; padding: 40px; color: var(--danger);">
            โŒ Search failed. Please try again.
          </div>
        `;
      }
    }
    
    function displaySearchResults(data) {
      const { packages, sources, total, query } = data;
      const packageResults = document.getElementById('packageResults');
      const countDiv = document.getElementById('searchResultsCount');
      
      countDiv.textContent = `Found ${total} packages from ${sources.length} sources`;
      
      if (packages.length === 0) {
        packageResults.innerHTML = `
          <div style="grid-column: 1 / -1; text-align: center; padding: 40px; color: var(--sub);">
            No packages found for "${query}".
            <br><br>
            Try searching for:
            <br>โ€ข System tools: pandoc, ffmpeg, git, curl
            <br>โ€ข Python packages: requests, pandas, numpy  
            <br>โ€ข Node.js packages: express, react, lodash
            <br>โ€ข Development tools: docker, terraform, kubernetes
          </div>
        `;
        return;
      }
      
      packageResults.innerHTML = packages.map(pkg => `
        <div style="
          background: var(--panel); 
          border: 1px solid var(--border); 
          border-radius: 8px; 
          padding: 20px;
          transition: all 0.2s ease;
        " onmouseover="this.style.borderColor='var(--primary)'" onmouseout="this.style.borderColor='var(--border)'">
          <div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 12px;">
            <div>
              <h3 style="margin: 0 0 4px 0; color: var(--text);">${pkg.name}</h3>
              <div style="font-size: 12px; color: var(--sub);">
                ${pkg.manager} โ€ข ${pkg.source} โ€ข Score: ${pkg.relevanceScore}
              </div>
            </div>
            <button 
              class="btn primary" 
              style="font-size: 12px; padding: 6px 12px;" 
              onclick="installPackage('${pkg.name}', '${pkg.manager}')"
            >
              ๐Ÿ“ฆ Install
            </button>
          </div>
          
          <p style="margin: 0 0 12px 0; color: var(--sub); font-size: 14px; line-height: 1.4;">
            ${pkg.description}
          </p>
          
          <div style="
            background: var(--muted); 
            padding: 8px 12px; 
            border-radius: 4px; 
            font-family: monospace; 
            font-size: 12px; 
            color: var(--text);
            border-left: 3px solid var(--primary);
          ">
            ${pkg.installCommand}
          </div>
        </div>
      `).join('');
    }
    
    async function installPackage(packageName, manager) {
      const installBtn = event.target;
      const originalText = installBtn.innerHTML;
      
      // Update button to show loading
      installBtn.innerHTML = 'โณ Installing...';
      installBtn.disabled = true;
      
      try {
        const response = await fetch('/api/packages/install', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ packageName, manager })
        });
        
        const result = await response.json();
        
        if (result.success) {
          installBtn.innerHTML = 'โœ… Installed';
          installBtn.style.background = 'var(--ok)';
          
          // Show success message
          showNotification(`โœ… Successfully installed ${packageName}`, 'success');
          
          // Refresh system tools after installation
          setTimeout(() => {
            if (typeof refreshToolData === 'function') {
              refreshToolData();
            }
          }, 2000);
          
        } else {
          throw new Error(result.error || 'Installation failed');
        }
        
      } catch (error) {
        console.error('Installation error:', error);
        installBtn.innerHTML = 'โŒ Failed';
        installBtn.style.background = 'var(--danger)';
        
        showNotification(`โŒ Failed to install ${packageName}: ${error.message}`, 'error');
        
        // Reset button after delay
        setTimeout(() => {
          installBtn.innerHTML = originalText;
          installBtn.disabled = false;
          installBtn.style.background = '';
        }, 3000);
      }
    }
    
    async function loadInstalledPackages() {
      const toolGrid = document.getElementById('toolGrid');
      toolGrid.innerHTML = `
        <div style="grid-column: 1 / -1; text-align: center; padding: 40px; color: var(--sub);">
          ๐Ÿ“ฆ Loading installed packages...
        </div>
      `;
      
      try {
        const response = await fetch('/api/packages/installed');
        if (response.ok) {
          const data = await response.json();
          displayInstalledPackages(data.installed);
        } else {
          throw new Error('Failed to load installed packages');
        }
      } catch (error) {
        console.error('Error loading installed packages:', error);
        toolGrid.innerHTML = `
          <div style="grid-column: 1 / -1; text-align: center; padding: 40px; color: var(--danger);">
            โŒ Failed to load installed packages
          </div>
        `;
      }
    }
    
    function displayInstalledPackages(installed) {
      const toolGrid = document.getElementById('toolGrid');
      const allPackages = [];
      
      // Aggregate packages from all managers
      Object.entries(installed).forEach(([manager, packages]) => {
        packages.forEach(pkg => {
          allPackages.push({ ...pkg, manager });
        });
      });
      
      if (allPackages.length === 0) {
        toolGrid.innerHTML = `
          <div style="grid-column: 1 / -1; text-align: center; padding: 40px; color: var(--sub);">
            No installed packages found.
            <br><br>
            Switch to the "System Packages" tab to install new tools.
          </div>
        `;
        return;
      }
      
      toolGrid.innerHTML = allPackages.slice(0, 50).map(pkg => `
        <div style="
          background: var(--panel); 
          border: 1px solid var(--border); 
          border-radius: 8px; 
          padding: 20px;
          transition: all 0.2s ease;
        ">
          <div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 12px;">
            <div>
              <h3 style="margin: 0 0 4px 0; color: var(--text);">${pkg.name}</h3>
              <div style="font-size: 12px; color: var(--sub);">
                ${pkg.manager} โ€ข Version: ${pkg.version}
              </div>
            </div>
            <span style="
              padding: 4px 8px; 
              background: var(--ok); 
              color: white; 
              border-radius: 12px; 
              font-size: 10px;
              font-weight: 500;
            ">
              โœ… INSTALLED
            </span>
          </div>
        </div>
      `).join('');
    }
    
    function showNotification(message, type = 'info') {
      // Create notification element
      const notification = document.createElement('div');
      notification.style.cssText = `
        position: fixed;
        top: 20px;
        right: 20px;
        padding: 12px 16px;
        background: ${type === 'success' ? 'var(--ok)' : type === 'error' ? 'var(--danger)' : 'var(--primary)'};
        color: white;
        border-radius: 6px;
        z-index: 10000;
        font-size: 14px;
        max-width: 400px;
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
      `;
      notification.textContent = message;
      
      document.body.appendChild(notification);
      
      // Remove after 5 seconds
      setTimeout(() => {
        if (notification.parentNode) {
          notification.parentNode.removeChild(notification);
        }
      }, 5000);
    }
    
    async function loadToolsData() {
      if (currentView !== 'tools') return;
      
      try {
        // Load catalog and stats in parallel
        const [catalogResponse, statsResponse] = await Promise.all([
          fetch('/api/tools/catalog'),
          fetch('/api/tools/stats')
        ]);
        
        if (catalogResponse.ok && statsResponse.ok) {
          toolsData.catalog = await catalogResponse.json();
          toolsData.stats = await statsResponse.json();
          
          displayToolStats();
          displayCategoryFilters();
          displayTools();
        } else {
          displayToolError('Failed to load tools data');
        }
      } catch (error) {
        console.error('Failed to load tools:', error);
        displayToolError('Error loading tools: ' + error.message);
      }
    }

    function displayToolStats() {
      if (!toolsData.stats) return;
      
      document.getElementById('totalTools').textContent = toolsData.stats.total || 0;
      document.getElementById('installedTools').textContent = toolsData.stats.installed || 0;
      document.getElementById('availableTools').textContent = toolsData.stats.available || 0;
      document.getElementById('builtinTools').textContent = toolsData.stats.builtin || 0;
    }

    function displayCategoryFilters() {
      if (!toolsData.catalog) return;
      
      const filtersContainer = document.getElementById('categoryFilters');
      const categories = toolsData.catalog.categories || {};
      
      let filtersHTML = `
        <button class="btn pill ${currentToolFilter === 'all' ? 'active' : ''}" data-category="all">
          All Tools (${toolsData.stats.total || 0})
        </button>
        <button class="btn pill ${currentToolFilter === 'available' ? 'active' : ''}" data-category="available">
          Available (${toolsData.stats.available || 0})
        </button>
        <button class="btn pill ${currentToolFilter === 'installed' ? 'active' : ''}" data-category="installed">
          Installed (${toolsData.stats.installed || 0})
        </button>
      `;
      
      // Add category filters
      Object.entries(categories).forEach(([catId, category]) => {
        const count = toolsData.stats.categories?.[catId]?.total || 0;
        filtersHTML += `
          <button class="btn pill ${currentToolFilter === catId ? 'active' : ''}" data-category="${catId}">
            ${category.icon} ${category.name} (${count})
          </button>
        `;
      });
      
      filtersContainer.innerHTML = filtersHTML;
      
      // Add click handlers
      filtersContainer.querySelectorAll('[data-category]').forEach(btn => {
        btn.addEventListener('click', function() {
          currentToolFilter = this.dataset.category;
          displayCategoryFilters();
          displayTools();
        });
      });
    }

    function displayTools() {
      if (!toolsData.catalog) return;
      
      const toolGrid = document.getElementById('toolGrid');
      let tools = toolsData.catalog.tools || [];
      
      // Filter tools based on current filter
      if (currentToolFilter === 'available') {
        tools = tools.filter(tool => tool.status === 'available');
      } else if (currentToolFilter === 'installed') {
        tools = tools.filter(tool => tool.status === 'installed' || tool.builtin);
      } else if (currentToolFilter !== 'all') {
        tools = tools.filter(tool => tool.category === currentToolFilter);
      }
      
      if (tools.length === 0) {
        toolGrid.innerHTML = `
          <div style="grid-column: 1 / -1; text-align: center; padding: 40px; color: var(--sub);">
            No tools found for the selected filter.
          </div>
        `;
        return;
      }
      
      const toolsHTML = tools.map(tool => createToolCard(tool)).join('');
      toolGrid.innerHTML = toolsHTML;
    }

    function createToolCard(tool) {
      const isInstalled = tool.status === 'installed' || tool.builtin;
      const categoryInfo = toolsData.catalog.categories[tool.category] || {};
      const categoryIcon = categoryInfo.icon || '๐Ÿ”ง';
      
      return `
        <div class="tool-card" style="
          background: var(--panel);
          border: 1px solid var(--border);
          border-radius: 12px;
          padding: 20px;
          transition: all 0.2s ease;
          position: relative;
        " onmouseover="this.style.borderColor='var(--primary)'" onmouseout="this.style.borderColor='var(--border)'">
          
          <!-- Tool Header -->
          <div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 12px;">
            <div>
              <h3 style="margin: 0 0 4px 0; font-size: 16px; color: var(--text);">${tool.name}</h3>
              <div style="font-size: 12px; color: var(--sub);">
                ${categoryIcon} ${categoryInfo.name || tool.category} โ€ข v${tool.version}
              </div>
            </div>
            <div style="display: flex; align-items: center; gap: 8px;">
              ${tool.builtin ? '<span style="background: var(--muted); color: var(--text); padding: 2px 8px; border-radius: 12px; font-size: 10px; font-weight: 500;">BUILT-IN</span>' : ''}
              ${isInstalled ? '<span style="background: var(--ok); color: white; padding: 2px 8px; border-radius: 12px; font-size: 10px; font-weight: 500;">INSTALLED</span>' : '<span style="background: var(--primary); color: white; padding: 2px 8px; border-radius: 12px; font-size: 10px; font-weight: 500;">AVAILABLE</span>'}
            </div>
          </div>
          
          <!-- Tool Description -->
          <p style="margin: 0 0 16px 0; color: var(--sub); font-size: 14px; line-height: 1.4;">
            ${tool.description}
          </p>
          
          <!-- Tool Details -->
          <div style="margin-bottom: 16px;">
            ${tool.dependencies && tool.dependencies.length > 0 ? `
              <div style="margin-bottom: 8px;">
                <strong style="font-size: 12px; color: var(--text);">Dependencies:</strong>
                <span style="font-size: 12px; color: var(--sub);">${tool.dependencies.join(', ')}</span>
              </div>
            ` : ''}
            ${tool.author ? `
              <div style="margin-bottom: 4px;">
                <strong style="font-size: 12px; color: var(--text);">Author:</strong>
                <span style="font-size: 12px; color: var(--sub);">${tool.author}</span>
              </div>
            ` : ''}
          </div>
          
          <!-- Tool Actions -->
          <div style="display: flex; gap: 8px;">
            ${isInstalled ? `
              <button class="btn secondary" onclick="showToolDetails('${tool.id}')" style="flex: 1; font-size: 12px; padding: 8px;">
                ๐Ÿ“‹ Details
              </button>
              ${tool.builtin ? '' : `
                <button class="btn" onclick="uninstallTool('${tool.id}')" style="background: var(--danger); flex: 1; font-size: 12px; padding: 8px;">
                  ๐Ÿ—‘๏ธ Remove
                </button>
              `}
            ` : `
              <button class="btn secondary" onclick="showToolDetails('${tool.id}')" style="flex: 1; font-size: 12px; padding: 8px;">
                ๐Ÿ“‹ Details
              </button>
              <button class="btn" onclick="installTool('${tool.id}')" style="flex: 1; font-size: 12px; padding: 8px;">
                ๐Ÿ“ฆ Install
              </button>
            `}
          </div>
        </div>
      `;
    }

    // Tool Management Functions
    async function installTool(toolId) {
      try {
        const response = await fetch('/api/tools/install', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ toolId })
        });
        
        const result = await response.json();
        
        if (result.success) {
          alert(`โœ… ${result.tool.name} installed successfully!`);
          refreshToolData();
        } else {
          alert(`โŒ Installation failed: ${result.error}`);
        }
      } catch (error) {
        console.error('Install failed:', error);
        alert(`โŒ Installation error: ${error.message}`);
      }
    }

    async function uninstallTool(toolId) {
      const tool = toolsData.catalog.tools.find(t => t.id === toolId);
      if (!tool) return;
      
      if (!confirm(`Are you sure you want to uninstall "${tool.name}"?`)) {
        return;
      }
      
      try {
        const response = await fetch('/api/tools/uninstall', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ toolId })
        });
        
        const result = await response.json();
        
        if (result.success) {
          alert(`โœ… ${tool.name} uninstalled successfully!`);
          refreshToolData();
        } else {
          alert(`โŒ Uninstall failed: ${result.error}`);
        }
      } catch (error) {
        console.error('Uninstall failed:', error);
        alert(`โŒ Uninstall error: ${error.message}`);
      }
    }

    function showToolDetails(toolId) {
      const tool = toolsData.catalog.tools.find(t => t.id === toolId);
      if (!tool) return;
      
      const isInstalled = tool.status === 'installed' || tool.builtin;
      const categoryInfo = toolsData.catalog.categories[tool.category] || {};
      
      const modal = document.createElement('div');
      modal.style.cssText = `
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0, 0, 0, 0.8);
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 10000;
      `;
      
      const content = document.createElement('div');
      content.style.cssText = `
        background: var(--panel);
        border: 1px solid var(--border);
        border-radius: 12px;
        padding: 24px;
        max-width: 600px;
        width: 90%;
        max-height: 80vh;
        overflow-y: auto;
      `;
      
      content.innerHTML = `
        <div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 16px;">
          <div>
            <h2 style="margin: 0 0 4px 0;">${tool.name}</h2>
            <div style="color: var(--sub);">
              ${categoryInfo.icon || '๐Ÿ”ง'} ${categoryInfo.name || tool.category} โ€ข v${tool.version} โ€ข ID: ${tool.id}
            </div>
          </div>
          ${isInstalled ? '<span style="background: var(--ok); color: white; padding: 4px 12px; border-radius: 16px; font-size: 12px; font-weight: 500;">INSTALLED</span>' : '<span style="background: var(--primary); color: white; padding: 4px 12px; border-radius: 16px; font-size: 12px; font-weight: 500;">AVAILABLE</span>'}
        </div>
        
        <p style="color: var(--sub); line-height: 1.6; margin-bottom: 20px;">
          ${tool.description}
        </p>
        
        ${tool.dependencies && tool.dependencies.length > 0 ? `
          <div style="margin-bottom: 16px;">
            <h4 style="margin-bottom: 8px;">Dependencies:</h4>
            <div style="background: var(--muted); padding: 12px; border-radius: 8px;">
              ${tool.dependencies.map(dep => `<code style="background: var(--bg); padding: 2px 6px; border-radius: 4px; margin-right: 8px;">${dep}</code>`).join('')}
            </div>
          </div>
        ` : ''}
        
        ${tool.schema ? `
          <div style="margin-bottom: 16px;">
            <h4 style="margin-bottom: 8px;">Parameters:</h4>
            <div style="background: var(--muted); padding: 12px; border-radius: 8px; font-family: monospace; font-size: 12px;">
              ${Object.entries(tool.schema).map(([param, spec]) => `
                <div style="margin-bottom: 8px;">
                  <strong>${param}</strong> (${spec.type}${spec.required ? ', required' : ', optional'})
                  ${spec.description ? `<br><span style="color: var(--sub);">${spec.description}</span>` : ''}
                </div>
              `).join('')}
            </div>
          </div>
        ` : ''}
        
        ${tool.author ? `
          <div style="margin-bottom: 16px;">
            <strong>Author:</strong> <span style="color: var(--sub);">${tool.author}</span>
          </div>
        ` : ''}
        
        <div style="display: flex; gap: 12px; justify-content: flex-end;">
          <button class="btn secondary" onclick="this.closest('[style*=fixed]').remove()">Close</button>
          ${isInstalled ? 
            (tool.builtin ? '' : `<button class="btn" onclick="uninstallTool('${tool.id}'); this.closest('[style*=fixed]').remove();" style="background: var(--danger);">๐Ÿ—‘๏ธ Uninstall</button>`) :
            `<button class="btn" onclick="installTool('${tool.id}'); this.closest('[style*=fixed]').remove();">๐Ÿ“ฆ Install</button>`
          }
        </div>
      `;
      
      modal.appendChild(content);
      document.body.appendChild(modal);
      
      // Close on backdrop click
      modal.addEventListener('click', function(e) {
        if (e.target === modal) {
          modal.remove();
        }
      });
    }

    function refreshToolData() {
      loadToolsData();
    }

    function displayToolError(message) {
      const toolGrid = document.getElementById('toolGrid');
      toolGrid.innerHTML = `
        <div style="grid-column: 1 / -1; text-align: center; padding: 40px; color: var(--danger);">
          โŒ ${message}
        </div>
      `;
    }

    function showBatchInstall() {
      // TODO: Implement batch install modal
      alert('Batch install feature coming soon!');
    }

    // Load tools data when switching to tools view
    const originalShowView = showView;
    showView = function(viewName) {
      originalShowView(viewName);
      if (viewName === 'tools') {
        setTimeout(loadToolsData, 100); // Small delay to ensure view is shown
      } else if (viewName === 'vibe') {
        setTimeout(loadVibeView, 100); // Small delay to ensure view is shown
      }
    };

    // ======= VIBE SESSION MANAGEMENT =======
    
    let activeSession = null;
    let vibeDetectionData = null;
    
    function loadVibeView() {
      // Load available templates on view load
      refreshTemplates();
    }
    
    async function detectCurrentVibe() {
      const energyLevel = document.getElementById('energyLevel').value;
      const currentMood = document.getElementById('currentMood').value;
      const availableTime = parseInt(document.getElementById('availableTime').value);
      const workContext = document.getElementById('workContext').value;
      
      if (!energyLevel) {
        showNotification('Please select your energy level', 'warning');
        return;
      }
      
      const contextSignals = {
        energyLevel,
        mood: currentMood,
        availableTime,
        workEnvironment: workContext.includes('quiet') ? 'quiet' : 'normal',
        workContext: [workContext],
        timeOfDay: new Date().getHours(),
        recentActivity: ["development", "coding"],
        goals: ["build", "create"]
      };
      
      try {
        const response = await fetch('/api/vibe/detect', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(contextSignals)
        });
        
        if (!response.ok) throw new Error('Vibe detection failed');
        
        const data = await response.json();
        vibeDetectionData = data.vibe;
        
        displayVibeResult(data.vibe);
        
        // Auto-match templates based on detected vibe
        await matchTemplatesForVibe(contextSignals);
        
      } catch (error) {
        console.error('Vibe detection error:', error);
        showNotification('Failed to detect vibe: ' + error.message, 'error');
      }
    }
    
    function displayVibeResult(vibeData) {
      const resultDiv = document.getElementById('vibeResult');
      const vibeNameDiv = document.getElementById('detectedVibe');
      const vibeDescDiv = document.getElementById('vibeDescription');
      const vibeConfDiv = document.getElementById('vibeConfidence');
      
      if (vibeData.primaryVibe) {
        const [vibeName, vibeInfo] = vibeData.primaryVibe;
        vibeNameDiv.textContent = `๐ŸŽญ Detected Vibe: ${vibeName.replace('-', ' ')}`;
        vibeDescDiv.textContent = vibeInfo.profile.description;
        vibeConfDiv.textContent = `Confidence: ${(vibeData.confidence * 100).toFixed(1)}% โ€ข Signals: ${vibeData.detectedSignals.slice(0, 3).join(', ')}`;
      } else {
        vibeNameDiv.textContent = '๐ŸŽญ Balanced Work Mode';
        vibeDescDiv.textContent = 'General productive work session detected';
        vibeConfDiv.textContent = 'Default recommendation';
      }
      
      resultDiv.style.display = 'block';
    }
    
    async function matchTemplatesForVibe(contextSignals) {
      try {
        const response = await fetch('/api/workflows/templates/match', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(contextSignals)
        });
        
        if (!response.ok) throw new Error('Template matching failed');
        
        const data = await response.json();
        displayMatchedTemplates(data.matches);
        
      } catch (error) {
        console.error('Template matching error:', error);
        showNotification('Failed to match templates: ' + error.message, 'error');
      }
    }
    
    function displayMatchedTemplates(matches) {
      const templatesGrid = document.getElementById('workflowTemplates');
      
      if (matches.length === 0) {
        templatesGrid.innerHTML = `
          <div style="text-align: center; color: var(--sub); padding: 40px; grid-column: 1 / -1;">
            <div style="font-size: 48px; margin-bottom: 16px;">๐Ÿค”</div>
            <div>No templates matched your current vibe. Try adjusting your context or energy level.</div>
          </div>
        `;
        return;
      }
      
      templatesGrid.innerHTML = matches.map(match => `
        <div style="background: var(--muted); border: 1px solid var(--border); border-radius: 8px; padding: 16px;">
          <div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 12px;">
            <h4 style="margin: 0; color: var(--primary);">${match.template.name}</h4>
            <span style="background: var(--primary); color: white; padding: 2px 8px; border-radius: 12px; font-size: 11px; font-weight: 600;">
              ${(match.score * 100).toFixed(0)}% match
            </span>
          </div>
          
          <div style="color: var(--sub); font-size: 13px; margin-bottom: 12px; line-height: 1.4;">
            ${match.template.description}
          </div>
          
          <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; font-size: 12px; color: var(--sub);">
            <span>โฑ๏ธ ${match.template.vibe.duration}</span>
            <span>๐Ÿ’ณ ${match.template.credits?.estimated || 0} credits</span>
          </div>
          
          <div style="display: flex; gap: 8px; margin-bottom: 12px;">
            ${match.template.vibe.tags?.slice(0, 3).map(tag => `
              <span style="background: var(--panel); padding: 2px 6px; border-radius: 6px; font-size: 10px; text-transform: uppercase;">
                ${tag}
              </span>
            `).join('') || ''}
          </div>
          
          <button class="btn primary" onclick="startVibeSession('${match.template.id}')" style="width: 100%; font-size: 13px;">
            Start This Workflow
          </button>
        </div>
      `).join('');
    }
    
    async function refreshTemplates() {
      try {
        const response = await fetch('/api/workflows/templates');
        if (!response.ok) throw new Error('Failed to load templates');
        
        const data = await response.json();
        displayAllTemplates(data.templates);
        
      } catch (error) {
        console.error('Template refresh error:', error);
        showNotification('Failed to refresh templates: ' + error.message, 'error');
      }
    }

    async function refreshSlides() {
      try {
        const r = await fetch('/api/slides');
        if (!r.ok) throw new Error('Failed to load slides');
        const data = await r.json();
        displaySlides(data.slides || []);
      } catch (e) {
        showNotification('Slides refresh error: ' + (e && e.message ? e.message : e), 'error');
      }
    }

    function displaySlides(slides) {
      const grid = document.getElementById('slidesGrid');
      if (!slides || slides.length === 0) {
        grid.innerHTML = `
          <div style="text-align: center; color: var(--sub); padding: 40px; grid-column: 1 / -1;">
            <div style="font-size: 42px; margin-bottom: 16px;">๐Ÿ—‚๏ธ</div>
            <div>No slides found. Generate from Markdown, then refresh.</div>
          </div>`;
        return;
      }
      grid.innerHTML = slides.map(s => `
        <div style="background: var(--muted); border: 1px solid var(--border); border-radius: 8px; padding: 16px;">
          <h4 style="margin: 0 0 8px 0; color: var(--primary); word-break: break-word;">${s.name}</h4>
          <div style="font-size: 12px; color: var(--sub); margin-bottom: 10px;">${s.mtime ? new Date(s.mtime).toLocaleString() : ''}</div>
          <div style="display:flex; gap:8px;">
            <a class="btn primary" href="${s.url}" target="_blank" rel="noopener noreferrer">Open</a>
            <button class="btn" onclick="copySlideLink('${s.url}')">Copy Link</button>
          </div>
        </div>
      `).join('');
    }

    function copySlideLink(url) {
      const full = location.origin + url;
      navigator.clipboard.writeText(full).then(() => showNotification('Copied link: ' + full, 'success'));
    }

    // Generate a workflow from a prompt via cloud AI and save it server-side
    function showGenerateWorkflowModal() {
      const modal = document.createElement('div');
      modal.style.cssText = 'position:fixed; inset:0; background:rgba(0,0,0,0.6); display:flex; align-items:center; justify-content:center; z-index:10000;';
      const card = document.createElement('div');
      card.style.cssText = 'background: var(--panel); border:1px solid var(--border); border-radius:12px; width: min(700px, 92vw); padding:20px;';
      card.innerHTML = `
        <h3 style="margin-top:0;">โœจ Generate Workflow from Prompt</h3>
        <div class="form-group"><label class="form-label">Goal</label><textarea id="gwGoal" class="form-input" style="min-height:90px;" placeholder="e.g., Write a research brief on LLM reliability"></textarea></div>
        <div style="display:flex; gap:10px; flex-wrap:wrap;">
          <div style="flex:1; min-width:180px;">
            <label class="form-label">Provider</label>
            <select id="gwProvider" class="form-select">
              <option value="claude">Claude</option>
              <option value="gemini">Gemini</option>
              <option value="openai">OpenAI</option>
              <option value="deepseek">DeepSeek</option>
            </select>
          </div>
          <div style="flex:1; min-width:180px;">
            <label class="form-label">Template ID (optional)</label>
            <input id="gwId" class="form-input" type="text" placeholder="custom-research-brief"/>
          </div>
          <div style="flex:1; min-width:180px;">
            <label class="form-label">Name (optional)</label>
            <input id="gwName" class="form-input" type="text" placeholder="Research Brief"/>
          </div>
        </div>
        <div style="display:flex; gap:8px; justify-content:flex-end; margin-top:14px;">
          <button class="btn secondary" onclick="this.closest('[style*=position:fixed]').remove()">Cancel</button>
          <button class="btn primary" id="gwBtn">Generate</button>
        </div>`;
      modal.appendChild(card);
      document.body.appendChild(modal);

      const btn = card.querySelector('#gwBtn');
      btn.addEventListener('click', async () => {
        const goal = card.querySelector('#gwGoal').value.trim();
        const provider = card.querySelector('#gwProvider').value;
        const id = card.querySelector('#gwId').value.trim();
        const name = card.querySelector('#gwName').value.trim();
        if (!goal) { showNotification('Please enter a goal', 'warning'); return; }
        try {
          btn.disabled = true; btn.textContent = 'Generatingโ€ฆ';
          const resp = await fetch('/api/workflows/templates/generate', {
            method: 'POST', headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ provider, goal, id: id || undefined, name: name || undefined })
          });
          const data = await resp.json();
          if (!resp.ok || !data.success) throw new Error(data.error || 'Generation failed');
          showNotification(`Workflow saved: ${data.template?.id || data.file}`, 'success');
          modal.remove();
          await refreshTemplates();
        } catch (e) {
          showNotification('Failed to generate workflow: ' + (e && e.message ? e.message : e), 'error');
          btn.disabled = false; btn.textContent = 'Generate';
        }
      });
    }
    
    function displayAllTemplates(templates) {
      const templatesGrid = document.getElementById('workflowTemplates');
      
      if (templates.length === 0) {
        templatesGrid.innerHTML = `
          <div style="text-align: center; color: var(--sub); padding: 40px; grid-column: 1 / -1;">
            <div style="font-size: 48px; margin-bottom: 16px;">๐Ÿ“‹</div>
            <div>No workflow templates available</div>
          </div>
        `;
        return;
      }
      
      templatesGrid.innerHTML = templates.map(template => `
        <div style="background: var(--muted); border: 1px solid var(--border); border-radius: 8px; padding: 16px;">
          <h4 style="margin: 0 0 8px 0; color: var(--primary);">${template.name}</h4>
          
          <div style="color: var(--sub); font-size: 13px; margin-bottom: 12px; line-height: 1.4;">
            ${template.description}
          </div>
          
          <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; font-size: 12px; color: var(--sub);">
            <span>โฑ๏ธ ${template.estimatedDuration}</span>
            <span>๐Ÿ’ณ ${template.estimatedCredits} credits</span>
            <span>๐Ÿ“ ${template.stepCount} steps</span>
          </div>
          
          <div style="display: flex; gap: 6px; margin-bottom: 12px; flex-wrap: wrap;">
            ${template.tags.slice(0, 4).map(tag => `
              <span style="background: var(--panel); color: var(--sub); padding: 2px 6px; border-radius: 6px; font-size: 10px; text-transform: uppercase;">
                ${tag}
              </span>
            `).join('')}
          </div>
          
          <button class="btn secondary" onclick="startVibeSession('${template.id}')" style="width: 100%; font-size: 13px;">
            Start Session
          </button>
        </div>
      `).join('');
    }
    
    async function startVibeSession(templateId) {
      try {
        // Get template details first
        const templateResponse = await fetch(`/api/workflows/templates/${templateId}`);
        if (!templateResponse.ok) throw new Error('Template not found');
        
        const templateData = await templateResponse.json();
        const template = templateData.template;
        
        // Initialize interactive session
        activeSession = {
          sessionId: `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
          template: template,
          currentStep: 0,
          completedSteps: [],
          stepResults: {},
          status: 'active',
          startTime: new Date().toISOString()
        };
        
        displayInteractiveSession(activeSession);
        showNotification(`Started interactive "${template.name}" session!`, 'success');
        
      } catch (error) {
        console.error('Start session error:', error);
        showNotification('Failed to start session: ' + error.message, 'error');
      }
    }
    
    function displayInteractiveSession(session) {
      const sessionCard = document.getElementById('interactiveSessionCard');
      const sessionTitle = document.getElementById('sessionTitle');
      const sessionSubtitle = document.getElementById('sessionSubtitle');
      const stepsContainer = document.getElementById('workflowStepsContainer');
      
      sessionTitle.textContent = `๐ŸŽฏ ${session.template.name}`;
      sessionSubtitle.textContent = session.template.description;
      
      // Create interactive steps
      stepsContainer.innerHTML = session.template.flow.map((step, index) => 
        createInteractiveStep(step, index, session)
      ).join('');
      
      // Update progress
      updateWorkflowProgress(session);
      
      sessionCard.style.display = 'block';
      sessionCard.scrollIntoView({ behavior: 'smooth' });
    }
    
    function createInteractiveStep(step, index, session) {
      const isCompleted = session.completedSteps.includes(index);
      const isCurrent = session.currentStep === index;
      const canExecute = index === session.currentStep || isCompleted;
      
      return `
        <div class="workflow-step" data-step-index="${index}" style="
          background: var(--muted); 
          border: 2px solid ${isCurrent ? 'var(--primary)' : isCompleted ? 'var(--ok)' : 'var(--border)'}; 
          border-radius: 12px; 
          padding: 20px;
          ${!canExecute ? 'opacity: 0.6;' : ''}
        ">
          <!-- Step Header -->
          <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
            <div style="display: flex; align-items: center; gap: 12px;">
              <div style="
                width: 32px; height: 32px; 
                border-radius: 50%; 
                background: ${isCompleted ? 'var(--ok)' : isCurrent ? 'var(--primary)' : 'var(--sub)'}; 
                color: white; 
                display: flex; align-items: center; justify-content: center; 
                font-weight: 600; font-size: 14px;
              ">
                ${isCompleted ? 'โœ“' : index + 1}
              </div>
              <div>
                <h4 style="margin: 0; color: var(--text);">${step.step.replace('-', ' ')}</h4>
                <div style="font-size: 13px; color: var(--sub); margin-top: 2px;">
                  ${step.estimatedTime} โ€ข ${step.vibe} vibe
                </div>
              </div>
            </div>
            <div style="display: flex; gap: 8px;">
              ${step.tools.map(tool => `
                <span style="
                  background: var(--panel); 
                  color: var(--sub); 
                  padding: 4px 8px; 
                  border-radius: 6px; 
                  font-size: 11px; 
                  text-transform: uppercase; 
                  font-weight: 500;
                ">
                  ${tool.split('.')[0]}
                </span>
              `).join('')}
            </div>
          </div>
          
          <!-- Step Description -->
          <div style="color: var(--sub); margin-bottom: 20px; line-height: 1.5;">
            ${step.description}
          </div>
          
          <!-- Step Inputs -->
          <div style="background: var(--panel); border-radius: 8px; padding: 16px; margin-bottom: 16px;">
            <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 16px;">
              <!-- File Upload -->
              <div>
                <label style="display: block; margin-bottom: 8px; font-weight: 500; color: var(--text);">
                  ๐Ÿ“ Upload Files (Optional)
                </label>
                <input 
                  type="file" 
                  id="stepFiles_${index}"
                  multiple
                  style="
                    width: 100%; 
                    padding: 8px; 
                    border: 1px dashed var(--border); 
                    border-radius: 6px; 
                    background: var(--muted);
                    color: var(--text);
                    font-size: 13px;
                  "
                />
              </div>
              
              <!-- Quick Inputs -->
              <div>
                <label style="display: block; margin-bottom: 8px; font-weight: 500; color: var(--text);">
                  โšก Quick Input
                </label>
                <input 
                  type="text" 
                  id="stepQuickInput_${index}"
                  placeholder="Enter key info, URLs, or parameters..."
                  style="
                    width: 100%; 
                    padding: 8px 12px; 
                    border: 1px solid var(--border); 
                    border-radius: 6px; 
                    background: var(--muted); 
                    color: var(--text);
                    font-size: 13px;
                  "
                />
              </div>
            </div>
            
            <!-- Custom Prompt -->
            <div>
              <label style="display: block; margin-bottom: 8px; font-weight: 500; color: var(--text);">
                ๐Ÿ’ฌ Custom Instructions
              </label>
              <textarea 
                id="stepPrompt_${index}"
                placeholder="Customize how this step should be executed..."
                rows="3"
                style="
                  width: 100%; 
                  padding: 12px; 
                  border: 1px solid var(--border); 
                  border-radius: 6px; 
                  background: var(--muted); 
                  color: var(--text); 
                  font-size: 13px;
                  font-family: inherit;
                  resize: vertical;
                "
              >${getStepDefaultPrompt(step)}</textarea>
            </div>
          </div>
          
          <!-- Step Actions -->
          <div style="display: flex; justify-content: space-between; align-items: center;">
            <div style="font-size: 13px; color: var(--sub);">
              ${isCompleted ? 'โœ… Completed' : canExecute ? 'Ready to execute' : 'Complete previous steps first'}
            </div>
            <div style="display: flex; gap: 8px;">
              ${isCompleted ? `
                <button class="btn secondary" onclick="viewStepResults(${index})" style="font-size: 13px;">
                  <span>๐Ÿ‘๏ธ</span> View Results
                </button>
                <button class="btn secondary" onclick="rerunStep(${index})" style="font-size: 13px;">
                  <span>๐Ÿ”„</span> Re-run
                </button>
              ` : canExecute ? `
                <button class="btn primary" onclick="executeInteractiveStep(${index})" style="font-size: 13px;">
                  <span>๐Ÿš€</span> Execute Step
                </button>
              ` : `
                <button class="btn secondary" disabled style="font-size: 13px; opacity: 0.5;">
                  <span>โณ</span> Waiting
                </button>
              `}
            </div>
          </div>
          
          <!-- Step Results -->
          <div id="stepResults_${index}" style="display: none; margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--border);">
            <h5 style="margin: 0 0 12px 0; color: var(--primary);">๐Ÿ“Š Step Results</h5>
            <div id="stepResultsContent_${index}" style="background: var(--panel); border-radius: 6px; padding: 12px; font-family: monospace; font-size: 12px; max-height: 300px; overflow-y: auto;"></div>
          </div>
        </div>
      `;
    }
    
    function getStepDefaultPrompt(step) {
      const prompts = {
        'inspiration-gather': 'Research trending topics and gather inspiration for content creation. Focus on current industry trends and engaging angles.',
        'draft-creation': 'Create compelling content based on the research and inputs provided. Write in an engaging, professional tone.',
        'visual-enhancement': 'Generate or suggest visuals that complement the content and enhance engagement.',
        'publish-distribute': 'Prepare content for publication and distribution across selected platforms.',
        'data-discovery': 'Analyze and explore the provided data sources. Identify key patterns and insights.',
        'data-cleaning': 'Clean and prepare the data for analysis. Handle missing values and inconsistencies.',
        'exploratory-analysis': 'Perform comprehensive data analysis and generate visualizations.',
        'insight-synthesis': 'Synthesize findings into actionable insights and recommendations.',
        'idea-capture': 'Organize and structure the concept for rapid prototyping.',
        'rapid-build': 'Create a functional prototype quickly using best practices.',
        'instant-deploy': 'Deploy the prototype and make it accessible for testing.',
        'feedback-collect': 'Gather user feedback and analyze usability.'
      };
      
      return prompts[step.step] || `Execute ${step.step.replace('-', ' ')} step with the provided inputs and context.`;
    }
    
    async function executeInteractiveStep(stepIndex) {
      if (!activeSession) return;
      
      const step = activeSession.template.flow[stepIndex];
      const stepElement = document.querySelector(`[data-step-index="${stepIndex}"]`);
      
      // Get user inputs
      const filesInput = document.getElementById(`stepFiles_${stepIndex}`);
      const quickInput = document.getElementById(`stepQuickInput_${stepIndex}`);
      const customPrompt = document.getElementById(`stepPrompt_${stepIndex}`);
      
      const userInputs = {
        files: filesInput.files,
        quickInput: quickInput.value,
        customPrompt: customPrompt.value,
        stepInfo: step
      };
      
      // Show execution in progress
      const executeBtn = stepElement.querySelector('.btn.primary');
      executeBtn.innerHTML = '<span>โณ</span> Executing...';
      executeBtn.disabled = true;
      
      try {
        // Execute step with real agent
        const result = await executeStepWithRealAgent(step, userInputs, stepIndex);
        
        // Mark step as completed
        activeSession.completedSteps.push(stepIndex);
        activeSession.stepResults[stepIndex] = result;
        activeSession.currentStep = stepIndex + 1;
        
        // Show results immediately with enhanced display
        displayStepResults(stepIndex, result);
        
        // Auto-scroll to show results after a brief delay
        setTimeout(() => {
          const resultContainer = document.getElementById(`stepResults_${stepIndex}`);
          if (resultContainer) {
            resultContainer.scrollIntoView({ behavior: 'smooth', block: 'center' });
          }
        }, 500);
        
        // Update UI
        refreshInteractiveSession();
        
        showNotification(`Step "${step.step}" completed! Results displayed below - click to edit.`, 'success');
        
      } catch (error) {
        console.error('Step execution failed:', error);
        executeBtn.innerHTML = '<span>โŒ</span> Failed - Retry';
        executeBtn.disabled = false;
        showNotification(`Step failed: ${error.message}`, 'error');
      }
    }
    
    async function executeStepWithRealAgent(step, userInputs, stepIndex) {
      return new Promise((resolve, reject) => {
        let resultContent = '';
        
        // Use the new workflow API endpoint with tool mapping
        fetch('/api/workflows/execute-step', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            step: step,
            userInputs: userInputs,
            stepIndex: stepIndex,
            provider: currentProvider || 'llamacpp'
          })
        }).then(response => {
          if (!response.ok) {
            reject(new Error('Agent execution failed'));
            return;
          }
          
          const reader = response.body.getReader();
          const decoder = new TextDecoder();
          
          function readStream() {
            reader.read().then(({ done, value }) => {
              if (done) {
                resolve({
                  content: resultContent,
                  timestamp: new Date().toISOString(),
                  stepIndex: stepIndex,
                  userInputs: userInputs
                });
                return;
              }
              
              const chunk = decoder.decode(value);
              const lines = chunk.split('\n');
              
              for (const line of lines) {
                if (line.startsWith('data: ')) {
                  try {
                    const data = JSON.parse(line.slice(6));
                    console.log('SSE Data received:', data); // Debug log
                    
                    // Handle different response types
                    if (data.type === 'response' || data.type === 'chunk') {
                      const content = data.content || data.text || data.data || '';
                      resultContent += content;
                      
                      // Live update results as they stream in
                      const resultsDiv = document.getElementById(`stepResultsContent_${stepIndex}`);
                      if (resultsDiv) {
                        resultsDiv.innerHTML = resultContent.replace(/\n/g, '<br>');
                        resultsDiv.scrollTop = resultsDiv.scrollHeight;
                      }
                    }
                    
                    if (data.type === 'final') {
                      console.log('Final result content:', resultContent); // Debug log
                      resolve({
                        content: resultContent,
                        timestamp: new Date().toISOString(),
                        stepIndex: stepIndex,
                        userInputs: userInputs,
                        mappedTools: data.mappedTools,
                        originalTools: data.originalTools
                      });
                      return;
                    }
                    
                    if (data.type === 'error') {
                      reject(new Error(data.error || 'Step execution failed'));
                      return;
                    }
                  } catch (e) {
                    console.error('JSON parsing error:', e, 'Line:', line); // Better error logging
                  }
                } else if (line.trim() && !line.startsWith('event:')) {
                  // Handle non-JSON responses
                  console.log('Non-JSON response:', line);
                  resultContent += line + '\n';
                  const resultsDiv = document.getElementById(`stepResultsContent_${stepIndex}`);
                  if (resultsDiv) {
                    resultsDiv.innerHTML = resultContent.replace(/\n/g, '<br>');
                    resultsDiv.scrollTop = resultsDiv.scrollHeight;
                  }
                }
              }
              
              readStream();
            }).catch(reject);
          }
          
          readStream();
        }).catch(reject);
      });
    }
    
    function displayStepResults(stepIndex, result) {
      const resultsDiv = document.getElementById(`stepResults_${stepIndex}`);
      const resultsContent = document.getElementById(`stepResultsContent_${stepIndex}`);
      
      const content = result.content || 'No content generated - there may have been an issue with the AI response.';
      
      // Create editable content with better styling
      resultsContent.innerHTML = `
        <div style="position: relative; border: 1px solid var(--border); border-radius: 8px; overflow: hidden;">
          <div style="background: var(--muted); padding: 8px 12px; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; font-size: 12px; color: var(--sub);">
            <span>๐Ÿ“„ Step Results</span>
            <div>
              <button onclick="editStepResult(${stepIndex})" class="edit-btn" style="background: var(--primary); color: var(--primary-ink); border: none; border-radius: 4px; padding: 4px 8px; margin-right: 8px; cursor: pointer; font-size: 11px;">โœ๏ธ Edit</button>
              <button onclick="copyStepResult(${stepIndex})" class="copy-btn" style="background: var(--ok); color: white; border: none; border-radius: 4px; padding: 4px 8px; cursor: pointer; font-size: 11px;">๐Ÿ“‹ Copy</button>
            </div>
          </div>
          <div id="stepResultDisplay_${stepIndex}" style="padding: 12px; background: var(--panel); min-height: 60px; line-height: 1.5; white-space: pre-wrap; font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Monaco, Consolas, 'Roboto Mono', monospace;">${content}</div>
          <textarea id="stepResultEditor_${stepIndex}" style="display: none; width: 100%; min-height: 150px; padding: 12px; border: none; background: var(--panel); color: var(--text); font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Monaco, Consolas, 'Roboto Mono', monospace; font-size: 13px; line-height: 1.5; resize: vertical;" placeholder="Edit the step results...">${content}</textarea>
          <div id="stepResultActions_${stepIndex}" style="display: none; padding: 8px 12px; background: var(--muted); border-top: 1px solid var(--border);">
            <button onclick="saveStepResult(${stepIndex})" class="save-btn" style="background: var(--ok); color: white; border: none; border-radius: 4px; padding: 6px 12px; margin-right: 8px; cursor: pointer;">๐Ÿ’พ Save</button>
            <button onclick="cancelEditStepResult(${stepIndex})" class="cancel-btn" style="background: var(--danger); color: white; border: none; border-radius: 4px; padding: 6px 12px; cursor: pointer;">โŒ Cancel</button>
          </div>
        </div>
      `;
      
      resultsDiv.style.display = 'block';
      
      console.log('Displaying step results:', { stepIndex, content: result.content });
    }
    
    // Step result editing functions
    function editStepResult(stepIndex) {
      const displayDiv = document.getElementById(`stepResultDisplay_${stepIndex}`);
      const editorTextarea = document.getElementById(`stepResultEditor_${stepIndex}`);
      const actionsDiv = document.getElementById(`stepResultActions_${stepIndex}`);
      
      displayDiv.style.display = 'none';
      editorTextarea.style.display = 'block';
      actionsDiv.style.display = 'block';
      
      // Focus the editor and select all text for easy editing
      editorTextarea.focus();
      editorTextarea.select();
      
      showNotification('Editing mode enabled - make your changes and click Save', 'info');
    }
    
    function saveStepResult(stepIndex) {
      const displayDiv = document.getElementById(`stepResultDisplay_${stepIndex}`);
      const editorTextarea = document.getElementById(`stepResultEditor_${stepIndex}`);
      const actionsDiv = document.getElementById(`stepResultActions_${stepIndex}`);
      
      const newContent = editorTextarea.value;
      
      // Update the display
      displayDiv.innerHTML = newContent;
      displayDiv.style.display = 'block';
      editorTextarea.style.display = 'none';
      actionsDiv.style.display = 'none';
      
      // Update the stored result
      if (activeSession && activeSession.stepResults[stepIndex]) {
        activeSession.stepResults[stepIndex].content = newContent;
        activeSession.stepResults[stepIndex].modified = true;
        activeSession.stepResults[stepIndex].modifiedAt = new Date().toISOString();
        
        // Save progress
        saveWorkflowProgress();
      }
      
      showNotification('Step results saved successfully!', 'success');
    }
    
    function cancelEditStepResult(stepIndex) {
      const displayDiv = document.getElementById(`stepResultDisplay_${stepIndex}`);
      const editorTextarea = document.getElementById(`stepResultEditor_${stepIndex}`);
      const actionsDiv = document.getElementById(`stepResultActions_${stepIndex}`);
      
      // Revert editor content to original
      if (activeSession && activeSession.stepResults[stepIndex]) {
        editorTextarea.value = activeSession.stepResults[stepIndex].content || '';
      }
      
      displayDiv.style.display = 'block';
      editorTextarea.style.display = 'none';
      actionsDiv.style.display = 'none';
      
      showNotification('Edit cancelled', 'info');
    }
    
    function copyStepResult(stepIndex) {
      if (activeSession && activeSession.stepResults[stepIndex]) {
        const content = activeSession.stepResults[stepIndex].content || '';
        navigator.clipboard.writeText(content).then(() => {
          showNotification('Step results copied to clipboard!', 'success');
        }).catch(err => {
          console.error('Failed to copy to clipboard:', err);
          showNotification('Failed to copy to clipboard', 'error');
        });
      }
    }
    
    function refreshInteractiveSession() {
      if (!activeSession) return;
      
      // Refresh the entire session display
      displayInteractiveSession(activeSession);
    }
    
    function updateWorkflowProgress(session) {
      const progressBar = document.getElementById('workflowProgressBar');
      const progressText = document.getElementById('workflowProgressText');
      
      const totalSteps = session.template.flow.length;
      const completedSteps = session.completedSteps.length;
      const progress = (completedSteps / totalSteps) * 100;
      
      progressBar.style.width = `${progress}%`;
      progressText.textContent = `${completedSteps} of ${totalSteps} steps completed`;
    }
    
    function viewStepResults(stepIndex) {
      const result = activeSession.stepResults[stepIndex];
      if (!result) return;
      
      // Show modal with full results
      const modal = document.createElement('div');
      modal.style.cssText = `
        position: fixed; top: 0; left: 0; right: 0; bottom: 0;
        background: rgba(0,0,0,0.8); z-index: 1000;
        display: flex; align-items: center; justify-content: center;
        padding: 20px;
      `;
      
      modal.innerHTML = `
        <div style="
          background: var(--panel); 
          border-radius: 12px; 
          padding: 24px; 
          max-width: 800px; 
          max-height: 80vh; 
          overflow-y: auto;
          border: 1px solid var(--border);
        ">
          <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
            <h3 style="margin: 0; color: var(--primary);">๐Ÿ“Š Step Results</h3>
            <button onclick="this.closest('.modal').remove()" style="
              background: none; border: none; color: var(--sub); 
              font-size: 24px; cursor: pointer; padding: 0;
            ">ร—</button>
          </div>
          
          <div style="margin-bottom: 16px;">
            <strong>Step:</strong> ${activeSession.template.flow[stepIndex].step}<br>
            <strong>Completed:</strong> ${new Date(result.timestamp).toLocaleString()}
          </div>
          
          <div style="
            background: var(--muted); 
            border-radius: 6px; 
            padding: 16px; 
            font-family: monospace; 
            white-space: pre-wrap; 
            max-height: 400px; 
            overflow-y: auto;
            border: 1px solid var(--border);
          ">
            ${result.content}
          </div>
        </div>
      `;
      
      modal.className = 'modal';
      document.body.appendChild(modal);
      
      modal.addEventListener('click', (e) => {
        if (e.target === modal) modal.remove();
      });
    }
    
    function rerunStep(stepIndex) {
      if (!activeSession) return;
      
      // Remove from completed steps and reset current step
      activeSession.completedSteps = activeSession.completedSteps.filter(i => i !== stepIndex);
      activeSession.currentStep = Math.min(activeSession.currentStep, stepIndex);
      delete activeSession.stepResults[stepIndex];
      
      refreshInteractiveSession();
      showNotification('Step reset - you can now re-run it with different inputs', 'info');
    }
    
    function saveWorkflowProgress() {
      if (!activeSession) return;
      
      const progressData = {
        sessionId: activeSession.sessionId,
        templateId: activeSession.template.id,
        completedSteps: activeSession.completedSteps,
        stepResults: activeSession.stepResults,
        currentStep: activeSession.currentStep,
        savedAt: new Date().toISOString()
      };
      
      localStorage.setItem(`workflow_${activeSession.sessionId}`, JSON.stringify(progressData));
      showNotification('Workflow progress saved!', 'success');
    }
    
    function endInteractiveSession() {
      if (!activeSession) return;
      
      const sessionCard = document.getElementById('interactiveSessionCard');
      sessionCard.style.display = 'none';
      
      // Show completion summary if any steps were completed
      if (activeSession.completedSteps.length > 0) {
        const completedCount = activeSession.completedSteps.length;
        const totalCount = activeSession.template.flow.length;
        
        showNotification(`Session ended. Completed ${completedCount}/${totalCount} steps.`, 'info');
        
        // Show workflow results
        displayWorkflowSummary();
      } else {
        showNotification('Session ended', 'info');
      }
      
      activeSession = null;
      vibeDetectionData = null;
    }
    
    function displayWorkflowSummary() {
      const resultsDiv = document.getElementById('workflowResults');
      const resultsContent = document.getElementById('workflowResultsContent');
      
      if (!activeSession || activeSession.completedSteps.length === 0) return;
      
      const completedSteps = activeSession.completedSteps.map(index => ({
        step: activeSession.template.flow[index],
        result: activeSession.stepResults[index],
        index: index
      }));
      
      resultsContent.innerHTML = completedSteps.map(({ step, result, index }) => `
        <div style="border: 1px solid var(--border); border-radius: 8px; padding: 16px; margin-bottom: 16px;">
          <h5 style="margin: 0 0 8px 0; color: var(--primary);">
            ${index + 1}. ${step.step.replace('-', ' ')}
          </h5>
          <div style="
            background: var(--panel); 
            border-radius: 4px; 
            padding: 12px; 
            font-family: monospace; 
            font-size: 12px; 
            max-height: 150px; 
            overflow-y: auto;
          ">
            ${result.content.substring(0, 300)}${result.content.length > 300 ? '...' : ''}
          </div>
        </div>
      `).join('');
      
      resultsDiv.style.display = 'block';
    }

    // Embedded Agent Functions
    function showEmbeddedAgent() {
      const container = document.getElementById('embeddedAgentContainer');
      const iframe = document.getElementById('embeddedAgentFrame');
      
      if (!iframe.src) {
        iframe.src = '/agent-test-ui.html';
      }
      
      container.style.display = 'block';
      container.scrollIntoView({ behavior: 'smooth' });
    }

    function hideEmbeddedAgent() {
      const container = document.getElementById('embeddedAgentContainer');
      container.style.display = 'none';
    }

    // Cloud AI Action Confirmation System
    let pendingActions = [];
    let currentExecutionSession = null;

    function showActionConfirmation(actions, executionPlan) {
      pendingActions = actions;
      currentExecutionSession = {
        sessionId: executionPlan.sessionId || generateSessionId(),
        actions: actions,
        executionPlan: executionPlan,
        approvedActions: new Set(),
        results: {}
      };

      const modal = document.getElementById('actionConfirmationModal');
      const content = document.getElementById('actionConfirmationContent');
      
      // Build action list
      let actionsHtml = `
        <div style="margin-bottom: 20px;">
          <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
            <h3 style="margin: 0;">๐ŸŽฏ Confirm Actions</h3>
            <div style="font-size: 12px; color: var(--sub);">
              ${actions.length} action${actions.length !== 1 ? 's' : ''} โ€ข 
              Est. ${executionPlan.estimatedDuration || 'unknown'} โ€ข 
              Risk: <span style="color: ${getRiskColor(executionPlan.riskAssessment?.overallRiskLevel || 'low')}">${executionPlan.riskAssessment?.overallRiskLevel || 'low'}</span>
            </div>
          </div>
          
          <div style="max-height: 400px; overflow-y: auto; border: 1px solid var(--border); border-radius: 8px;">
      `;

      actions.forEach((action, index) => {
        const riskColor = getRiskColor(action.risk_level || 'low');
        const isChecked = true; // Default to selected
        
        actionsHtml += `
          <div class="action-item" style="padding: 12px; border-bottom: 1px solid var(--border); display: flex; align-items: flex-start; gap: 12px;">
            <input type="checkbox" id="action-${action.id}" ${isChecked ? 'checked' : ''} style="margin-top: 4px;" />
            <div style="flex: 1;">
              <div style="display: flex; align-items: center; gap: 8px; margin-bottom: 4px;">
                <strong>${action.sigil}</strong>
                <span style="background: ${riskColor}; color: white; padding: 2px 6px; border-radius: 3px; font-size: 10px; font-weight: 500;">
                  ${action.risk_level || 'low'}
                </span>
                <span style="color: var(--sub); font-size: 12px;">~${action.estimated_time || '10s'}</span>
              </div>
              <div style="color: var(--sub); font-size: 13px; margin-bottom: 6px;">${action.description}</div>
              ${action.args ? `<div style="font-family: monospace; font-size: 12px; background: var(--muted); padding: 4px 8px; border-radius: 4px; color: var(--primary);">${action.args}</div>` : ''}
            </div>
          </div>
        `;
      });

      actionsHtml += `</div></div>`;

      // Add execution options
      actionsHtml += `
        <div style="margin-bottom: 20px;">
          <h4 style="margin-bottom: 10px;">Execution Options</h4>
          <div style="display: flex; gap: 15px; flex-wrap: wrap;">
            <label style="display: flex; align-items: center; gap: 6px;">
              <input type="radio" name="executionMode" value="sequential" checked />
              <span>Sequential (safer)</span>
            </label>
            <label style="display: flex; align-items: center; gap: 6px;">
              <input type="radio" name="executionMode" value="parallel" />
              <span>Parallel (faster)</span>
            </label>
            <label style="display: flex; align-items: center; gap: 6px;">
              <input type="checkbox" id="dryRunMode" />
              <span>Dry run (preview only)</span>
            </label>
          </div>
        </div>
      `;

      content.innerHTML = actionsHtml;
      modal.style.display = 'flex';
    }

    function executeApprovedActions() {
      const selectedActions = [];
      const checkboxes = document.querySelectorAll('#actionConfirmationContent input[type="checkbox"]:checked');
      
      checkboxes.forEach(cb => {
        if (cb.id.startsWith('action-')) {
          const actionId = cb.id.replace('action-', '');
          const action = pendingActions.find(a => a.id === actionId);
          if (action) selectedActions.push(action);
        }
      });

      if (selectedActions.length === 0) {
        alert('No actions selected');
        return;
      }

      const executionMode = document.querySelector('input[name="executionMode"]:checked').value;
      const dryRun = document.getElementById('dryRunMode').checked;

      // Close modal and show progress
      closeActionConfirmation();
      showExecutionProgress(selectedActions, executionMode, dryRun);

      // Execute actions
      executeActionsWithProgress(selectedActions, executionMode, dryRun);
    }

    function closeActionConfirmation() {
      document.getElementById('actionConfirmationModal').style.display = 'none';
      pendingActions = [];
      currentExecutionSession = null;
    }

    function showExecutionProgress(actions, mode, dryRun) {
      const modal = document.getElementById('executionProgressModal');
      const content = document.getElementById('executionProgressContent');
      
      let progressHtml = `
        <div style="margin-bottom: 20px;">
          <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
            <h3 style="margin: 0;">โšก ${dryRun ? 'Dry Run' : 'Executing'} Actions</h3>
            <div style="font-size: 12px; color: var(--sub);">
              ${actions.length} action${actions.length !== 1 ? 's' : ''} โ€ข Mode: ${mode}
            </div>
          </div>
          
          <div class="progress-list" style="max-height: 500px; overflow-y: auto;">
      `;

      actions.forEach((action, index) => {
        progressHtml += `
          <div class="progress-item" id="progress-${action.id}" style="padding: 12px; border-bottom: 1px solid var(--border); display: flex; align-items: center; gap: 12px;">
            <div class="progress-status" style="width: 20px; height: 20px; border-radius: 50%; background: var(--sub); display: flex; align-items: center; justify-content: center; font-size: 10px;">
              ${index + 1}
            </div>
            <div style="flex: 1;">
              <div style="font-weight: 500;">${action.sigil} ${action.description}</div>
              <div class="progress-details" style="font-size: 12px; color: var(--sub); margin-top: 4px;">Waiting...</div>
            </div>
          </div>
        `;
      });

      progressHtml += `
          </div>
          <div style="margin-top: 20px;">
            <button class="btn secondary" onclick="cancelExecution()" style="margin-right: 10px;">Cancel</button>
            <button class="btn secondary" onclick="closeExecutionProgress()" style="display: none;" id="closeProgressBtn">Close</button>
          </div>
        </div>
      `;

      content.innerHTML = progressHtml;
      modal.style.display = 'flex';
    }

    async function executeActionsWithProgress(actions, mode, dryRun) {
      try {
        for (let i = 0; i < actions.length; i++) {
          const action = actions[i];
          updateActionProgress(action.id, 'running', 'Executing...');

          // Simulate execution time for demo
          await new Promise(resolve => setTimeout(resolve, 1000));

          // Mock execution result
          const result = {
            success: true,
            output: `Mock result for ${action.sigil}`,
            dryRun: dryRun
          };

          updateActionProgress(action.id, 'completed', result.output);
          currentExecutionSession.results[action.id] = result;
        }

        // Show completion
        document.getElementById('closeProgressBtn').style.display = 'inline-block';
        updateProgressStatus('โœ… All actions completed successfully');

      } catch (error) {
        updateProgressStatus('โŒ Execution failed: ' + error.message);
        document.getElementById('closeProgressBtn').style.display = 'inline-block';
      }
    }

    function updateActionProgress(actionId, status, details) {
      const progressItem = document.getElementById(`progress-${actionId}`);
      if (!progressItem) return;

      const statusIcon = progressItem.querySelector('.progress-status');
      const detailsEl = progressItem.querySelector('.progress-details');

      switch (status) {
        case 'running':
          statusIcon.style.background = 'var(--primary)';
          statusIcon.textContent = 'โšก';
          statusIcon.style.animation = 'pulse 1.5s infinite';
          break;
        case 'completed':
          statusIcon.style.background = 'var(--ok)';
          statusIcon.textContent = 'โœ“';
          statusIcon.style.animation = 'none';
          break;
        case 'failed':
          statusIcon.style.background = 'var(--danger)';
          statusIcon.textContent = 'โœ—';
          statusIcon.style.animation = 'none';
          break;
      }

      detailsEl.textContent = details;
    }

    function updateProgressStatus(message) {
      const existingStatus = document.querySelector('.execution-status');
      if (existingStatus) {
        existingStatus.textContent = message;
      } else {
        const content = document.getElementById('executionProgressContent');
        const statusDiv = document.createElement('div');
        statusDiv.className = 'execution-status';
        statusDiv.style.cssText = 'text-align: center; padding: 15px; background: var(--panel); border-radius: 8px; margin-top: 15px; font-weight: 500;';
        statusDiv.textContent = message;
        content.appendChild(statusDiv);
      }
    }

    function closeExecutionProgress() {
      document.getElementById('executionProgressModal').style.display = 'none';
    }

    function cancelExecution() {
      closeExecutionProgress();
    }

    function getRiskColor(riskLevel) {
      switch (riskLevel?.toLowerCase()) {
        case 'high': return 'var(--danger)';
        case 'medium': return '#f39c12';
        case 'low': return 'var(--ok)';
        default: return 'var(--sub)';
      }
    }

    function generateSessionId() {
      return 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
    }

    // Test function for development
    function testActionConfirmation() {
      const mockActions = [
        {
          id: 'test-1',
          sigil: '@calc',
          args: '22/7',
          description: 'Calculate mathematical expression',
          risk_level: 'low',
          estimated_time: '5s'
        },
        {
          id: 'test-2', 
          sigil: '@write',
          args: 'result.txt -> Result: ${test-1.result}',
          description: 'Save calculation result to file',
          risk_level: 'medium',
          estimated_time: '3s'
        },
        {
          id: 'test-3',
          sigil: '@email',
          args: 'user@example.com "Results" "The calculation is complete"',
          description: 'Email results to user',
          risk_level: 'high',
          estimated_time: '10s'
        }
      ];

      const mockPlan = {
        sessionId: 'test-session-123',
        estimatedDuration: '18s',
        riskAssessment: {
          overallRiskLevel: 'medium'
        }
      };

      showActionConfirmation(mockActions, mockPlan);
    }

    // Code Block Button Handlers
    function setupCodeButtonHandlers() {
      document.addEventListener('click', async function(e) {
        if (e.target.classList.contains('save-code-btn')) {
          e.preventDefault();
          await handleSaveCode(e.target);
        } else if (e.target.classList.contains('run-code-btn')) {
          e.preventDefault();
          await handleRunCode(e.target);
        } else if (e.target.classList.contains('copy-code-btn')) {
          e.preventDefault();
          await handleCopyCode(e.target);
        }
      });
    }

    async function handleSaveCode(button) {
      const language = button.dataset.language;
      const filename = button.dataset.filename;
      const code = decodeURIComponent(button.dataset.code);

      try {
        const response = await fetch('/api/command', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            command: 'save',
            args: { language, code, filename }
          })
        });

        if (response.ok) {
          const result = await response.json();
          if (result.success && result.result.savedFiles && result.result.savedFiles[0]) {
            const actualFilename = result.result.savedFiles[0].filename;
            // Update the run button with the actual saved filename
            const runButton = button.parentElement.querySelector('.run-code-btn');
            if (runButton) {
              runButton.dataset.filename = actualFilename;
            }
            button.innerHTML = `โœ… Saved as ${actualFilename}!`;
          } else {
            button.innerHTML = 'โœ… Saved!';
          }
          button.disabled = true;
          setTimeout(() => {
            button.innerHTML = `๐Ÿ’พ Save as ${filename}`;
            button.disabled = false;
          }, 2000);
        } else {
          throw new Error('Save failed');
        }
      } catch (error) {
        button.innerHTML = 'โŒ Failed';
        setTimeout(() => {
          button.innerHTML = `๐Ÿ’พ Save as ${filename}`;
        }, 2000);
      }
    }

    async function handleRunCode(button) {
      const filename = button.dataset.filename;

      try {
        button.innerHTML = '๐Ÿš€ Running...';
        button.disabled = true;

        const response = await fetch('/api/command', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            command: 'run',
            args: { filename }
          })
        });

        if (response.ok) {
          button.innerHTML = 'โœ… Executed!';
          // The result will appear in the chat
        } else {
          throw new Error('Execution failed');
        }
      } catch (error) {
        button.innerHTML = 'โŒ Failed';
      }

      setTimeout(() => {
        button.innerHTML = '๐Ÿš€ Run Code';
        button.disabled = false;
      }, 2000);
    }

    async function handleCopyCode(button) {
      const code = decodeURIComponent(button.dataset.code);

      try {
        await navigator.clipboard.writeText(code);
        button.innerHTML = 'โœ… Copied!';
        setTimeout(() => {
          button.innerHTML = '๐Ÿ“‹ Copy';
        }, 2000);
      } catch (error) {
        // Fallback for older browsers
        const textArea = document.createElement('textarea');
        textArea.value = code;
        document.body.appendChild(textArea);
        textArea.select();
        document.execCommand('copy');
        document.body.removeChild(textArea);
        
        button.innerHTML = 'โœ… Copied!';
        setTimeout(() => {
          button.innerHTML = '๐Ÿ“‹ Copy';
        }, 2000);
      }
    }

    // Initialize code button handlers
    setupCodeButtonHandlers();
  </script>

  <!-- Action Confirmation Modal -->
  <div id="actionConfirmationModal" style="
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.8);
    z-index: 1000;
    align-items: center;
    justify-content: center;
    padding: 20px;
  ">
    <div style="
      background: var(--panel);
      border-radius: 12px;
      border: 1px solid var(--border);
      max-width: 600px;
      width: 100%;
      max-height: 80vh;
      overflow-y: auto;
      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
    ">
      <div id="actionConfirmationContent" style="padding: 24px;">
        <!-- Content will be populated by JavaScript -->
      </div>
      <div style="padding: 0 24px 24px 24px; display: flex; gap: 12px; justify-content: flex-end;">
        <button class="btn secondary" onclick="closeActionConfirmation()">Cancel</button>
        <button class="btn primary" onclick="executeApprovedActions()">Execute Selected</button>
      </div>
    </div>
  </div>

  <!-- Execution Progress Modal -->
  <div id="executionProgressModal" style="
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.8);
    z-index: 1000;
    align-items: center;
    justify-content: center;
    padding: 20px;
  ">
    <div style="
      background: var(--panel);
      border-radius: 12px;
      border: 1px solid var(--border);
      max-width: 700px;
      width: 100%;
      max-height: 80vh;
      overflow-y: auto;
      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
    ">
      <div id="executionProgressContent" style="padding: 24px;">
        <!-- Content will be populated by JavaScript -->
      </div>
    </div>
  </div>

  <!-- Debug Panel -->
  <div class="debug-panel" id="debugPanel">
    <div class="debug-header">
      <div class="debug-title">๐Ÿ”ฌ Debug Console</div>
      <div style="display: flex; gap: 8px; align-items: center;">
        <button class="debug-close" onclick="clearDebugLog()" title="Clear Log" style="font-size: 14px;">๐Ÿงน</button>
        <button class="debug-close" onclick="toggleDebugPanel()" title="Close">&times;</button>
      </div>
    </div>
    <div class="debug-content" id="debugContent">
      <div class="debug-entry info">
        <span class="debug-timestamp">Ready</span>
        <span class="debug-icon">๐ŸŽฏ</span>
        <span class="debug-message">Debug console initialized. Waiting for executive requests...</span>
      </div>
    </div>
  </div>

  

  <script src="/workflows.js"></script>
  <script>
    async function runTerminalCmd() {
      const cmd = document.getElementById('termCmd').value;
      const out = document.getElementById('termOut');
      out.textContent = 'Runningโ€ฆ';
      try {
        const r = await fetch('/api/terminal/run', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ cmd }) });
        const j = await r.json();
        if (!r.ok) throw new Error(j.error || 'Failed');
        out.textContent = (j.stdout || '') + (j.stderr ? ('\n[stderr]\n' + j.stderr) : '');
      } catch (e) { out.textContent = 'Error: ' + e.message; }
    }
    async function loadSystemStatus() {
      const el = document.getElementById('systemStatus');
      if (!el) return;
      el.textContent = 'Loadingโ€ฆ';
      try {
        const r = await fetch('/api/health');
        const j = await r.json();
        if (!r.ok) throw new Error('Failed to load');
        const rows = [
          ['llama.cpp', j.llama],
          ['Claude', j.claude],
          ['Gemini', j.gemini],
          ['OpenAI', j.openai]
        ];
        el.innerHTML = rows.map(function(row){
          var name=row[0], ok=row[1];
          return '<div>' + (ok ? 'โœ…' : 'โŒ') + ' ' + name + '</div>';
        }).join('');
      } catch (e) { el.textContent = 'Error: ' + e.message; }
    }
  

    // Cream API quick actions via workflow executor
    async function systemCreamFetch() {
      const limitEl = document.getElementById('creamFetchLimit');
      const limit = parseInt(limitEl && limitEl.value || '5', 10) || 5;
      const out = document.getElementById('creamOut');
      if (out) out.textContent = 'Fetchingโ€ฆ';
      try {
        const r = await fetch('/api/workflows/custom/execute', {
          method:'POST', headers:{'Content-Type':'application/json'},
          body: JSON.stringify({ steps: [ { type: 'cream.fetch', args: { limit: limit, raw: raw } } ] })
        });
        const j = await r.json();
        if (!r.ok || j.success === false) throw new Error(j.error || 'Failed');
        if (out) out.textContent = typeof j.final === 'string' ? j.final : JSON.stringify(j.final, null, 2);
      } catch (e) { if (out) out.textContent = 'Error: ' + e.message; }
    }

    async function systemCreamMail() {
      const from_email = (document.getElementById('creamMailFrom')||{}).value || '';
      const to_email = (document.getElementById('creamMailTo')||{}).value || '';
      const subject = (document.getElementById('creamMailSubject')||{}).value || '';
      const body = (document.getElementById('creamMailBody')||{}).value || '';
      const out = document.getElementById('creamOut');
      if (out) out.textContent = 'Sendingโ€ฆ';
      try {
        const r = await fetch('/api/workflows/custom/execute', {
          method:'POST', headers:{'Content-Type':'application/json'},
          body: JSON.stringify({ steps: [ { type: 'cream.mail', args: { from_email, to_email, subject, body } } ] })
        });
        const j = await r.json();
        if (!r.ok || j.success === false) throw new Error(j.error || 'Failed');
        if (out) out.textContent = typeof j.final === 'string' ? j.final : JSON.stringify(j.final, null, 2);
      } catch (e) { if (out) out.textContent = 'Error: ' + e.message; }
    }

    async function systemCreamPost() {
      const content = (document.getElementById('creamPostContent')||{}).value || '';
      const visibility = (document.getElementById('creamPostVisibility')||{}).value || 'public';
      const out = document.getElementById('creamOut');
      if (out) out.textContent = 'Postingโ€ฆ';
      try {
        const r = await fetch('/api/workflows/custom/execute', {
          method:'POST', headers:{'Content-Type':'application/json'},
          body: JSON.stringify({ steps: [ { type: 'cream.post', args: { content, visibility } } ] })
        });
        const j = await r.json();
        if (!r.ok || j.success === false) throw new Error(j.error || 'Failed');
        if (out) out.textContent = typeof j.final === 'string' ? j.final : JSON.stringify(j.final, null, 2);
      } catch (e) { if (out) out.textContent = 'Error: ' + e.message; }
    }
</script>
<script>
  async function systemCreamDiagnose() {
    const out = document.getElementById('creamOut');
    if (out) out.textContent = 'Diagnosingโ€ฆ';
    try {
      const r = await fetch('/api/cream/debug');
      const j = await r.json();
      if (!r.ok) throw new Error('Failed to diagnose');
      if (out) out.textContent = JSON.stringify(j, null, 2);
    } catch (e) { if (out) out.textContent = 'Error: ' + e.message; }
  }
  async function systemCreamDiagMail() {
    const out = document.getElementById('creamOut');
    if (out) out.textContent = 'Diagnosing mailโ€ฆ';
    try {
      const r = await fetch('/api/cream/diag-mail');
      const j = await r.json();
      if (!r.ok) throw new Error('Failed to diagnose mail');
      if (out) out.textContent = JSON.stringify(j, null, 2);
    } catch (e) { if (out) out.textContent = 'Error: ' + e.message; }
  }
  async function systemCreamDiagPost() {
    const out = document.getElementById('creamOut');
    if (out) out.textContent = 'Diagnosing postsโ€ฆ';
    try {
      const r = await fetch('/api/cream/diag-post');
      const j = await r.json();
      if (!r.ok) throw new Error('Failed to diagnose posts');
      if (out) out.textContent = JSON.stringify(j, null, 2);
    } catch (e) { if (out) out.textContent = 'Error: ' + e.message; }
  }
</script>

</body>
</html>