{"version":3,"file":"ngx-core-components-ai.mjs","sources":["../../../projects/ngx-core-components/ai/ai-chat/ai-chat.component.ts","../../../projects/ngx-core-components/ai/ai-chat-widget/ai-chat-widget.component.ts","../../../projects/ngx-core-components/ai/ai-prompt-editor/ai-prompt-editor.component.ts","../../../projects/ngx-core-components/ai/ai-code-editor/ai-code-editor.component.ts","../../../projects/ngx-core-components/ai/ai-audio-wave/ai-audio-wave.component.ts","../../../projects/ngx-core-components/ai/ai-model-compare/ai-model-compare.component.ts","../../../projects/ngx-core-components/ai/ai-rag-inspector/ai-rag-inspector.component.ts","../../../projects/ngx-core-components/ai/ngx-web-llm.service.ts","../../../projects/ngx-core-components/ai/ai-form-copilot/ai-form-copilot.component.ts","../../../projects/ngx-core-components/ai/ngx-core-components-ai.ts"],"sourcesContent":["import { Component, input, output, model, viewChild, ElementRef, computed, effect, HostListener, signal, inject } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { AIMessage, AgentStep, AICard, AICardAction, QuickReply } from './models';\n\n@Component({\n  selector: 'ngx-ai-chat',\n  standalone: true,\n  imports: [CommonModule, FormsModule],\n  template: `\n    <div \n      class=\"ngx-ai-chat-container\" \n      [class.dark-mode]=\"theme() === 'dark'\"\n      [class.drag-over]=\"isDraggingOver()\"\n      (dragover)=\"onDragOver($event)\"\n      (dragleave)=\"onDragLeave($event)\"\n      (drop)=\"onDrop($event)\"\n    >\n      <!-- Drag & Drop Overlay -->\n      @if (isDraggingOver()) {\n        <div class=\"drag-dropzone-overlay\">\n          <div class=\"drag-dropzone-content\">\n            <svg viewBox=\"0 0 24 24\" class=\"drag-icon\"><path d=\"M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z\"/></svg>\n            <span>Drop files here to attach (Images, PDFs, Docs)</span>\n          </div>\n        </div>\n      }\n\n      <!-- Chat Header -->\n      <div class=\"ngx-ai-chat-header\">\n        <div class=\"header-avatar\" [style.background]=\"avatarBg()\">\n          @if (agentAvatarUrl()) {\n            <img [src]=\"agentAvatarUrl()\" [alt]=\"agentName()\" />\n          } @else {\n            <span class=\"avatar-initials\">{{ getInitials(agentName()) }}</span>\n          }\n          <span class=\"status-indicator\" [class.online]=\"isOnline()\"></span>\n        </div>\n        <div class=\"header-info\">\n          <div class=\"agent-title\">{{ agentName() }}</div>\n          <div class=\"agent-status\">{{ isOnline() ? 'Active Now' : 'Offline' }}</div>\n        </div>\n        <div class=\"header-actions\">\n          <button class=\"header-btn\" (click)=\"clearHistory.emit()\" title=\"Clear chat history\">\n            <svg viewBox=\"0 0 24 24\" class=\"svg-icon\"><path d=\"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z\"/></svg>\n          </button>\n        </div>\n      </div>\n\n      <!-- Messages Thread -->\n      <div class=\"ngx-ai-chat-body\" #chatBody (scroll)=\"onBodyScroll()\">\n        <!-- Scroll-to-bottom Floating Button -->\n        @if (isUserScrolledUp()) {\n          <button type=\"button\" class=\"scroll-bottom-pill\" (click)=\"scrollToBottom(true)\" title=\"Resume auto-scroll\">\n            <svg viewBox=\"0 0 24 24\" class=\"pill-icon\"><path d=\"M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z\"/></svg>\n            <span>New messages</span>\n          </button>\n        }\n        <div class=\"messages-list\">\n          @for (msg of messages(); track msg.id; let isLast = $last) {\n            <div class=\"message-wrapper\" [class.user-msg]=\"msg.role === 'user'\" [class.assistant-msg]=\"msg.role === 'assistant'\">\n              <!-- Avatar -->\n              @if (msg.role !== 'user') {\n                <div class=\"msg-avatar\" [style.background]=\"avatarBg()\">\n                  @if (msg.avatarUrl || agentAvatarUrl()) {\n                    <img [src]=\"msg.avatarUrl || agentAvatarUrl()\" [alt]=\"msg.senderName || agentName()\" />\n                  } @else {\n                    <span>{{ getInitials(msg.senderName || agentName()) }}</span>\n                  }\n                </div>\n              }\n\n              <!-- Content Area -->\n              <div class=\"msg-bubble-container\">\n                <!-- Sender Name -->\n                @if (msg.role !== 'user' && showSenderNames()) {\n                  <span class=\"msg-sender\">{{ msg.senderName || agentName() }}</span>\n                }\n\n                <div class=\"msg-bubble\">\n                  <!-- Text Content -->\n                  <div class=\"msg-text\">\n                    <span [innerHTML]=\"formatMessage(msg.content)\"></span>\n                    @if (isStreaming() && isLast && msg.role === 'assistant') {\n                      <span class=\"streaming-cursor\"></span>\n                    }\n                  </div>\n\n                  <!-- Agent Steps (Accordion) -->\n                  @if (msg.steps && msg.steps.length > 0) {\n                    <div class=\"agent-steps-container\">\n                      <div class=\"steps-header\">\n                        <span class=\"steps-title-text\">Execution Steps</span>\n                        <span class=\"steps-badge\">{{ getCompletedStepsCount(msg.steps) }}/{{ msg.steps.length }}</span>\n                      </div>\n                      <div class=\"steps-list\">\n                        @for (step of msg.steps; track step.id) {\n                          <div class=\"agent-step-item\" [class.step-error]=\"step.status === 'error'\">\n                            <div class=\"step-summary\" (click)=\"toggleStep(step)\">\n                              <span class=\"step-status-icon\" [class.running]=\"step.status === 'running'\" [class.success]=\"step.status === 'success'\" [class.error]=\"step.status === 'error'\">\n                                @if (step.status === 'running') {\n                                  <span class=\"spinner\"></span>\n                                } @else if (step.status === 'success') {\n                                  ✓\n                                } @else {\n                                  ✕\n                                }\n                              </span>\n                              <span class=\"step-name\">{{ step.name }}</span>\n                              @if (step.duration) {\n                                <span class=\"step-duration\">{{ step.duration }}</span>\n                              }\n                              <span class=\"step-chevron\" [class.expanded]=\"!step.collapsed\">▼</span>\n                            </div>\n\n                            @if (!step.collapsed) {\n                              <div class=\"step-details\">\n                                @if (step.input) {\n                                  <div class=\"step-detail-section\">\n                                    <div class=\"detail-label\">Input Parameters</div>\n                                    <pre class=\"detail-code\"><code>{{ step.input }}</code></pre>\n                                  </div>\n                                }\n                                @if (step.output) {\n                                  <div class=\"step-detail-section\">\n                                    <div class=\"detail-label\">Output Result</div>\n                                    <pre class=\"detail-code\"><code>{{ step.output }}</code></pre>\n                                  </div>\n                                }\n                              </div>\n                            }\n                          </div>\n                        }\n                      </div>\n                    </div>\n                  }\n                </div>\n\n                <!-- Structured Cards (Carousel) -->\n                @if (msg.cards && msg.cards.length > 0) {\n                  <div class=\"cards-carousel\">\n                    @for (card of msg.cards; track card.title) {\n                      <div class=\"ai-carousel-card\">\n                        @if (card.imageUrl) {\n                          <div class=\"card-img-container\">\n                            <img [src]=\"card.imageUrl\" [alt]=\"card.title\" />\n                          </div>\n                        }\n                        <div class=\"card-body\">\n                          <h4 class=\"card-title\">{{ card.title }}</h4>\n                          @if (card.subtitle) {\n                            <h5 class=\"card-subtitle\">{{ card.subtitle }}</h5>\n                          }\n                          @if (card.description) {\n                            <p class=\"card-description\">{{ card.description }}</p>\n                          }\n                          @if (card.actions && card.actions.length > 0) {\n                            <div class=\"card-actions\">\n                              @for (act of card.actions; track act.label) {\n                                <button\n                                  class=\"card-action-btn\"\n                                  [class.btn-primary]=\"act.variant === 'primary'\"\n                                  (click)=\"cardActionClick.emit(act)\"\n                                >\n                                  {{ act.label }}\n                                </button>\n                              }\n                            </div>\n                          }\n                        </div>\n                      </div>\n                    }\n                  </div>\n                }\n\n                <!-- Attachments inside message bubble -->\n                @if (msg.attachments && msg.attachments.length > 0) {\n                  <div class=\"message-attachments-list\">\n                    @for (att of msg.attachments; track att.name) {\n                      <a [href]=\"att.url\" target=\"_blank\" class=\"msg-attachment-item\" download>\n                        @if (att.type.startsWith('image/')) {\n                          <div class=\"msg-attachment-img-preview\">\n                            <img [src]=\"att.url\" [alt]=\"att.name\" />\n                          </div>\n                        } @else {\n                          <span class=\"msg-attachment-icon\">📄</span>\n                        }\n                        <span class=\"msg-attachment-name\" [title]=\"att.name\">{{ att.name }}</span>\n                      </a>\n                    }\n                  </div>\n                }\n\n                <!-- Time & Feedback -->\n                <div class=\"msg-meta-row\">\n                  <span class=\"msg-time\">{{ msg.timestamp | date:'shortTime' }}</span>\n                  @if (msg.role !== 'user') {\n                    <div class=\"feedback-actions\">\n                      <button type=\"button\" class=\"feedback-tiny-btn\" [class.selected]=\"msgFeedbackMap[msg.id] === 'like'\" (click)=\"onMessageRating(msg.id, 'like')\" title=\"Helpful\">👍</button>\n                      <button type=\"button\" class=\"feedback-tiny-btn\" [class.selected]=\"msgFeedbackMap[msg.id] === 'dislike'\" (click)=\"onMessageRating(msg.id, 'dislike')\" title=\"Unhelpful\">👎</button>\n                    </div>\n                  }\n                </div>\n              </div>\n            </div>\n          }\n\n          <!-- Typing Indicator -->\n          @if (isTyping()) {\n            <div class=\"message-wrapper assistant-msg\">\n              <div class=\"msg-avatar\" [style.background]=\"avatarBg()\">\n                <span>{{ getInitials(agentName()) }}</span>\n              </div>\n              <div class=\"msg-bubble-container\">\n                <div class=\"msg-bubble typing-bubble\">\n                  <div class=\"typing-indicator\">\n                    <span></span>\n                    <span></span>\n                    <span></span>\n                  </div>\n                </div>\n              </div>\n            </div>\n          }\n        </div>\n      </div>\n\n      <!-- Quick Replies -->\n      @if (quickReplies() && quickReplies().length > 0) {\n        <div class=\"quick-replies-container\">\n          <div class=\"quick-replies-list\">\n            @for (reply of quickReplies(); track reply.value) {\n              <button class=\"quick-reply-btn\" (click)=\"quickReplyClick.emit(reply)\">\n                @if (reply.icon) {\n                  <span class=\"reply-icon\">{{ reply.icon }}</span>\n                }\n                <span>{{ reply.label }}</span>\n              </button>\n            }\n          </div>\n        </div>\n      }\n\n      <!-- Chat Footer / Input -->\n      <div class=\"ngx-ai-chat-footer\">\n        <!-- Attachment Previews -->\n        @if (attachedFiles().length > 0) {\n          <div class=\"attachments-preview-bar\">\n            @for (file of attachedFiles(); track file.name) {\n              <div class=\"attachment-preview-tag\">\n                @if (file.type.startsWith('image/')) {\n                  <img [src]=\"file.url\" class=\"attachment-thumb\" />\n                } @else {\n                  <span class=\"attachment-icon\">📄</span>\n                }\n                <span class=\"attachment-name\">{{ file.name }}</span>\n                <button type=\"button\" class=\"remove-attachment-btn\" (click)=\"removeAttachment(file)\">✕</button>\n              </div>\n            }\n          </div>\n        }\n        <form (ngSubmit)=\"onSubmit()\" class=\"input-form\">\n          <button type=\"button\" class=\"attach-btn\" (click)=\"fileInput.click()\" title=\"Attach files\" [disabled]=\"disabled()\">\n            <svg viewBox=\"0 0 24 24\" class=\"svg-icon\"><path d=\"M16.5 6v11.5c0 2.21-1.79 4-4 4s-4-1.79-4-4V5a2.5 2.5 0 0 1 5 0v10.5c0 .83-.67 1.5-1.5 1.5s-1.5-.67-1.5-1.5V6H9v9.5c0 2.48 2.02 4.5 4.5 4.5s4.5-2.02 4.5-4.5V5a4 4 0 0 0-8 0v12c0 3.86 3.14 7 7 7s7-3.14 7-7V6h-1.5z\"/></svg>\n          </button>\n          <input #fileInput type=\"file\" style=\"display: none\" (change)=\"onFileSelected($event)\" multiple />\n          <input\n            type=\"text\"\n            class=\"chat-input\"\n            [placeholder]=\"placeholder()\"\n            [(ngModel)]=\"inputText\"\n            name=\"messageText\"\n            [disabled]=\"disabled()\"\n            autocomplete=\"off\"\n          />\n          <button type=\"submit\" class=\"send-btn\" [disabled]=\"(!inputText.trim() && attachedFiles().length === 0) || disabled()\" title=\"Send message\">\n            <svg viewBox=\"0 0 24 24\" class=\"svg-icon\"><path d=\"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z\"/></svg>\n          </button>\n        </form>\n      </div>\n    </div>\n  `,\n  styles: [`\n    :host {\n      display: block;\n      height: 100%;\n      font-family: var(--ngx-font-family, system-ui, -apple-system, sans-serif);\n    }\n\n    .ngx-ai-chat-container {\n      display: flex;\n      flex-direction: column;\n      height: 100%;\n      background: var(--ngx-ai-chat-bg, #ffffff);\n      border: 1px solid var(--ngx-ai-chat-border, #e2e8f0);\n      border-radius: 12px;\n      overflow: hidden;\n      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);\n      transition: all 0.3s ease;\n    }\n\n    .ngx-ai-chat-container.dark-mode {\n      --ngx-ai-chat-bg: #1e293b;\n      --ngx-ai-chat-border: #334155;\n      --ngx-ai-header-bg: #0f172a;\n      --ngx-ai-header-text: #f8fafc;\n      --ngx-ai-bubble-user-bg: #3b82f6;\n      --ngx-ai-bubble-user-text: #ffffff;\n      --ngx-ai-bubble-assistant-bg: #334155;\n      --ngx-ai-bubble-assistant-text: #f8fafc;\n      --ngx-ai-input-bg: #0f172a;\n      --ngx-ai-input-text: #f8fafc;\n      --ngx-ai-input-border: #334155;\n    }\n\n    /* Header */\n    .ngx-ai-chat-header {\n      display: flex;\n      align-items: center;\n      padding: 14px 18px;\n      background: var(--ngx-ai-header-bg, #f8fafc);\n      border-bottom: 1px solid var(--ngx-ai-chat-border, #e2e8f0);\n      gap: 12px;\n    }\n\n    .header-avatar {\n      position: relative;\n      width: 40px;\n      height: 40px;\n      border-radius: 50%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      font-weight: 700;\n      color: #fff;\n      font-size: 14px;\n    }\n\n    .header-avatar img {\n      width: 100%;\n      height: 100%;\n      object-fit: cover;\n      border-radius: 50%;\n    }\n\n    .status-indicator {\n      position: absolute;\n      bottom: 0;\n      right: 0;\n      width: 10px;\n      height: 10px;\n      border-radius: 50%;\n      background: #94a3b8;\n      border: 2px solid var(--ngx-ai-chat-bg, #fff);\n    }\n\n    .status-indicator.online {\n      background: #10b981;\n    }\n\n    .header-info {\n      flex: 1;\n    }\n\n    .agent-title {\n      font-weight: 600;\n      font-size: 15px;\n      color: var(--ngx-ai-header-text, #1e293b);\n    }\n\n    .agent-status {\n      font-size: 12px;\n      color: #64748b;\n    }\n\n    .header-actions {\n      display: flex;\n      gap: 8px;\n    }\n\n    .header-btn {\n      background: none;\n      border: none;\n      padding: 8px;\n      border-radius: 50%;\n      cursor: pointer;\n      color: #64748b;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      transition: background-color 0.2s;\n    }\n\n    .header-btn:hover {\n      background-color: rgba(100, 116, 139, 0.1);\n    }\n\n    .svg-icon {\n      width: 20px;\n      height: 20px;\n      fill: currentColor;\n    }\n\n    /* Chat Body */\n    .ngx-ai-chat-body {\n      flex: 1;\n      overflow-y: auto;\n      padding: 16px 20px;\n      display: flex;\n      flex-direction: column;\n    }\n\n    .messages-list {\n      display: flex;\n      flex-direction: column;\n      gap: 20px;\n    }\n\n    .message-wrapper {\n      display: flex;\n      gap: 12px;\n      max-width: 85%;\n    }\n\n    .message-wrapper.user-msg {\n      align-self: flex-end;\n      flex-direction: row-reverse;\n      max-width: 75%;\n    }\n\n    .message-wrapper.assistant-msg {\n      align-self: flex-start;\n    }\n\n    .msg-avatar {\n      width: 32px;\n      height: 32px;\n      border-radius: 50%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      color: #fff;\n      font-weight: 600;\n      font-size: 12px;\n      flex-shrink: 0;\n    }\n\n    .msg-avatar img {\n      width: 100%;\n      height: 100%;\n      object-fit: cover;\n      border-radius: 50%;\n    }\n\n    .msg-bubble-container {\n      display: flex;\n      flex-direction: column;\n      gap: 4px;\n    }\n\n    .user-msg .msg-bubble-container {\n      align-items: flex-end;\n    }\n\n    .msg-sender {\n      font-size: 11px;\n      font-weight: 600;\n      color: #64748b;\n      margin-left: 4px;\n    }\n\n    .msg-bubble {\n      padding: 12px 16px;\n      border-radius: 16px;\n      font-size: 14px;\n      line-height: 1.5;\n      word-break: break-word;\n    }\n\n    .user-msg .msg-bubble {\n      background: var(--ngx-ai-bubble-user-bg, #1a73e8);\n      color: var(--ngx-ai-bubble-user-text, #ffffff);\n      border-bottom-right-radius: 4px;\n    }\n\n    .assistant-msg .msg-bubble {\n      background: var(--ngx-ai-bubble-assistant-bg, #f1f5f9);\n      color: var(--ngx-ai-bubble-assistant-text, #1e293b);\n      border-bottom-left-radius: 4px;\n    }\n\n    .msg-text {\n      white-space: pre-wrap;\n    }\n\n    .msg-time {\n      font-size: 10px;\n      color: #94a3b8;\n      margin: 0 4px;\n    }\n\n    /* Agent Steps Accordion */\n    .agent-steps-container {\n      margin-top: 10px;\n      border: 1px solid rgba(148, 163, 184, 0.2);\n      border-radius: 8px;\n      overflow: hidden;\n      background: rgba(255, 255, 255, 0.05);\n    }\n\n    .steps-header {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      padding: 8px 12px;\n      background: rgba(148, 163, 184, 0.1);\n      border-bottom: 1px solid rgba(148, 163, 184, 0.1);\n    }\n\n    .steps-title-text {\n      font-size: 12px;\n      font-weight: 600;\n      opacity: 0.8;\n    }\n\n    .steps-badge {\n      font-size: 10px;\n      font-weight: 700;\n      background: rgba(148, 163, 184, 0.2);\n      padding: 2px 6px;\n      border-radius: 10px;\n    }\n\n    .steps-list {\n      display: flex;\n      flex-direction: column;\n    }\n\n    .agent-step-item {\n      border-bottom: 1px solid rgba(148, 163, 184, 0.08);\n    }\n\n    .agent-step-item:last-child {\n      border-bottom: none;\n    }\n\n    .step-summary {\n      display: flex;\n      align-items: center;\n      padding: 8px 12px;\n      cursor: pointer;\n      font-size: 12px;\n      gap: 8px;\n      transition: background-color 0.2s;\n    }\n\n    .step-summary:hover {\n      background: rgba(148, 163, 184, 0.05);\n    }\n\n    .step-status-icon {\n      width: 16px;\n      height: 16px;\n      border-radius: 50%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      font-size: 10px;\n      font-weight: bold;\n      color: #fff;\n    }\n\n    .step-status-icon.success {\n      background: #10b981;\n    }\n\n    .step-status-icon.error {\n      background: #ef4444;\n    }\n\n    .step-status-icon.running {\n      background: #3b82f6;\n    }\n\n    .step-name {\n      flex: 1;\n      font-weight: 500;\n    }\n\n    .step-duration {\n      font-size: 10px;\n      opacity: 0.6;\n    }\n\n    .step-chevron {\n      font-size: 8px;\n      transition: transform 0.2s;\n      opacity: 0.5;\n    }\n\n    .step-chevron.expanded {\n      transform: rotate(180deg);\n    }\n\n    .step-details {\n      padding: 8px 12px;\n      background: rgba(0, 0, 0, 0.02);\n      display: flex;\n      flex-direction: column;\n      gap: 8px;\n      border-top: 1px solid rgba(148, 163, 184, 0.05);\n    }\n\n    .step-detail-section {\n      display: flex;\n      flex-direction: column;\n      gap: 4px;\n    }\n\n    .detail-label {\n      font-size: 10px;\n      font-weight: 600;\n      opacity: 0.6;\n      text-transform: uppercase;\n      letter-spacing: 0.3px;\n    }\n\n    .detail-code {\n      margin: 0;\n      padding: 6px 10px;\n      background: rgba(0, 0, 0, 0.05);\n      border-radius: 4px;\n      font-family: monospace;\n      font-size: 11px;\n      overflow-x: auto;\n      white-space: pre-wrap;\n      max-height: 120px;\n    }\n\n    /* Structured Response Carousel Cards */\n    .cards-carousel {\n      display: flex;\n      gap: 12px;\n      overflow-x: auto;\n      padding: 10px 4px 6px;\n      margin-top: 8px;\n      scroll-snap-type: x mandatory;\n      scrollbar-width: thin;\n    }\n\n    .cards-carousel::-webkit-scrollbar {\n      height: 6px;\n    }\n    .cards-carousel::-webkit-scrollbar-thumb {\n      background: rgba(148, 163, 184, 0.3);\n      border-radius: 3px;\n    }\n\n    .ai-carousel-card {\n      flex: 0 0 240px;\n      background: var(--ngx-ai-chat-bg, #fff);\n      border: 1px solid var(--ngx-ai-chat-border, #e2e8f0);\n      border-radius: 12px;\n      overflow: hidden;\n      display: flex;\n      flex-direction: column;\n      scroll-snap-align: start;\n      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);\n    }\n\n    .card-img-container {\n      height: 120px;\n      overflow: hidden;\n    }\n\n    .card-img-container img {\n      width: 100%;\n      height: 100%;\n      object-fit: cover;\n    }\n\n    .card-body {\n      padding: 12px;\n      display: flex;\n      flex-direction: column;\n      flex: 1;\n    }\n\n    .card-title {\n      font-size: 14px;\n      font-weight: 600;\n      margin: 0 0 2px;\n    }\n\n    .card-subtitle {\n      font-size: 12px;\n      font-weight: 500;\n      color: #64748b;\n      margin: 0 0 6px;\n    }\n\n    .card-description {\n      font-size: 12px;\n      color: #64748b;\n      line-height: 1.4;\n      margin: 0 0 12px;\n      flex: 1;\n    }\n\n    .card-actions {\n      display: flex;\n      flex-direction: column;\n      gap: 6px;\n    }\n\n    .card-action-btn {\n      width: 100%;\n      padding: 6px 12px;\n      font-size: 12px;\n      font-weight: 600;\n      border-radius: 6px;\n      border: 1px solid var(--ngx-ai-chat-border, #e2e8f0);\n      background: none;\n      cursor: pointer;\n      transition: all 0.2s;\n    }\n\n    .card-action-btn.btn-primary {\n      background: var(--ngx-ai-bubble-user-bg, #1a73e8);\n      color: #fff;\n      border-color: transparent;\n    }\n\n    .card-action-btn:hover {\n      opacity: 0.9;\n      transform: translateY(-1px);\n    }\n\n    /* Typing Indicator Bubble */\n    .typing-bubble {\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      padding: 12px 20px;\n    }\n\n    .typing-indicator {\n      display: flex;\n      gap: 4px;\n    }\n\n    .typing-indicator span {\n      width: 8px;\n      height: 8px;\n      background: #94a3b8;\n      border-radius: 50%;\n      animation: typing 1.4s infinite ease-in-out both;\n    }\n\n    .typing-indicator span:nth-child(1) { animation-delay: -0.32s; }\n    .typing-indicator span:nth-child(2) { animation-delay: -0.16s; }\n\n    @keyframes typing {\n      0%, 80%, 100% { transform: scale(0); }\n      40% { transform: scale(1.0); }\n    }\n\n    .streaming-cursor {\n      display: inline-block;\n      width: 6px;\n      height: 14px;\n      background-color: var(--ngx-ai-chat-primary, #3b82f6);\n      margin-left: 4px;\n      animation: blink-cursor 1s step-end infinite;\n      vertical-align: middle;\n    }\n\n    @keyframes blink-cursor {\n      from, to { background-color: transparent }\n      50% { background-color: var(--ngx-ai-chat-primary, #3b82f6) }\n    }\n\n    /* Spinner */\n    .spinner {\n      width: 10px;\n      height: 10px;\n      border: 2px solid rgba(255, 255, 255, 0.3);\n      border-radius: 50%;\n      border-top-color: #fff;\n      animation: spin 1s ease-in-out infinite;\n    }\n\n    @keyframes spin {\n      to { transform: rotate(360deg); }\n    }\n\n    /* Quick Replies */\n    .quick-replies-container {\n      padding: 10px 16px 4px;\n      background: transparent;\n    }\n\n    .quick-replies-list {\n      display: flex;\n      gap: 8px;\n      overflow-x: auto;\n      padding-bottom: 6px;\n      scrollbar-width: none;\n    }\n\n    .quick-replies-list::-webkit-scrollbar {\n      display: none;\n    }\n\n    .quick-reply-btn {\n      flex: 0 0 auto;\n      padding: 6px 14px;\n      border-radius: 18px;\n      border: 1px solid var(--ngx-ai-chat-border, #e2e8f0);\n      background: var(--ngx-ai-chat-bg, #fff);\n      font-size: 13px;\n      font-weight: 500;\n      color: #64748b;\n      cursor: pointer;\n      display: flex;\n      align-items: center;\n      gap: 6px;\n      transition: all 0.2s;\n    }\n\n    .quick-reply-btn:hover {\n      border-color: var(--ngx-ai-bubble-user-bg, #1a73e8);\n      color: var(--ngx-ai-bubble-user-bg, #1a73e8);\n      background-color: rgba(26, 115, 232, 0.04);\n    }\n\n    /* Chat Footer */\n    .ngx-ai-chat-footer {\n      padding: 14px 18px;\n      background: var(--ngx-ai-header-bg, #f8fafc);\n      border-top: 1px solid var(--ngx-ai-chat-border, #e2e8f0);\n    }\n\n    .input-form {\n      display: flex;\n      gap: 10px;\n    }\n\n    .chat-input {\n      flex: 1;\n      padding: 10px 14px;\n      border-radius: 8px;\n      border: 1px solid var(--ngx-ai-input-border, #cbd5e1);\n      background: var(--ngx-ai-input-bg, #fff);\n      color: var(--ngx-ai-input-text, #1e293b);\n      font-size: 14px;\n      outline: none;\n      transition: border-color 0.2s;\n    }\n\n    .chat-input:focus {\n      border-color: var(--ngx-ai-bubble-user-bg, #1a73e8);\n    }\n\n    .send-btn {\n      width: 38px;\n      height: 38px;\n      border-radius: 8px;\n      background: var(--ngx-ai-bubble-user-bg, #1a73e8);\n      color: #fff;\n      border: none;\n      cursor: pointer;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      transition: background-color 0.2s, transform 0.1s;\n    }\n\n    .send-btn:hover:not(:disabled) {\n      background-color: #1557b0;\n      transform: translateY(-1px);\n    }\n\n    .send-btn:disabled {\n      background-color: #94a3b8;\n      cursor: not-allowed;\n    }\n\n    /* Attachment Previews in Input Area */\n    .attachments-preview-bar {\n      display: flex;\n      gap: 8px;\n      padding: 8px;\n      overflow-x: auto;\n      border-bottom: 1px solid var(--ngx-ai-chat-border, #e2e8f0);\n      background: var(--ngx-ai-chat-bg, #ffffff);\n    }\n    .attachment-preview-tag {\n      display: flex;\n      align-items: center;\n      gap: 6px;\n      padding: 4px 8px;\n      background: #f1f5f9;\n      border: 1px solid #cbd5e1;\n      border-radius: 6px;\n      font-size: 11px;\n      max-width: 150px;\n    }\n    .attachment-thumb {\n      width: 18px;\n      height: 18px;\n      object-fit: cover;\n      border-radius: 2px;\n    }\n    .attachment-icon {\n      font-size: 12px;\n    }\n    .attachment-name {\n      white-space: nowrap;\n      overflow: hidden;\n      text-overflow: ellipsis;\n      flex: 1;\n      color: #334155;\n    }\n    .remove-attachment-btn {\n      background: none;\n      border: none;\n      color: #94a3b8;\n      cursor: pointer;\n      padding: 0 2px;\n      font-size: 10px;\n    }\n    .remove-attachment-btn:hover {\n      color: #ef4444;\n    }\n\n    /* Attachments inside bubble */\n    .message-attachments-list {\n      display: flex;\n      flex-direction: column;\n      gap: 6px;\n      margin-top: 8px;\n    }\n    .msg-attachment-item {\n      display: flex;\n      align-items: center;\n      gap: 8px;\n      padding: 6px 10px;\n      background: rgba(255,255,255,0.7);\n      border: 1px solid rgba(0,0,0,0.06);\n      border-radius: 8px;\n      text-decoration: none;\n      color: inherit;\n      max-width: 250px;\n      font-size: 12px;\n      transition: background 0.2s;\n    }\n    .msg-attachment-item:hover {\n      background: rgba(255,255,255,0.9);\n    }\n    .msg-attachment-img-preview {\n      width: 32px;\n      height: 32px;\n      overflow: hidden;\n      border-radius: 4px;\n    }\n    .msg-attachment-img-preview img {\n      width: 100%;\n      height: 100%;\n      object-fit: cover;\n    }\n    .msg-attachment-icon {\n      font-size: 16px;\n    }\n    .msg-attachment-name {\n      white-space: nowrap;\n      overflow: hidden;\n      text-overflow: ellipsis;\n      font-weight: 500;\n    }\n\n    /* Attach button */\n    .attach-btn {\n      background: none;\n      border: none;\n      color: #64748b;\n      cursor: pointer;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      padding: 8px;\n      border-radius: 8px;\n      transition: background 0.2s;\n    }\n    .attach-btn:hover:not(:disabled) {\n      background: rgba(100, 116, 139, 0.1);\n      color: #334155;\n    }\n    .attach-btn:disabled {\n      opacity: 0.5;\n      cursor: not-allowed;\n    }\n\n    /* Meta Row / Feedback Row styling */\n    .msg-meta-row {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      margin-top: 4px;\n      min-width: 80px;\n    }\n    .feedback-actions {\n      display: flex;\n      gap: 4px;\n      opacity: 0.3;\n      transition: opacity 0.2s;\n    }\n    .message-wrapper:hover .feedback-actions {\n      opacity: 1;\n    }\n    .feedback-tiny-btn {\n      background: transparent;\n      border: none;\n      cursor: pointer;\n      font-size: 10px;\n      padding: 2px;\n      border-radius: 4px;\n      transition: background 0.2s;\n    }\n    .feedback-tiny-btn:hover {\n      background: rgba(0,0,0,0.08);\n    }\n    .feedback-tiny-btn.selected {\n      background: rgba(0,0,0,0.12);\n      transform: scale(1.1);\n    }\n\n    /* Drag & Drop Overlay */\n    .ngx-ai-chat-container {\n      position: relative;\n    }\n    .ngx-ai-chat-container.drag-over {\n      border-color: #3b82f6 !important;\n      box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);\n    }\n    .drag-dropzone-overlay {\n      position: absolute;\n      top: 0;\n      left: 0;\n      right: 0;\n      bottom: 0;\n      z-index: 100;\n      background: rgba(59, 130, 246, 0.85);\n      backdrop-filter: blur(4px);\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      color: #ffffff;\n      border-radius: 12px;\n      pointer-events: none;\n      animation: fadeIn 0.2s ease;\n    }\n    .drag-dropzone-content {\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n      gap: 12px;\n      font-weight: 600;\n      font-size: 15px;\n    }\n    .drag-icon {\n      width: 48px;\n      height: 48px;\n      fill: currentColor;\n    }\n    @keyframes fadeIn {\n      from { opacity: 0; }\n      to { opacity: 1; }\n    }\n\n    /* Scroll to bottom pill button */\n    .ngx-ai-chat-body {\n      position: relative;\n    }\n    .scroll-bottom-pill {\n      position: absolute;\n      bottom: 16px;\n      left: 50%;\n      transform: translateX(-50%);\n      z-index: 10;\n      display: flex;\n      align-items: center;\n      gap: 6px;\n      background: #3b82f6;\n      color: #ffffff;\n      border: none;\n      border-radius: 20px;\n      padding: 6px 14px;\n      font-size: 12px;\n      font-weight: 600;\n      cursor: pointer;\n      box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);\n      transition: all 0.2s ease;\n    }\n    .scroll-bottom-pill:hover {\n      background: #2563eb;\n      transform: translateX(-50%) translateY(-2px);\n    }\n    .pill-icon {\n      width: 16px;\n      height: 16px;\n      fill: currentColor;\n    }\n\n    /* Code block syntax highlighting */\n    .code-container {\n      background: #0f172a !important;\n      color: #e2e8f0 !important;\n      border-radius: 8px !important;\n      padding: 10px 14px !important;\n      font-family: 'Fira Code', Consolas, Monaco, monospace !important;\n      font-size: 12.5px !important;\n      margin: 10px 0 !important;\n      border-left: 4px solid #3b82f6 !important;\n      overflow-x: auto !important;\n    }\n    .code-header-bar {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      font-size: 10px;\n      font-weight: 700;\n      color: #94a3b8;\n      margin-bottom: 6px;\n      padding-bottom: 4px;\n      border-bottom: 1px solid rgba(255, 255, 255, 0.1);\n      text-transform: uppercase;\n      letter-spacing: 0.5px;\n    }\n    .copy-code-btn {\n      background: rgba(255, 255, 255, 0.1) !important;\n      color: #f8fafc !important;\n      border: 1px solid rgba(255, 255, 255, 0.15) !important;\n      padding: 2px 8px !important;\n      border-radius: 4px !important;\n      cursor: pointer !important;\n      font-size: 10px !important;\n      font-family: sans-serif !important;\n      transition: all 0.2s !important;\n    }\n    .copy-code-btn:hover {\n      background: rgba(255, 255, 255, 0.2) !important;\n    }\n    .token-kw { color: #f472b6; font-weight: 600; }\n    .token-str { color: #a7f3d0; }\n    .token-num { color: #fde047; }\n    .token-cmt { color: #64748b; font-style: italic; }\n    .token-fn { color: #60a5fa; }\n\n    /* Dark Mode specific overrides */\n    .dark-mode .attachments-preview-bar {\n      border-bottom-color: var(--ngx-ai-chat-border, #334155);\n      background: var(--ngx-ai-chat-bg, #1e293b);\n    }\n    .dark-mode .attachment-preview-tag {\n      background: #334155;\n      border-color: #475569;\n    }\n    .dark-mode .attachment-name {\n      color: #f8fafc;\n    }\n    .dark-mode .msg-attachment-item {\n      background: rgba(15, 23, 42, 0.4);\n      border-color: rgba(255,255,255,0.06);\n    }\n    .dark-mode .msg-attachment-item:hover {\n      background: rgba(15, 23, 42, 0.6);\n    }\n    .dark-mode .attach-btn {\n      color: #94a3b8;\n    }\n    .dark-mode .attach-btn:hover:not(:disabled) {\n      background: rgba(255, 255, 255, 0.05);\n      color: #f8fafc;\n    }\n    .dark-mode .feedback-tiny-btn:hover {\n      background: rgba(255,255,255,0.08);\n    }\n    .dark-mode .feedback-tiny-btn.selected {\n      background: rgba(255,255,255,0.15);\n    }\n  `]\n})\nexport class AIChatComponent {\n  private sanitizer = inject(DomSanitizer);\n  messages = input<AIMessage[]>([]);\n  agentName = input('AI Agent');\n  agentAvatarUrl = input('');\n  isOnline = input(true);\n  isTyping = input(false);\n  isStreaming = input(false);\n  showSenderNames = input(false);\n  theme = input<'light' | 'dark'>('light');\n  placeholder = input('Type a message...');\n  disabled = input(false);\n  quickReplies = input<QuickReply[]>([]);\n  avatarBg = input('#4f46e5');\n\n  sendMessage = output<string>();\n  quickReplyClick = output<QuickReply>();\n  cardActionClick = output<AICardAction>();\n  clearHistory = output<void>();\n  messageFeedback = output<{ messageId: string; rating: 'like' | 'dislike' }>();\n  fileAttached = output<{ name: string; type: string; size: number; file: File }>();\n  messageSent = output<{ content: string; attachments: { name: string; url: string; type: string; size?: number }[] }>();\n\n  chatBody = viewChild<ElementRef>('chatBody');\n\n  inputText = '';\n  attachedFiles = signal<{ name: string; type: string; size: number; url: string; rawFile: File }[]>([]);\n  msgFeedbackMap: Record<string, 'like' | 'dislike'> = {};\n\n  isUserScrolledUp = signal(false);\n  isDraggingOver = signal(false);\n\n  @HostListener('click', ['$event'])\n  onHostClick(event: MouseEvent) {\n    const target = event.target as HTMLElement;\n    if (target && target.classList.contains('copy-code-btn')) {\n      const codeText = target.getAttribute('data-code');\n      if (codeText) {\n        navigator.clipboard.writeText(decodeURIComponent(codeText)).then(() => {\n          target.innerText = 'Copied!';\n          setTimeout(() => { target.innerText = 'Copy'; }, 2000);\n        });\n      }\n    }\n  }\n\n  onBodyScroll(): void {\n    const el = this.chatBody()?.nativeElement;\n    if (el) {\n      const isAtBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 40;\n      this.isUserScrolledUp.set(!isAtBottom);\n    }\n  }\n\n  onDragOver(event: DragEvent): void {\n    event.preventDefault();\n    event.stopPropagation();\n    if (!this.disabled()) {\n      this.isDraggingOver.set(true);\n    }\n  }\n\n  onDragLeave(event: DragEvent): void {\n    event.preventDefault();\n    event.stopPropagation();\n    this.isDraggingOver.set(false);\n  }\n\n  onDrop(event: DragEvent): void {\n    event.preventDefault();\n    event.stopPropagation();\n    this.isDraggingOver.set(false);\n    if (this.disabled()) return;\n    if (event.dataTransfer && event.dataTransfer.files.length > 0) {\n      this.processFiles(Array.from(event.dataTransfer.files));\n    }\n  }\n\n  onFileSelected(event: Event) {\n    const inputEl = event.target as HTMLInputElement;\n    if (inputEl && inputEl.files) {\n      this.processFiles(Array.from(inputEl.files));\n      inputEl.value = '';\n    }\n  }\n\n  private processFiles(filesArray: File[]) {\n    filesArray.forEach(file => {\n      const fileUrl = URL.createObjectURL(file);\n      const attachment = {\n        name: file.name,\n        type: file.type,\n        size: file.size,\n        url: fileUrl,\n        rawFile: file\n      };\n      this.attachedFiles.update(current => [...current, attachment]);\n      this.fileAttached.emit({\n        name: file.name,\n        type: file.type,\n        size: file.size,\n        file: file\n      });\n    });\n  }\n\n  removeAttachment(file: any) {\n    URL.revokeObjectURL(file.url);\n    this.attachedFiles.update(current => current.filter(f => f.url !== file.url));\n  }\n\n  onMessageRating(messageId: string, rating: 'like' | 'dislike') {\n    if (this.msgFeedbackMap[messageId] === rating) {\n      delete this.msgFeedbackMap[messageId];\n    } else {\n      this.msgFeedbackMap[messageId] = rating;\n    }\n    this.messageFeedback.emit({ messageId, rating });\n  }\n\n  constructor() {\n    // Automatically scroll to bottom when messages or typing status changes\n    effect(() => {\n      this.messages();\n      this.isTyping();\n      this.scrollToBottom();\n    });\n  }\n\n  onSubmit(): void {\n    const text = this.inputText.trim();\n    if (!text && this.attachedFiles().length === 0) return;\n    if (this.disabled()) return;\n    \n    const attachmentsData = this.attachedFiles().map(f => ({\n      name: f.name,\n      url: f.url,\n      type: f.type,\n      size: f.size\n    }));\n    \n    this.sendMessage.emit(text);\n    this.messageSent.emit({ content: text, attachments: attachmentsData });\n    \n    this.attachedFiles.set([]);\n    this.inputText = '';\n    this.scrollToBottom(true);\n  }\n\n  toggleStep(step: AgentStep): void {\n    step.collapsed = !step.collapsed;\n  }\n\n  getCompletedStepsCount(steps: AgentStep[]): number {\n    return steps.filter(s => s.status === 'success' || s.status === 'error').length;\n  }\n\n  getInitials(name: string): string {\n    if (!name) return 'AI';\n    const parts = name.split(' ');\n    if (parts.length >= 2) {\n      return (parts[0][0] + parts[1][0]).toUpperCase();\n    }\n    return name.slice(0, 2).toUpperCase();\n  }\n\n  scrollToBottom(force = false): void {\n    if (this.isUserScrolledUp() && !force) return;\n    setTimeout(() => {\n      const el = this.chatBody()?.nativeElement;\n      if (el) {\n        el.scrollTop = el.scrollHeight;\n        if (force) this.isUserScrolledUp.set(false);\n      }\n    }, 60);\n  }\n\n  private highlightSyntax(code: string): string {\n    // Lightweight regex syntax tokenizer\n    return code\n      .replace(/(\".*?\"|'.*?'|`[^`]*`)/g, '<span class=\"token-str\">$1</span>')\n      .replace(/\\b(const|let|var|function|return|import|export|class|if|else|true|false|async|await|interface|type)\\b/g, '<span class=\"token-kw\">$1</span>')\n      .replace(/\\b([a-zA-Z_]\\w*)(?=\\()/g, '<span class=\"token-fn\">$1</span>')\n      .replace(/\\b(\\d+)\\b/g, '<span class=\"token-num\">$1</span>');\n  }\n\n  formatMessage(content: string): SafeHtml {\n    if (!content) return '';\n    let formatted = content\n      .replace(/&/g, '&amp;')\n      .replace(/</g, '&lt;')\n      .replace(/>/g, '&gt;');\n\n    // Handle unclosed triple backticks (code blocks) during streaming\n    const codeBlockCount = (formatted.match(/```/g) || []).length;\n    if (codeBlockCount % 2 !== 0) {\n      formatted += '\\n```';\n    }\n\n    // Handle unclosed bold markers during streaming\n    const boldCount = (formatted.match(/\\*\\*/g) || []).length;\n    if (boldCount % 2 !== 0) {\n      formatted += '**';\n    }\n\n    // Handle unclosed inline code backticks during streaming\n    const inlineCodeCount = (formatted.match(/`/g) || []).length;\n    if (inlineCodeCount % 2 !== 0) {\n      formatted += '`';\n    }\n\n    // Bold markdown helper\n    formatted = formatted.replace(/\\*\\*(.*?)\\*\\*/g, '<strong>$1</strong>');\n\n    // Code blocks helper with syntax highlighting & copy button\n    formatted = formatted.replace(/```(\\w*)\\n([\\s\\S]*?)```/g, (_, lang, code) => {\n      const language = lang || 'code';\n      const cleanCode = code.trim();\n      const highlighted = this.highlightSyntax(cleanCode);\n      const encoded = encodeURIComponent(cleanCode);\n      return `\n        <div class=\"code-container\">\n          <div class=\"code-header-bar\">\n            <span>${language}</span>\n            <button class=\"copy-code-btn\" data-code=\"${encoded}\">Copy</button>\n          </div>\n          <pre style=\"margin: 0; white-space: pre-wrap;\"><code>${highlighted}</code></pre>\n        </div>\n      `;\n    });\n\n    // Inline code helper\n    formatted = formatted.replace(/`(.*?)`/g, '<code style=\"background: rgba(0,0,0,0.06); padding: 2px 4px; border-radius: 4px; font-family: monospace; font-size: 12px;\">$1</code>');\n\n    return this.sanitizer.bypassSecurityTrustHtml(formatted);\n  }\n}\n","import { Component, input, signal, output, ElementRef, ViewChild } from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\nexport interface WidgetMessage {\n  sender: 'user' | 'assistant';\n  text: string;\n  timestamp: Date;\n}\n\n@Component({\n  selector: 'ngx-ai-chat-widget',\n  standalone: true,\n  imports: [CommonModule],\n  template: `\n    <!-- Floating Action Button (FAB) -->\n    <button\n      class=\"widget-fab\"\n      [class.active]=\"isOpen()\"\n      (click)=\"toggleOpen()\"\n      [title]=\"isOpen() ? 'Close Chat' : 'Open Chat'\"\n    >\n      <span class=\"fab-icon\">{{ isOpen() ? '✕' : icon() }}</span>\n    </button>\n\n    <!-- Chat Overlay Pane -->\n    <div class=\"widget-overlay-pane\" [class.open]=\"isOpen()\">\n      <!-- Header -->\n      <div class=\"widget-header\">\n        <div class=\"header-details\">\n          <div class=\"widget-avatar\">🤖</div>\n          <div>\n            <h4 class=\"widget-title\">{{ agentName() }}</h4>\n            <span class=\"widget-status\">Online</span>\n          </div>\n        </div>\n        <button class=\"close-btn\" (click)=\"closeOpen()\">✕</button>\n      </div>\n\n      <!-- Feed Body -->\n      <div class=\"widget-body\" #scrollContainer (scroll)=\"onBodyScroll()\">\n        @if (isUserScrolledUp()) {\n          <button type=\"button\" class=\"widget-scroll-bottom-pill\" (click)=\"scrollToBottom(true)\">\n            ↓ New messages\n          </button>\n        }\n        @for (msg of messages(); track $index) {\n          <div class=\"message-row\" [class.user-row]=\"msg.sender === 'user'\">\n            @if (msg.sender === 'assistant') {\n              <div class=\"msg-avatar\">🤖</div>\n            }\n            <div class=\"msg-bubble\" [class.user-bubble]=\"msg.sender === 'user'\">\n              <div class=\"msg-text\">{{ msg.text }}</div>\n              <div class=\"msg-time\">{{ msg.timestamp | date:'shortTime' }}</div>\n            </div>\n          </div>\n        }\n      </div>\n\n      <!-- Quick Replies -->\n      @if (quickReplies().length > 0) {\n        <div class=\"widget-quick-replies\">\n          @for (reply of quickReplies(); track reply) {\n            <button class=\"reply-pill\" (click)=\"selectReply(reply)\">\n              {{ reply }}\n            </button>\n          }\n        </div>\n      }\n\n      <!-- Footer Input -->\n      <div class=\"widget-footer\">\n        <input\n          #inputBox\n          type=\"text\"\n          [placeholder]=\"placeholder()\"\n          (keydown.enter)=\"sendMessage(inputBox.value); inputBox.value = ''\"\n          class=\"widget-input\"\n        />\n        <button\n          class=\"send-btn\"\n          (click)=\"sendMessage(inputBox.value); inputBox.value = ''\"\n        >\n          ➔\n        </button>\n      </div>\n    </div>\n  `,\n  styles: [`\n    :host {\n      position: fixed;\n      bottom: 24px;\n      right: 24px;\n      z-index: 9999;\n      font-family: inherit;\n    }\n\n    /* FAB styling */\n    .widget-fab {\n      width: 56px;\n      height: 56px;\n      border-radius: 50%;\n      border: none;\n      background: var(--primary-gradient, linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%));\n      color: #ffffff;\n      font-size: 24px;\n      cursor: pointer;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      box-shadow: 0 4px 16px rgba(79, 70, 229, 0.4);\n      transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n    }\n    .widget-fab:hover {\n      transform: scale(1.06);\n    }\n    .widget-fab.active {\n      transform: rotate(90deg) scale(0.95);\n      background: #0f172a;\n      box-shadow: 0 2px 8px rgba(0,0,0,0.15);\n    }\n    .fab-icon {\n      line-height: 1;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n    }\n\n    /* Overlay container pane */\n    .widget-overlay-pane {\n      position: absolute;\n      bottom: 72px;\n      right: 0;\n      width: 360px;\n      height: 500px;\n      background: var(--bg-secondary, #ffffff);\n      border: 1px solid var(--border-color, #e2e8f0);\n      border-radius: 16px;\n      box-shadow: 0 10px 25px -5px rgba(0,0,0,0.15), 0 8px 10px -6px rgba(0,0,0,0.1);\n      display: flex;\n      flex-direction: column;\n      overflow: hidden;\n      opacity: 0;\n      transform: translateY(20px) scale(0.95);\n      pointer-events: none;\n      transition: all 0.28s cubic-bezier(0.34, 1.56, 0.64, 1);\n      transform-origin: bottom right;\n    }\n    .widget-overlay-pane.open {\n      opacity: 1;\n      transform: translateY(0) scale(1);\n      pointer-events: auto;\n    }\n\n    /* Header styling */\n    .widget-header {\n      padding: 14px 16px;\n      background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);\n      color: #ffffff;\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      border-bottom: 1px solid rgba(255, 255, 255, 0.08);\n    }\n    .header-details {\n      display: flex;\n      align-items: center;\n      gap: 10px;\n    }\n    .widget-avatar {\n      font-size: 20px;\n      background: rgba(255, 255, 255, 0.1);\n      width: 36px;\n      height: 36px;\n      border-radius: 50%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n    }\n    .widget-title {\n      margin: 0;\n      font-size: 14px;\n      font-weight: 750;\n    }\n    .widget-status {\n      font-size: 10px;\n      color: #10b981;\n      font-weight: 600;\n      display: flex;\n      align-items: center;\n      gap: 4px;\n    }\n    .widget-status::before {\n      content: '';\n      display: inline-block;\n      width: 6px;\n      height: 6px;\n      border-radius: 50%;\n      background: #10b981;\n    }\n    .close-btn {\n      background: none;\n      border: none;\n      color: rgba(255, 255, 255, 0.6);\n      font-size: 16px;\n      cursor: pointer;\n      padding: 4px;\n      transition: color 0.15s;\n    }\n    .close-btn:hover {\n      color: #ffffff;\n    }\n\n    /* Body messages list feed */\n    .widget-body {\n      flex: 1;\n      overflow-y: auto;\n      padding: 16px;\n      display: flex;\n      flex-direction: column;\n      gap: 12px;\n      background: var(--bg-primary, #f8fafc);\n    }\n    .message-row {\n      display: flex;\n      gap: 8px;\n      align-items: flex-start;\n      max-width: 85%;\n    }\n    .message-row.user-row {\n      align-self: flex-end;\n      flex-direction: row-reverse;\n    }\n    .msg-avatar {\n      width: 28px;\n      height: 28px;\n      border-radius: 50%;\n      background: #e2e8f0;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      font-size: 14px;\n      flex-shrink: 0;\n    }\n    .msg-bubble {\n      background: var(--bg-secondary, #ffffff);\n      border: 1px solid var(--border-color, #e2e8f0);\n      padding: 10px 12px;\n      border-radius: 12px;\n      border-top-left-radius: 2px;\n      box-shadow: var(--shadow-sm);\n    }\n    .message-row.user-row .msg-bubble {\n      background: var(--primary-color, #4f46e5);\n      color: #ffffff;\n      border: none;\n      border-top-left-radius: 12px;\n      border-top-right-radius: 2px;\n    }\n    .msg-text {\n      font-size: 13px;\n      line-height: 1.5;\n      word-break: break-word;\n    }\n    .msg-time {\n      font-size: 9px;\n      color: var(--text-secondary, #64748b);\n      text-align: right;\n      margin-top: 4px;\n    }\n    .message-row.user-row .msg-time {\n      color: rgba(255, 255, 255, 0.7);\n    }\n\n    /* Quick replies section */\n    .widget-quick-replies {\n      padding: 8px 12px;\n      background: var(--bg-primary, #f8fafc);\n      display: flex;\n      gap: 6px;\n      overflow-x: auto;\n      border-top: 1px solid var(--border-color, #e2e8f0);\n      white-space: nowrap;\n    }\n    .widget-quick-replies::-webkit-scrollbar {\n      display: none;\n    }\n    .reply-pill {\n      padding: 6px 12px;\n      background: var(--bg-secondary, #ffffff);\n      border: 1px solid var(--primary-color, #4f46e5);\n      color: var(--primary-color, #4f46e5);\n      border-radius: 16px;\n      font-size: 11px;\n      font-weight: 600;\n      cursor: pointer;\n      transition: all 0.15s;\n      font-family: inherit;\n    }\n    .reply-pill:hover {\n      background: var(--primary-color, #4f46e5);\n      color: #ffffff;\n    }\n\n    /* Footer text area input */\n    .widget-footer {\n      padding: 12px 14px;\n      background: var(--bg-secondary, #ffffff);\n      border-top: 1px solid var(--border-color, #e2e8f0);\n      display: flex;\n      gap: 8px;\n      align-items: center;\n    }\n    .widget-input {\n      flex: 1;\n      border: 1px solid var(--border-color, #e2e8f0);\n      border-radius: 20px;\n      padding: 8px 16px;\n      font-size: 13px;\n      outline: none;\n      background: var(--bg-primary, #f8fafc);\n      color: var(--text-primary, #0f172a);\n      transition: border-color 0.15s;\n    }\n    .widget-input:focus {\n      border-color: var(--primary-color, #4f46e5);\n    }\n    .send-btn {\n      width: 32px;\n      height: 32px;\n      border-radius: 50%;\n      border: none;\n      background: var(--primary-color, #4f46e5);\n      color: #ffffff;\n      cursor: pointer;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      font-size: 14px;\n      transition: background 0.15s;\n    }\n    .send-btn:hover {\n      background: var(--primary-color-dark, #3730a3);\n    }\n\n    /* Scroll to bottom pill */\n    .widget-body {\n      position: relative;\n    }\n    .widget-scroll-bottom-pill {\n      position: absolute;\n      bottom: 12px;\n      left: 50%;\n      transform: translateX(-50%);\n      z-index: 10;\n      background: #4f46e5;\n      color: #ffffff;\n      border: none;\n      border-radius: 16px;\n      padding: 4px 12px;\n      font-size: 11px;\n      font-weight: 600;\n      cursor: pointer;\n      box-shadow: 0 4px 10px rgba(79, 70, 229, 0.4);\n      transition: all 0.2s ease;\n    }\n    .widget-scroll-bottom-pill:hover {\n      background: #4338ca;\n    }\n  `]\n})\nexport class AIChatWidgetComponent {\n  agentName = input<string>('AI Assistant');\n  icon = input<string>('💬');\n  placeholder = input<string>('Type a message...');\n  welcomeMessage = input<string>('Hi! How can I help you today?');\n  quickReplies = input<string[]>([]);\n\n  messageSent = output<string>();\n\n  isOpen = signal<boolean>(false);\n  messages = signal<WidgetMessage[]>([]);\n  isUserScrolledUp = signal<boolean>(false);\n\n  @ViewChild('scrollContainer') scrollContainer!: ElementRef<HTMLDivElement>;\n\n  onBodyScroll(): void {\n    if (this.scrollContainer?.nativeElement) {\n      const el = this.scrollContainer.nativeElement;\n      const isAtBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 30;\n      this.isUserScrolledUp.set(!isAtBottom);\n    }\n  }\n\n  toggleOpen(): void {\n    this.isOpen.update(o => !o);\n    if (this.isOpen() && this.messages().length === 0) {\n      this.messages.set([\n        { sender: 'assistant', text: this.welcomeMessage(), timestamp: new Date() }\n      ]);\n    }\n  }\n\n  closeOpen(): void {\n    this.isOpen.set(false);\n  }\n\n  sendMessage(text: string): void {\n    const trimmed = text.trim();\n    if (!trimmed) return;\n\n    this.messages.update(msgs => [\n      ...msgs,\n      { sender: 'user', text: trimmed, timestamp: new Date() }\n    ]);\n    this.messageSent.emit(trimmed);\n    this.scrollToBottom(true);\n  }\n\n  selectReply(reply: string): void {\n    this.sendMessage(reply);\n  }\n\n  addAssistantReply(text: string): void {\n    this.messages.update(msgs => [\n      ...msgs,\n      { sender: 'assistant', text, timestamp: new Date() }\n    ]);\n    this.scrollToBottom();\n  }\n\n  scrollToBottom(force = false): void {\n    if (this.isUserScrolledUp() && !force) return;\n    setTimeout(() => {\n      if (this.scrollContainer?.nativeElement) {\n        this.scrollContainer.nativeElement.scrollTop = this.scrollContainer.nativeElement.scrollHeight;\n        if (force) this.isUserScrolledUp.set(false);\n      }\n    }, 50);\n  }\n}\n","import { Component, input, signal, computed, effect } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\n\n@Component({\n  selector: 'ngx-ai-prompt-editor',\n  standalone: true,\n  imports: [CommonModule, FormsModule],\n  template: `\n    <div class=\"prompt-studio-wrapper\">\n      <div class=\"prompt-studio-grid\">\n        \n        <!-- Left Panel: Prompt Configuration -->\n        <div class=\"studio-config-card\">\n          <div class=\"card-header\">\n            <div class=\"header-top-row\">\n              <div>\n                <h3>Prompt Engineering Studio</h3>\n                <p>Design instructions, parse template variables, and estimate token costs.</p>\n              </div>\n              <div class=\"model-select-wrap\">\n                <label class=\"model-label\">Model Engine</label>\n                <select \n                  class=\"studio-select\" \n                  [ngModel]=\"selectedModel()\" \n                  (ngModelChange)=\"selectedModel.set($event)\"\n                >\n                  <option value=\"gpt-4o\">GPT-4o ($0.0025/1k)</option>\n                  <option value=\"gpt-4o-mini\">GPT-4o-mini ($0.00015/1k)</option>\n                  <option value=\"claude-3-5-sonnet\">Claude 3.5 Sonnet ($0.003/1k)</option>\n                  <option value=\"gemini-1-5-pro\">Gemini 1.5 Pro ($0.00125/1k)</option>\n                </select>\n              </div>\n            </div>\n\n            <!-- Token & Cost Metrics Banner -->\n            <div class=\"metrics-banner\">\n              <div class=\"metric-card\">\n                <span class=\"metric-val\">{{ systemTokens() }}</span>\n                <span class=\"metric-lbl\">System Tokens</span>\n              </div>\n              <div class=\"metric-card\">\n                <span class=\"metric-val\">{{ compiledTokens() }}</span>\n                <span class=\"metric-lbl\">Prompt Tokens</span>\n              </div>\n              <div class=\"metric-card highlight\">\n                <span class=\"metric-val\">{{ totalPromptTokens() }}</span>\n                <span class=\"metric-lbl\">Total Tokens</span>\n              </div>\n              <div class=\"metric-card cost\">\n                <span class=\"metric-val\">{{ estimatedCost() }}</span>\n                <span class=\"metric-lbl\">Est. Cost / Run</span>\n              </div>\n            </div>\n          </div>\n\n          <div class=\"config-body\">\n            <!-- System Instructions -->\n            <div class=\"form-group\">\n              <label class=\"group-label\">System Instructions</label>\n              <textarea\n                class=\"studio-textarea\"\n                rows=\"3\"\n                [ngModel]=\"systemPrompt\"\n                (ngModelChange)=\"onSystemPromptChange($event)\"\n                placeholder=\"You are a helpful and precise assistant...\"\n              ></textarea>\n            </div>\n\n            <!-- Prompt Template -->\n            <div class=\"form-group\">\n              <div class=\"label-with-tools\">\n                <label class=\"group-label\">Prompt Template</label>\n                <button type=\"button\" class=\"add-var-btn\" (click)=\"addNewVariable()\">+ Add {{ '{' }}{{ '{' }}var{{ '}' }}{{ '}' }}</button>\n              </div>\n              <div class=\"help-text\">Use double braces <code>{{ '{' }}{{ '{' }}variable{{ '}' }}{{ '}' }}</code> to define dynamic parameters.</div>\n              <textarea\n                class=\"studio-textarea template-textarea\"\n                rows=\"6\"\n                [ngModel]=\"templateText()\"\n                (ngModelChange)=\"onTemplateChange($event)\"\n                placeholder=\"Write your template here...\"\n              ></textarea>\n            </div>\n\n            <!-- Parameters Grid -->\n            <div class=\"parameters-grid\">\n              <div class=\"form-group\">\n                <label class=\"group-label\">Temperature: {{ temperature() }}</label>\n                <input\n                  type=\"range\"\n                  min=\"0\"\n                  max=\"1\"\n                  step=\"0.05\"\n                  [ngModel]=\"temperature()\"\n                  (input)=\"onTempChange($event)\"\n                  class=\"studio-slider\"\n                />\n              </div>\n\n              <div class=\"form-group\">\n                <label class=\"group-label\">Max Output Tokens</label>\n                <input\n                  type=\"number\"\n                  [(ngModel)]=\"maxTokens\"\n                  class=\"studio-input\"\n                  min=\"1\"\n                  max=\"4096\"\n                />\n              </div>\n            </div>\n\n            <!-- Dynamic Variables -->\n            @if (parsedVariables().length > 0) {\n              <div class=\"form-group variables-section\">\n                <label class=\"group-label\">Parsed Template Variables</label>\n                <div class=\"variables-grid\">\n                  @for (v of parsedVariables(); track v) {\n                    <div class=\"var-row\">\n                      <span class=\"var-name\">{{ v }}</span>\n                      <input\n                        type=\"text\"\n                        [value]=\"getVarValue(v)\"\n                        (input)=\"setVarValue(v, $event)\"\n                        class=\"studio-input var-input\"\n                        [placeholder]=\"'Value for ' + v\"\n                      />\n                    </div>\n                  }\n                </div>\n              </div>\n            }\n          </div>\n        </div>\n\n        <!-- Right Panel: Live Compiler & Simulator -->\n        <div class=\"studio-output-card\">\n          <div class=\"card-header\">\n            <h3>Live Preview &amp; Test</h3>\n            <p>Inspect compiled prompt outputs and trigger mock run generations.</p>\n          </div>\n\n          <div class=\"output-body\">\n            <!-- Compiled Output Box -->\n            <div class=\"preview-group\">\n              <label class=\"group-label\">Compiled Prompt Preview</label>\n              <div class=\"prompt-preview-box\">\n                @if (compiledPrompt()) {\n                  <p class=\"compiled-text\">{{ compiledPrompt() }}</p>\n                } @else {\n                  <span class=\"empty-text\">Write a template to preview compiled text...</span>\n                }\n              </div>\n            </div>\n\n            <!-- Run Control -->\n            <div class=\"run-control-row\">\n              <button\n                class=\"run-btn\"\n                [disabled]=\"isRunning()\"\n                (click)=\"triggerRun()\"\n              >\n                {{ isRunning() ? 'Generating Response...' : '⚡ Run Simulation' }}\n              </button>\n            </div>\n\n            <!-- Simulated Output Response -->\n            <div class=\"preview-group flex-fill\">\n              <label class=\"group-label\">Simulated AI Response</label>\n              <div class=\"simulation-response-box\" [class.loading]=\"isRunning()\">\n                @if (isRunning()) {\n                  <div class=\"pulse-loader\">\n                    <span></span><span></span><span></span>\n                  </div>\n                } @else if (simulatedResponse()) {\n                  <div class=\"response-text\">{{ simulatedResponse() }}</div>\n                } @else {\n                  <span class=\"empty-text\">Click Run Simulation to generate a mock response.</span>\n                }\n              </div>\n            </div>\n          </div>\n        </div>\n\n      </div>\n    </div>\n  `,\n  styles: [`\n    .prompt-studio-wrapper {\n      width: 100%;\n      height: 100%;\n      padding: 4px;\n      font-family: inherit;\n    }\n\n    .prompt-studio-grid {\n      display: grid;\n      grid-template-columns: 1.2fr 1fr;\n      gap: 24px;\n      align-items: stretch;\n    }\n    @media (max-width: 960px) {\n      .prompt-studio-grid {\n        grid-template-columns: 1fr;\n      }\n    }\n\n    /* Cards layouts */\n    .studio-config-card, .studio-output-card {\n      background: var(--bg-secondary, #ffffff);\n      border: 1px solid var(--border-color, #e2e8f0);\n      border-radius: 12px;\n      box-shadow: var(--shadow-sm);\n      display: flex;\n      flex-direction: column;\n      overflow: hidden;\n    }\n\n    .card-header {\n      padding: 16px 20px;\n      border-bottom: 1px solid var(--border-color, #e2e8f0);\n    }\n    .header-top-row {\n      display: flex;\n      justify-content: space-between;\n      align-items: flex-start;\n      gap: 16px;\n      flex-wrap: wrap;\n    }\n    .card-header h3 {\n      margin: 0 0 4px;\n      font-size: 16px;\n      font-weight: 800;\n      color: var(--text-primary, #0f172a);\n    }\n    .card-header p {\n      margin: 0;\n      font-size: 12px;\n      color: var(--text-secondary, #64748b);\n    }\n\n    .model-select-wrap {\n      display: flex;\n      flex-direction: column;\n      gap: 4px;\n    }\n    .model-label {\n      font-size: 10px;\n      font-weight: 700;\n      text-transform: uppercase;\n      color: #64748b;\n    }\n    .studio-select {\n      background: var(--bg-primary, #f8fafc);\n      color: var(--text-primary, #0f172a);\n      border: 1px solid var(--border-color, #cbd5e1);\n      border-radius: 6px;\n      padding: 4px 8px;\n      font-size: 12px;\n      font-weight: 600;\n      outline: none;\n    }\n\n    .metrics-banner {\n      display: flex;\n      gap: 12px;\n      margin-top: 14px;\n      flex-wrap: wrap;\n    }\n    .metric-card {\n      flex: 1;\n      min-width: 90px;\n      background: var(--bg-primary, #f8fafc);\n      border: 1px solid var(--border-color, #e2e8f0);\n      border-radius: 8px;\n      padding: 8px 10px;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n    }\n    .metric-card.highlight {\n      background: rgba(79, 70, 229, 0.08);\n      border-color: rgba(79, 70, 229, 0.3);\n    }\n    .metric-card.cost {\n      background: rgba(16, 185, 129, 0.08);\n      border-color: rgba(16, 185, 129, 0.3);\n    }\n    .metric-val {\n      font-size: 14px;\n      font-weight: 800;\n      color: var(--text-primary, #0f172a);\n    }\n    .metric-card.cost .metric-val {\n      color: #059669;\n    }\n    .metric-card.highlight .metric-val {\n      color: #4f46e5;\n    }\n    .metric-lbl {\n      font-size: 10px;\n      font-weight: 600;\n      color: #64748b;\n      margin-top: 2px;\n    }\n\n    .label-with-tools {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n    }\n    .add-var-btn {\n      background: transparent;\n      border: 1px solid #4f46e5;\n      color: #4f46e5;\n      border-radius: 4px;\n      padding: 2px 8px;\n      font-size: 11px;\n      font-weight: 600;\n      cursor: pointer;\n      transition: all 0.2s;\n    }\n    .add-var-btn:hover {\n      background: #4f46e5;\n      color: #ffffff;\n    }\n\n    .config-body, .output-body {\n      padding: 20px;\n      display: flex;\n      flex-direction: column;\n      gap: 16px;\n      flex: 1;\n    }\n    .flex-fill {\n      flex: 1;\n      display: flex;\n      flex-direction: column;\n    }\n\n    /* Forms */\n    .form-group {\n      display: flex;\n      flex-direction: column;\n      gap: 6px;\n    }\n    .group-label {\n      font-size: 11px;\n      font-weight: 750;\n      text-transform: uppercase;\n      letter-spacing: 0.5px;\n      color: var(--text-secondary, #64748b);\n    }\n    .help-text {\n      font-size: 11px;\n      color: var(--text-secondary, #64748b);\n      margin-bottom: 2px;\n    }\n    .help-text code {\n      background: var(--border-light, #f1f5f9);\n      padding: 1px 4px;\n      border-radius: 3px;\n      font-family: monospace;\n      font-weight: 700;\n    }\n\n    /* Input elements */\n    .studio-textarea {\n      width: 100%;\n      border: 1px solid var(--border-color, #e2e8f0);\n      border-radius: 8px;\n      padding: 10px 12px;\n      font-size: 13px;\n      outline: none;\n      background: var(--bg-primary, #f8fafc);\n      color: var(--text-primary, #0f172a);\n      font-family: inherit;\n      resize: vertical;\n      transition: border-color 0.15s;\n    }\n    .template-textarea {\n      font-family: 'Cascadia Code', Consolas, Monaco, monospace;\n      font-size: 12px;\n    }\n    .studio-textarea:focus, .studio-input:focus {\n      border-color: var(--primary-color, #4f46e5);\n    }\n\n    .studio-input {\n      border: 1px solid var(--border-color, #e2e8f0);\n      border-radius: 8px;\n      padding: 8px 12px;\n      font-size: 13px;\n      background: var(--bg-primary, #f8fafc);\n      color: var(--text-primary, #0f172a);\n      outline: none;\n      transition: border-color 0.15s;\n      font-family: inherit;\n    }\n\n    .parameters-grid {\n      display: grid;\n      grid-template-columns: 1fr 1fr;\n      gap: 16px;\n    }\n\n    .studio-slider {\n      width: 100%;\n      cursor: pointer;\n      accent-color: var(--primary-color, #4f46e5);\n      margin-top: 6px;\n    }\n\n    /* Variables settings */\n    .variables-section {\n      border-top: 1px dashed var(--border-color, #e2e8f0);\n      padding-top: 16px;\n      margin-top: 8px;\n    }\n    .variables-grid {\n      display: flex;\n      flex-direction: column;\n      gap: 10px;\n      margin-top: 6px;\n    }\n    .var-row {\n      display: grid;\n      grid-template-columns: 100px 1fr;\n      align-items: center;\n      gap: 12px;\n    }\n    .var-name {\n      font-family: monospace;\n      font-size: 12px;\n      font-weight: 700;\n      color: var(--primary-color, #4f46e5);\n      overflow: hidden;\n      text-overflow: ellipsis;\n      white-space: nowrap;\n    }\n    .var-input {\n      padding: 6px 12px;\n    }\n\n    /* Live Output Box styling */\n    .preview-group {\n      display: flex;\n      flex-direction: column;\n      gap: 6px;\n    }\n    .prompt-preview-box, .simulation-response-box {\n      border: 1px solid var(--border-color, #e2e8f0);\n      border-radius: 8px;\n      padding: 12px 14px;\n      background: var(--bg-primary, #f8fafc);\n      min-height: 80px;\n      max-height: 180px;\n      overflow-y: auto;\n      font-size: 13px;\n      line-height: 1.5;\n    }\n    .prompt-preview-box {\n      font-family: monospace;\n      font-size: 12px;\n      color: var(--text-primary, #0f172a);\n    }\n    .simulation-response-box {\n      flex: 1;\n      display: flex;\n      align-items: flex-start;\n    }\n    .simulation-response-box.loading {\n      align-items: center;\n      justify-content: center;\n    }\n    .empty-text {\n      color: var(--text-secondary, #64748b);\n      font-style: italic;\n    }\n    .compiled-text, .response-text {\n      margin: 0;\n      white-space: pre-wrap;\n    }\n\n    /* Buttons */\n    .run-control-row {\n      display: flex;\n      justify-content: flex-end;\n    }\n    .run-btn {\n      background: var(--primary-gradient, linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%));\n      color: #ffffff;\n      border: none;\n      padding: 10px 20px;\n      border-radius: 8px;\n      font-size: 13px;\n      font-weight: 700;\n      cursor: pointer;\n      box-shadow: 0 4px 12px rgba(79, 70, 229, 0.25);\n      transition: all 0.2s;\n      font-family: inherit;\n    }\n    .run-btn:hover:not(:disabled) {\n      transform: translateY(-1px);\n      box-shadow: 0 6px 16px rgba(79, 70, 229, 0.35);\n    }\n    .run-btn:disabled {\n      opacity: 0.6;\n      cursor: not-allowed;\n    }\n\n    /* Loader animations */\n    .pulse-loader {\n      display: flex;\n      gap: 6px;\n    }\n    .pulse-loader span {\n      width: 8px;\n      height: 8px;\n      background: var(--primary-color, #4f46e5);\n      border-radius: 50%;\n      animation: bounce 1.4s infinite ease-in-out both;\n    }\n    .pulse-loader span:nth-child(1) { animation-delay: -0.32s; }\n    .pulse-loader span:nth-child(2) { animation-delay: -0.16s; }\n\n    @keyframes bounce {\n      0%, 80%, 100% { transform: scale(0); }\n      40% { transform: scale(1.0); }\n    }\n  `]\n})\nexport class AIPromptEditorComponent {\n  // Inputs Binds\n  initialTemplate = input<string>('Write a greeting letter to {{user_name}} recommending dynamic integrations for {{product_name}}.');\n  initialSystem = input<string>('You are an encouraging and helpful product specialist.');\n\n  // Component Internal State Signals\n  systemPromptSignal = signal('');\n  get systemPrompt(): string {\n    return this.systemPromptSignal();\n  }\n  set systemPrompt(val: string) {\n    this.systemPromptSignal.set(val || '');\n  }\n\n  templateText = signal('');\n  temperature = signal(0.7);\n  maxTokens = 512;\n  \n  selectedModel = signal<'gpt-4o' | 'gpt-4o-mini' | 'claude-3-5-sonnet' | 'gemini-1-5-pro'>('gpt-4o');\n  varValues = signal<Record<string, string>>({});\n  isRunning = signal(false);\n  simulatedResponse = signal('');\n\n  readonly MODEL_RATES: Record<string, { name: string; ratePer1k: number }> = {\n    'gpt-4o': { name: 'GPT-4o', ratePer1k: 0.0025 },\n    'gpt-4o-mini': { name: 'GPT-4o-mini', ratePer1k: 0.00015 },\n    'claude-3-5-sonnet': { name: 'Claude 3.5 Sonnet', ratePer1k: 0.003 },\n    'gemini-1-5-pro': { name: 'Gemini 1.5 Pro', ratePer1k: 0.00125 },\n  };\n\n  // Real-time Token Count Calculations (~4 chars per token)\n  systemTokens = computed(() => Math.ceil((this.systemPromptSignal() || '').length / 4));\n  compiledTokens = computed(() => Math.ceil((this.compiledPrompt() || '').length / 4));\n  totalPromptTokens = computed(() => this.systemTokens() + this.compiledTokens());\n\n  // Real-time Cost Estimation ($ per request)\n  estimatedCost = computed(() => {\n    const rate = this.MODEL_RATES[this.selectedModel()]?.ratePer1k || 0.0025;\n    const total = this.totalPromptTokens();\n    const cost = (total / 1000) * rate;\n    return cost < 0.00005 ? '< $0.0001' : `$${cost.toFixed(5)}`;\n  });\n\n  constructor() {\n    // Populate defaults on initialize\n    effect(() => {\n      this.templateText.set(this.initialTemplate());\n      this.systemPromptSignal.set(this.initialSystem());\n    }, { allowSignalWrites: true });\n  }\n\n  onSystemPromptChange(text: string): void {\n    this.systemPromptSignal.set(text || '');\n  }\n\n  // Parse variables from template string dynamically\n  parsedVariables = computed(() => {\n    const text = this.templateText();\n    const matches = text.match(/\\{\\{([^}]+)\\}\\}/g) || [];\n    // Deduplicate array values\n    const unique = [...new Set(matches.map(m => m.replace(/[{}]/g, '').trim()))];\n    return unique;\n  });\n\n  // Compiled dynamic prompt preview\n  compiledPrompt = computed(() => {\n    let t = this.templateText();\n    const dict = this.varValues();\n    \n    this.parsedVariables().forEach(v => {\n      const placeholder = `{{${v}}}`;\n      const val = dict[v] || '';\n      t = t.split(placeholder).join(val);\n    });\n\n    return t;\n  });\n\n  onTemplateChange(text: string): void {\n    this.templateText.set(text);\n  }\n\n  onTempChange(event: Event): void {\n    const val = (event.target as HTMLInputElement).value;\n    this.temperature.set(Number(val));\n  }\n\n  getVarValue(vName: string): string {\n    // Default initial values to make playground look populated\n    const values = this.varValues();\n    if (values[vName] !== undefined) return values[vName];\n    \n    // Set typical defaults\n    if (vName === 'user_name') return 'John Doe';\n    if (vName === 'product_name') return 'ngx-core-components';\n    return '';\n  }\n\n  setVarValue(vName: string, event: Event): void {\n    const val = (event.target as HTMLInputElement).value;\n    this.varValues.update(dict => ({ ...dict, [vName]: val }));\n  }\n\n  addNewVariable(): void {\n    const varName = prompt('Enter new template variable name (e.g. user_role):');\n    if (varName) {\n      const clean = varName.trim().replace(/[^a-zA-Z0-9_]/g, '');\n      if (clean) {\n        this.templateText.update(t => t + (t.endsWith(' ') || t === '' ? '' : ' ') + `{{${clean}}}`);\n      }\n    }\n  }\n\n  triggerRun(): void {\n    if (this.isRunning()) return;\n    this.isRunning.set(true);\n    this.simulatedResponse.set('');\n\n    // Simulate Streaming response output\n    setTimeout(() => {\n      this.isRunning.set(false);\n      const name = this.varValues()['user_name'] || 'John Doe';\n      const prod = this.varValues()['product_name'] || 'ngx-core-components';\n      \n      this.simulatedResponse.set(\n        `Dear ${name},\\n\\n` +\n        `Thank you for exploring ${prod}! We are thrilled to assist you. ` +\n        `Implementing our modular Angular components will instantly modernize your user interface and ensure 100% signal-driven reactive state transitions.\\n\\n` +\n        `Best regards,\\n` +\n        `The Product Specialist Team`\n      );\n    }, 1800);\n  }\n}\n","import { Component, input, signal, output, HostListener, ViewChild, computed } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\n\n@Component({\n  selector: 'ngx-ai-code-editor',\n  standalone: true,\n  imports: [CommonModule, FormsModule],\n  template: `\n    <div class=\"code-editor-wrapper\" [class.dark]=\"theme() === 'dark'\" [class.focused]=\"isFocused()\">\n      <!-- Toolbar Header -->\n      <div class=\"editor-header\">\n        <div class=\"header-left\">\n          <span class=\"editor-dot red\"></span>\n          <span class=\"editor-dot yellow\"></span>\n          <span class=\"editor-dot green\"></span>\n          <span class=\"editor-lang-badge\">{{ language() | uppercase }}</span>\n        </div>\n        <div class=\"header-right\">\n          <button \n            *ngIf=\"hasSuggestion() && !suggestionAccepted()\"\n            class=\"toolbar-toggle-btn\"\n            [class.active]=\"diffMode()\"\n            (click)=\"toggleDiffMode()\"\n          >\n            {{ diffMode() ? '👁️ Editor' : '🔍 Diff View' }}\n          </button>\n          <span class=\"ai-pill\">✨ AI Suggestion Active</span>\n          <button class=\"icon-btn\" (click)=\"copyCode()\" [title]=\"copyTooltip()\">\n            {{ copyText() }}\n          </button>\n        </div>\n      </div>\n\n      <!-- Editor Canvas -->\n      <div class=\"editor-canvas\" *ngIf=\"!diffMode()\" (click)=\"focusTextarea()\">\n        <!-- Line Numbers -->\n        <div class=\"line-numbers\">\n          @for (line of lines(); track $index) {\n            <div class=\"line-num\">{{ $index + 1 }}</div>\n          }\n        </div>\n \n        <!-- Code Content Area -->\n        <div class=\"code-content-container\">\n          <textarea\n            #editorInput\n            class=\"hidden-textarea\"\n            [ngModel]=\"code()\"\n            (ngModelChange)=\"onCodeChange($event)\"\n            (focus)=\"isFocused.set(true)\"\n            (blur)=\"isFocused.set(false)\"\n            (keydown)=\"handleKeydown($event)\"\n            [disabled]=\"disabled()\"\n          ></textarea>\n \n          <!-- Rendered Code Grid with Ghost Text -->\n          <pre class=\"rendered-code\"><code><span [innerHTML]=\"highlightedCode()\"></span><span class=\"cursor-pipe\" *ngIf=\"isFocused()\">|</span><span \n            *ngIf=\"hasSuggestion() && !suggestionAccepted()\" \n            class=\"ghost-text\"\n          >{{ currentSuggestion() }}</span></code></pre>\n        </div>\n      </div>\n\n      <!-- Diff Canvas -->\n      <div class=\"diff-canvas\" *ngIf=\"diffMode() && hasSuggestion() && !suggestionAccepted()\">\n        <!-- Left original panel -->\n        <div class=\"diff-pane original-pane\">\n          <div class=\"diff-pane-title\">Original</div>\n          <pre class=\"diff-code\"><code>{{ code() }}</code></pre>\n        </div>\n        <!-- Right proposed panel -->\n        <div class=\"diff-pane proposed-pane\">\n          <div class=\"diff-pane-title\">Proposed</div>\n          <pre class=\"diff-code\"><code>{{ code() }}<span class=\"diff-highlight\">{{ currentSuggestion() }}</span></code></pre>\n        </div>\n      </div>\n\n      <!-- Suggestion Panel Controls -->\n      <div class=\"editor-footer\" *ngIf=\"hasSuggestion() && !suggestionAccepted()\">\n        <div class=\"suggestion-info\">\n          <span class=\"sparkle\">✨</span>\n          <span class=\"desc\">Press <kbd class=\"editor-kbd\">Tab</kbd> to accept, or <kbd class=\"editor-kbd\">Esc</kbd> to dismiss.</span>\n          @if (suggestions().length > 1) {\n            <div class=\"suggestions-navigator\">\n              <button type=\"button\" class=\"nav-arrow\" (click)=\"prevSuggestion()\" title=\"Previous suggestion\">◀</button>\n              <span class=\"nav-count\">{{ activeSuggestionIndex() + 1 }} / {{ suggestions().length }}</span>\n              <button type=\"button\" class=\"nav-arrow\" (click)=\"nextSuggestion()\" title=\"Next suggestion\">▶</button>\n            </div>\n          }\n        </div>\n        <div class=\"action-buttons\">\n          <button class=\"footer-btn reject-btn\" (click)=\"decline()\">Decline (Esc)</button>\n          <button class=\"footer-btn accept-btn\" (click)=\"accept()\">Accept (Tab)</button>\n        </div>\n      </div>\n\n      <!-- Explanation Panel -->\n      <div class=\"explanation-panel\" *ngIf=\"explanation() && showExplanation()\">\n        <div class=\"explanation-header\">\n          <span class=\"sparkle\">💡 AI Explanation</span>\n          <button class=\"close-explanation-btn\" (click)=\"showExplanation.set(false)\">✕</button>\n        </div>\n        <div class=\"explanation-body\">\n          {{ explanation() }}\n        </div>\n      </div>\n\n      <!-- Secondary Panel Controls (when suggestion is accepted or inactive) -->\n      <div class=\"editor-footer justify-end\" *ngIf=\"!hasSuggestion() || suggestionAccepted()\">\n        <div class=\"action-buttons\">\n          <button class=\"footer-btn secondary-btn\" (click)=\"explainSuggestedCode()\">Explain Code</button>\n          <button class=\"footer-btn primary-btn\" (click)=\"triggerRegenerate()\">Re-generate Suggestion</button>\n        </div>\n      </div>\n    </div>\n  `,\n  styles: [`\n    :host {\n      display: block;\n      width: 100%;\n      font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;\n    }\n\n    .code-editor-wrapper {\n      border: 1px solid var(--border-color, #e2e8f0);\n      border-radius: var(--radius-md, 10px);\n      background: var(--bg-secondary, #ffffff);\n      box-shadow: var(--shadow-md, 0 4px 6px -1px rgba(0, 0, 0, 0.08));\n      overflow: hidden;\n      display: flex;\n      flex-direction: column;\n      transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n    }\n\n    .code-editor-wrapper.focused {\n      border-color: var(--primary-color, #4f46e5);\n      box-shadow: 0 0 0 3px var(--primary-glow, rgba(79, 70, 229, 0.15));\n    }\n\n    /* Toolbar Header */\n    .editor-header {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      padding: 10px 16px;\n      background: var(--border-light, #f1f5f9);\n      border-bottom: 1px solid var(--border-color, #e2e8f0);\n    }\n\n    .header-left {\n      display: flex;\n      align-items: center;\n      gap: 6px;\n    }\n\n    .editor-dot {\n      width: 10px;\n      height: 10px;\n      border-radius: 50%;\n    }\n    .editor-dot.red { background: #ef4444; }\n    .editor-dot.yellow { background: #f59e0b; }\n    .editor-dot.green { background: #10b981; }\n\n    .editor-lang-badge {\n      margin-left: 10px;\n      font-size: 11px;\n      font-weight: 700;\n      color: var(--text-secondary, #475569);\n      background: rgba(0, 0, 0, 0.05);\n      padding: 2px 6px;\n      border-radius: 4px;\n      letter-spacing: 0.5px;\n    }\n\n    .header-right {\n      display: flex;\n      align-items: center;\n      gap: 12px;\n    }\n\n    .ai-pill {\n      font-size: 11px;\n      font-weight: 600;\n      background: linear-gradient(135deg, rgba(79, 70, 229, 0.1) 0%, rgba(124, 58, 237, 0.1) 100%);\n      color: #6d28d9;\n      padding: 2px 8px;\n      border-radius: 9999px;\n      border: 1px solid rgba(124, 58, 237, 0.2);\n    }\n\n    .icon-btn {\n      background: transparent;\n      border: none;\n      color: var(--text-secondary, #475569);\n      cursor: pointer;\n      font-size: 11px;\n      padding: 4px 8px;\n      border-radius: 4px;\n      transition: background 0.2s;\n    }\n    .icon-btn:hover {\n      background: rgba(0, 0, 0, 0.05);\n      color: var(--text-primary, #0f172a);\n    }\n\n    /* Editor Canvas */\n    .editor-canvas {\n      display: flex;\n      flex-direction: row;\n      position: relative;\n      min-height: 150px;\n      background: var(--bg-secondary, #ffffff);\n      cursor: text;\n    }\n\n    .line-numbers {\n      padding: 16px 8px 16px 12px;\n      border-right: 1px solid var(--border-color, #e2e8f0);\n      background: rgba(0, 0, 0, 0.01);\n      user-select: none;\n      text-align: right;\n      min-width: 40px;\n    }\n\n    .line-num {\n      color: var(--text-muted, #94a3b8);\n      font-size: 12px;\n      line-height: 1.6;\n      height: 19.2px;\n    }\n\n    .code-content-container {\n      position: relative;\n      flex: 1;\n      overflow: hidden;\n    }\n\n    .hidden-textarea {\n      position: absolute;\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n      opacity: 0;\n      z-index: 2;\n      resize: none;\n      border: none;\n      outline: none;\n      padding: 16px;\n      font-family: inherit;\n      font-size: 13px;\n      line-height: 1.6;\n      white-space: pre-wrap;\n      word-wrap: break-word;\n    }\n\n    .rendered-code {\n      margin: 0;\n      padding: 16px;\n      font-family: inherit;\n      font-size: 13px;\n      line-height: 1.6;\n      color: var(--text-primary, #0f172a);\n      white-space: pre-wrap;\n      word-wrap: break-word;\n      pointer-events: none;\n      z-index: 1;\n      overflow-y: auto;\n    }\n\n    .cursor-pipe {\n      color: var(--primary-color, #4f46e5);\n      font-weight: bold;\n      animation: blink 1s step-end infinite;\n    }\n\n    @keyframes blink {\n      from, to { opacity: 0; }\n      50% { opacity: 1; }\n    }\n\n    .ghost-text {\n      color: var(--text-muted, #94a3b8);\n      font-style: italic;\n      opacity: 0.7;\n    }\n\n    /* Footer controls */\n    .editor-footer {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      padding: 12px 16px;\n      background: var(--border-light, #f1f5f9);\n      border-top: 1px solid var(--border-color, #e2e8f0);\n      gap: 12px;\n      flex-wrap: wrap;\n    }\n\n    .editor-footer.justify-end {\n      justify-content: flex-end;\n    }\n\n    .suggestion-info {\n      display: flex;\n      align-items: center;\n      gap: 8px;\n      font-size: 12px;\n      color: var(--text-secondary, #475569);\n    }\n\n    .sparkle {\n      font-size: 14px;\n    }\n\n    .editor-kbd {\n      background: var(--bg-secondary, #ffffff);\n      border: 1px solid var(--border-color, #e2e8f0);\n      border-radius: 3px;\n      box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);\n      padding: 1px 4px;\n      font-size: 11px;\n      font-family: sans-serif;\n      font-weight: 600;\n      color: var(--text-primary, #0f172a);\n    }\n\n    .action-buttons {\n      display: flex;\n      gap: 8px;\n    }\n\n    .footer-btn {\n      padding: 6px 12px;\n      font-size: 12px;\n      font-weight: 600;\n      border-radius: 6px;\n      cursor: pointer;\n      font-family: var(--ngx-font-family, sans-serif);\n      transition: all 0.2s;\n    }\n\n    .accept-btn {\n      background: var(--primary-color, #4f46e5);\n      border: 1px solid var(--primary-color, #4f46e5);\n      color: #ffffff;\n    }\n    .accept-btn:hover {\n      background: var(--primary-hover, #4338ca);\n    }\n\n    .reject-btn {\n      background: transparent;\n      border: 1px solid var(--border-color, #e2e8f0);\n      color: var(--text-secondary, #475569);\n    }\n    .reject-btn:hover {\n      background: rgba(0, 0, 0, 0.04);\n      border-color: var(--text-secondary, #475569);\n    }\n\n    .primary-btn {\n      background: var(--primary-color, #4f46e5);\n      border: 1px solid var(--primary-color, #4f46e5);\n      color: #ffffff;\n    }\n    .primary-btn:hover {\n      background: var(--primary-hover, #4338ca);\n    }\n\n    .secondary-btn {\n      background: transparent;\n      border: 1px solid var(--border-color, #e2e8f0);\n      color: var(--text-secondary, #475569);\n    }\n    .secondary-btn:hover {\n      background: rgba(0, 0, 0, 0.04);\n    }\n\n    /* Explanation Panel */\n    .explanation-panel {\n      background: linear-gradient(to right, rgba(79, 70, 229, 0.03), rgba(124, 58, 237, 0.03));\n      border-top: 1px solid var(--border-color, #e2e8f0);\n      padding: 16px;\n    }\n\n    .explanation-header {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      margin-bottom: 8px;\n      font-weight: 700;\n      font-size: 13px;\n      color: var(--primary-color, #4f46e5);\n      font-family: var(--ngx-font-family, sans-serif);\n    }\n\n    .close-explanation-btn {\n      background: transparent;\n      border: none;\n      color: var(--text-muted, #94a3b8);\n      font-size: 14px;\n      cursor: pointer;\n    }\n    .close-explanation-btn:hover {\n      color: var(--text-primary, #0f172a);\n    }\n\n    .explanation-body {\n      font-size: 12px;\n      line-height: 1.6;\n      color: var(--text-secondary, #475569);\n      font-family: var(--ngx-font-family, sans-serif);\n    }\n\n    /* Toolbar Toggle Button */\n    .toolbar-toggle-btn {\n      background: transparent;\n      border: 1px solid var(--border-color, #cbd5e1);\n      border-radius: 6px;\n      color: var(--text-secondary, #475569);\n      cursor: pointer;\n      font-size: 11px;\n      font-weight: 600;\n      padding: 4px 8px;\n      font-family: inherit;\n      transition: all 0.2s;\n    }\n    .toolbar-toggle-btn:hover {\n      background: rgba(0, 0, 0, 0.05);\n      border-color: var(--text-primary, #0f172a);\n      color: var(--text-primary, #0f172a);\n    }\n    .toolbar-toggle-btn.active {\n      background: var(--primary-color, #4f46e5);\n      border-color: var(--primary-color, #4f46e5);\n      color: #ffffff;\n    }\n\n    /* Diff Canvas */\n    .diff-canvas {\n      display: grid;\n      grid-template-columns: 1fr 1fr;\n      min-height: 180px;\n      background: var(--bg-secondary, #ffffff);\n      border-bottom: 1px solid var(--border-color, #e2e8f0);\n    }\n    .diff-pane {\n      display: flex;\n      flex-direction: column;\n      border-right: 1px solid var(--border-color, #e2e8f0);\n    }\n    .diff-pane:last-child {\n      border-right: none;\n    }\n    .diff-pane-title {\n      padding: 6px 12px;\n      background: rgba(0, 0, 0, 0.02);\n      font-size: 10px;\n      font-weight: 700;\n      text-transform: uppercase;\n      color: var(--text-secondary, #64748b);\n      border-bottom: 1px solid var(--border-color, #e2e8f0);\n    }\n    .diff-code {\n      margin: 0;\n      padding: 12px;\n      font-family: inherit;\n      font-size: 12px;\n      line-height: 1.6;\n      white-space: pre-wrap;\n      overflow-y: auto;\n      flex: 1;\n    }\n    .original-pane .diff-code {\n      background: rgba(239, 68, 68, 0.02);\n      color: #991b1b;\n    }\n    .proposed-pane .diff-code {\n      background: rgba(16, 185, 129, 0.02);\n    }\n    .diff-highlight {\n      background: rgba(16, 185, 129, 0.15);\n      color: #065f46;\n      border-radius: 2px;\n      padding: 1px 2px;\n      font-weight: 600;\n    }\n\n    /* Suggestions Navigator */\n    .suggestions-navigator {\n      display: inline-flex;\n      align-items: center;\n      gap: 6px;\n      margin-left: 12px;\n      padding-left: 12px;\n      border-left: 1px solid var(--border-color, #cbd5e1);\n    }\n    .nav-arrow {\n      background: none;\n      border: none;\n      color: var(--primary-color, #4f46e5);\n      cursor: pointer;\n      font-size: 10px;\n      padding: 2px 4px;\n      border-radius: 4px;\n      transition: background 0.2s;\n    }\n    .nav-arrow:hover {\n      background: rgba(79, 70, 229, 0.1);\n    }\n    .nav-count {\n      font-size: 11px;\n      font-weight: 700;\n      color: var(--text-primary, #0f172a);\n    }\n\n    /* Dark Mode Diff Styling */\n    .code-editor-wrapper.dark .toolbar-toggle-btn {\n      border-color: #374151;\n      color: #94a3b8;\n    }\n    .code-editor-wrapper.dark .toolbar-toggle-btn:hover {\n      background: rgba(255, 255, 255, 0.05);\n      color: #f8fafc;\n    }\n    .code-editor-wrapper.dark .toolbar-toggle-btn.active {\n      background: var(--primary-color, #6366f1);\n      border-color: var(--primary-color, #6366f1);\n      color: #ffffff;\n    }\n    .code-editor-wrapper.dark .diff-canvas {\n      background: #0f172a;\n      border-bottom-color: #1f2937;\n    }\n    .code-editor-wrapper.dark .diff-pane {\n      border-right-color: #1f2937;\n    }\n    .code-editor-wrapper.dark .diff-pane-title {\n      background: rgba(255, 255, 255, 0.02);\n      color: #94a3b8;\n      border-bottom-color: #1f2937;\n    }\n    .code-editor-wrapper.dark .original-pane .diff-code {\n      background: rgba(239, 68, 68, 0.05);\n      color: #fca5a5;\n    }\n    .code-editor-wrapper.dark .proposed-pane .diff-code {\n      background: rgba(16, 185, 129, 0.05);\n      color: #e2e8f0;\n    }\n    .code-editor-wrapper.dark .diff-highlight {\n      background: rgba(16, 185, 129, 0.25);\n      color: #34d399;\n    }\n    .code-editor-wrapper.dark .suggestions-navigator {\n      border-left-color: #374151;\n    }\n    .code-editor-wrapper.dark .nav-count {\n      color: #cbd5e1;\n    }\n    .code-editor-wrapper.dark .nav-arrow {\n      color: #818cf8;\n    }\n    .code-editor-wrapper.dark .nav-arrow:hover {\n      background: rgba(99, 102, 241, 0.15);\n    }\n\n    /* Syntax Highlighting */\n    .hl-keyword { color: #2563eb; font-weight: 600; }\n    .hl-builtin { color: #7c3aed; }\n    .hl-number { color: #ea580c; }\n    .hl-string { color: #16a34a; }\n    .hl-comment { color: #94a3b8; font-style: italic; }\n    .hl-function { color: #d97706; }\n    .hl-tag { color: #2563eb; }\n    .hl-attr { color: #7c3aed; }\n    .hl-class { color: #d97706; }\n    .hl-id { color: #ef4444; }\n    .hl-pseudo { color: #8b5cf6; }\n    .hl-property { color: #0284c7; }\n    .hl-key { color: #2563eb; font-weight: 600; }\n\n    .code-editor-wrapper.dark .hl-keyword { color: #60a5fa; }\n    .code-editor-wrapper.dark .hl-builtin { color: #a78bfa; }\n    .code-editor-wrapper.dark .hl-number { color: #fb923c; }\n    .code-editor-wrapper.dark .hl-string { color: #4ade80; }\n    .code-editor-wrapper.dark .hl-comment { color: #64748b; }\n    .code-editor-wrapper.dark .hl-function { color: #f59e0b; }\n    .code-editor-wrapper.dark .hl-tag { color: #60a5fa; }\n    .code-editor-wrapper.dark .hl-attr { color: #a78bfa; }\n    .code-editor-wrapper.dark .hl-class { color: #f59e0b; }\n    .code-editor-wrapper.dark .hl-id { color: #f87171; }\n    .code-editor-wrapper.dark .hl-pseudo { color: #c084fc; }\n    .code-editor-wrapper.dark .hl-property { color: #38bdf8; }\n    .code-editor-wrapper.dark .hl-key { color: #60a5fa; }\n  `]\n})\nexport class AICodeEditorComponent {\n  // Inputs\n  code = input<string>('');\n  suggestion = input<string>('');\n  suggestions = input<string[]>([]);\n  language = input<string>('typescript');\n  theme = input<'light' | 'dark'>('light');\n  disabled = input<boolean>(false);\n  explanation = input<string>('');\n\n  // Outputs\n  codeChange = output<string>();\n  acceptSuggestion = output<void>();\n  declineSuggestion = output<void>();\n  regenerate = output<void>();\n\n  // State\n  isFocused = signal<boolean>(false);\n  suggestionAccepted = signal<boolean>(false);\n  showExplanation = signal<boolean>(false);\n  copyText = signal<string>('Copy');\n  copyTooltip = signal<string>('Copy code to clipboard');\n\n  activeSuggestionIndex = signal<number>(0);\n  diffMode = signal<boolean>(false);\n\n  // Computed suggestion resolution\n  currentSuggestion = computed(() => {\n    const list = this.suggestions() || [];\n    if (list.length > 0) {\n      const idx = this.activeSuggestionIndex();\n      return list[idx] || '';\n    }\n    return this.suggestion() || '';\n  });\n\n  hasSuggestion = computed(() => !!this.currentSuggestion());\n\n  // Lines computed property for line numbers\n  lines = () => {\n    const rawCode = this.code() || '';\n    return rawCode.split('\\n');\n  };\n\n  highlightedCode = computed(() => {\n    const raw = this.code() || '';\n    if (!raw) return '';\n    const escaped = this.escapeHtml(raw);\n    const lang = (this.language() || 'typescript').toLowerCase();\n\n    if (lang === 'typescript' || lang === 'javascript' || lang === 'js' || lang === 'ts') {\n      return this.highlightJS(escaped);\n    } else if (lang === 'json') {\n      return this.highlightJSON(escaped);\n    } else if (lang === 'css') {\n      return this.highlightCSS(escaped);\n    } else if (lang === 'html' || lang === 'xml') {\n      return this.highlightHTML(escaped);\n    }\n    return escaped;\n  });\n\n  private highlightJS(text: string): string {\n    const comments: string[] = [];\n    const strings: string[] = [];\n    let temp = text;\n\n    temp = temp.replace(/\\/\\*[\\s\\S]*?\\*\\//g, (match) => {\n      comments.push(match);\n      return `___COMMENT_${comments.length - 1}___`;\n    });\n\n    temp = temp.replace(/(?<!:)\\/\\/.*$/gm, (match) => {\n      comments.push(match);\n      return `___COMMENT_${comments.length - 1}___`;\n    });\n\n    temp = temp.replace(/\"(\\\\.|[^\"\\\\])*\"/g, (match) => {\n      strings.push(match);\n      return `___STRING_${strings.length - 1}___`;\n    });\n\n    temp = temp.replace(/'(\\\\.|[^'\\\\])*'/g, (match) => {\n      strings.push(match);\n      return `___STRING_${strings.length - 1}___`;\n    });\n\n    temp = temp.replace(/`(\\\\.|[^`\\\\])*`/g, (match) => {\n      strings.push(match);\n      return `___STRING_${strings.length - 1}___`;\n    });\n\n    const keywords = [\n      'const', 'let', 'var', 'function', 'class', 'return', 'import', 'export', 'from', 'as',\n      'extends', 'implements', 'if', 'else', 'for', 'while', 'do', 'switch', 'case', 'break',\n      'continue', 'default', 'new', 'this', 'typeof', 'instanceof', 'async', 'await',\n      'try', 'catch', 'finally', 'throw', 'interface', 'type', 'readonly', 'private',\n      'public', 'protected', 'constructor', 'super', 'get', 'set'\n    ];\n\n    const builtins = [\n      'String', 'Number', 'Boolean', 'Array', 'Object', 'Function', 'Promise', 'Observable',\n      'signal', 'computed', 'input', 'output', 'Component', 'Injectable', 'Directive', 'Pipe', 'NgModule',\n      'true', 'false', 'null', 'undefined'\n    ];\n\n    const keywordRegex = new RegExp(`\\\\b(${keywords.join('|')})\\\\b`, 'g');\n    temp = temp.replace(keywordRegex, '<span class=\"hl-keyword\">$1</span>');\n\n    const builtinRegex = new RegExp(`\\\\b(${builtins.join('|')})\\\\b`, 'g');\n    temp = temp.replace(builtinRegex, '<span class=\"hl-builtin\">$1</span>');\n\n    temp = temp.replace(/\\b(\\d+)\\b/g, '<span class=\"hl-number\">$1</span>');\n    temp = temp.replace(/\\b(\\w+)(?=\\()/g, '<span class=\"hl-function\">$1</span>');\n\n    strings.forEach((str, idx) => {\n      temp = temp.replace(`___STRING_${idx}___`, `<span class=\"hl-string\">${str}</span>`);\n    });\n\n    comments.forEach((comment, idx) => {\n      temp = temp.replace(`___COMMENT_${idx}___`, `<span class=\"hl-comment\">${comment}</span>`);\n    });\n\n    return temp;\n  }\n\n  private highlightCSS(text: string): string {\n    const comments: string[] = [];\n    const strings: string[] = [];\n    let temp = text;\n\n    temp = temp.replace(/\\/\\*[\\s\\S]*?\\*\\//g, (match) => {\n      comments.push(match);\n      return `___COMMENT_${comments.length - 1}___`;\n    });\n\n    temp = temp.replace(/\"(\\\\.|[^\"\\\\])*\"/g, (match) => {\n      strings.push(match);\n      return `___STRING_${strings.length - 1}___`;\n    });\n    temp = temp.replace(/'(\\\\.|[^'\\\\])*'/g, (match) => {\n      strings.push(match);\n      return `___STRING_${strings.length - 1}___`;\n    });\n\n    temp = temp.replace(/(\\.[a-zA-Z_-][\\w_-]*)/g, '<span class=\"hl-class\">$1</span>');\n    temp = temp.replace(/(#[a-zA-Z_-][\\w_-]*)/g, '<span class=\"hl-id\">$1</span>');\n    temp = temp.replace(/(:\\w+)\\b/g, '<span class=\"hl-pseudo\">$1</span>');\n    temp = temp.replace(/\\b([a-zA-Z-]+)(?=\\s*:)/g, '<span class=\"hl-property\">$1</span>');\n    temp = temp.replace(/\\b(\\d+(?:px|em|rem|%|ms|s|deg|fr|vh|vw|pt)?)\\b/g, '<span class=\"hl-number\">$1</span>');\n\n    strings.forEach((str, idx) => {\n      temp = temp.replace(`___STRING_${idx}___`, `<span class=\"hl-string\">${str}</span>`);\n    });\n    comments.forEach((comment, idx) => {\n      temp = temp.replace(`___COMMENT_${idx}___`, `<span class=\"hl-comment\">${comment}</span>`);\n    });\n\n    return temp;\n  }\n\n  private highlightHTML(text: string): string {\n    let temp = text;\n    const comments: string[] = [];\n    temp = temp.replace(/&lt;!--[\\s\\S]*?--&gt;/g, (match) => {\n      comments.push(match);\n      return `___COMMENT_${comments.length - 1}___`;\n    });\n\n    temp = temp.replace(/(&lt;\\/?[a-zA-Z0-9:-]+)/g, '<span class=\"hl-tag\">$1</span>');\n    temp = temp.replace(/(\\/?&gt;)/g, '<span class=\"hl-tag\">$1</span>');\n    temp = temp.replace(/\\b([a-zA-Z-]+)(?=\\s*=)/g, '<span class=\"hl-attr\">$1</span>');\n\n    const strings: string[] = [];\n    temp = temp.replace(/=\"([^\"]*)\"/g, (match, p1) => {\n      strings.push(`=\"${p1}\"`);\n      return `=___STRING_${strings.length - 1}___`;\n    });\n    temp = temp.replace(/='([^']*)'/g, (match, p1) => {\n      strings.push(`='${p1}'`);\n      return `=___STRING_${strings.length - 1}___`;\n    });\n\n    strings.forEach((str, idx) => {\n      temp = temp.replace(`___STRING_${idx}___`, `<span class=\"hl-string\">${str}</span>`);\n    });\n    comments.forEach((comment, idx) => {\n      temp = temp.replace(`___COMMENT_${idx}___`, `<span class=\"hl-comment\">${comment}</span>`);\n    });\n\n    return temp;\n  }\n\n  private highlightJSON(text: string): string {\n    let temp = text;\n    const strings: string[] = [];\n    temp = temp.replace(/\"(\\\\.|[^\"\\\\])*\"/g, (match) => {\n      strings.push(match);\n      return `___STRING_${strings.length - 1}___`;\n    });\n\n    temp = temp.replace(/(___STRING_\\d+___)(?=\\s*:)/g, '<span class=\"hl-key\">$1</span>');\n    temp = temp.replace(/\\b(true|false|null)\\b/g, '<span class=\"hl-builtin\">$1</span>');\n    temp = temp.replace(/\\b(\\d+)\\b/g, '<span class=\"hl-number\">$1</span>');\n\n    strings.forEach((str, idx) => {\n      if (temp.includes(`<span class=\"hl-key\">___STRING_${idx}___</span>`)) {\n        temp = temp.replace(`___STRING_${idx}___`, str);\n      } else {\n        temp = temp.replace(`___STRING_${idx}___`, `<span class=\"hl-string\">${str}</span>`);\n      }\n    });\n\n    return temp;\n  }\n\n  private escapeHtml(unsafe: string): string {\n    return unsafe\n      .replace(/&/g, '&amp;')\n      .replace(/</g, '&lt;')\n      .replace(/>/g, '&gt;')\n      .replace(/\"/g, '&quot;')\n      .replace(/'/g, '&#039;');\n  }\n\n  @ViewChild('editorInput') editorInput!: any;\n\n  focusTextarea() {\n    if (this.disabled()) return;\n    if (this.editorInput && this.editorInput.nativeElement) {\n      this.editorInput.nativeElement.focus();\n    }\n  }\n\n  onCodeChange(newVal: string) {\n    this.codeChange.emit(newVal);\n    // If the suggestion is pending and user edits, we reset the acceptance signal\n    if (this.suggestionAccepted()) {\n      this.suggestionAccepted.set(false);\n    }\n  }\n\n  handleKeydown(event: KeyboardEvent) {\n    if (this.disabled()) return;\n\n    // Tab accepts suggestion if available\n    if (event.key === 'Tab' && this.hasSuggestion() && !this.suggestionAccepted()) {\n      event.preventDefault();\n      this.accept();\n    }\n    // Tab inserts spaces if no suggestion is active\n    else if (event.key === 'Tab' && (!this.hasSuggestion() || this.suggestionAccepted())) {\n      event.preventDefault();\n      const textarea = event.target as HTMLTextAreaElement;\n      const start = textarea.selectionStart;\n      const end = textarea.selectionEnd;\n      const val = textarea.value;\n      const newVal = val.substring(0, start) + '  ' + val.substring(end);\n      this.onCodeChange(newVal);\n      // Wait for Angular to update the model, then restore cursor position\n      setTimeout(() => {\n        textarea.selectionStart = textarea.selectionEnd = start + 2;\n      });\n    }\n\n    // Esc declines suggestion if available\n    if (event.key === 'Escape' && this.hasSuggestion() && !this.suggestionAccepted()) {\n      event.preventDefault();\n      this.decline();\n    }\n  }\n\n  prevSuggestion(): void {\n    if (this.disabled()) return;\n    const len = this.suggestions().length;\n    if (len <= 1) return;\n    this.activeSuggestionIndex.update(idx => (idx - 1 + len) % len);\n  }\n\n  nextSuggestion(): void {\n    if (this.disabled()) return;\n    const len = this.suggestions().length;\n    if (len <= 1) return;\n    this.activeSuggestionIndex.update(idx => (idx + 1) % len);\n  }\n\n  toggleDiffMode(): void {\n    if (this.disabled()) return;\n    this.diffMode.update(d => !d);\n  }\n\n  accept() {\n    this.suggestionAccepted.set(true);\n    const fullCode = this.code() + this.currentSuggestion();\n    this.codeChange.emit(fullCode);\n    this.acceptSuggestion.emit();\n    this.diffMode.set(false); // Reset diff mode when suggestion is accepted\n  }\n\n  decline() {\n    this.declineSuggestion.emit();\n    this.diffMode.set(false); // Reset diff mode when suggestion is declined\n  }\n\n  triggerRegenerate() {\n    this.suggestionAccepted.set(false);\n    this.showExplanation.set(false);\n    this.regenerate.emit();\n  }\n\n  explainSuggestedCode() {\n    this.showExplanation.set(true);\n  }\n\n  copyCode() {\n    const combined = this.code() + (this.suggestionAccepted() ? '' : this.currentSuggestion());\n    navigator.clipboard.writeText(combined).then(() => {\n      this.copyText.set('Copied!');\n      setTimeout(() => this.copyText.set('Copy'), 2000);\n    });\n  }\n}\n","import { Component, input, signal, output, computed, effect, OnDestroy } from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\nexport type AIAudioState = 'idle' | 'listening' | 'thinking' | 'speaking';\n\n@Component({\n  selector: 'ngx-ai-audio-wave',\n  standalone: true,\n  imports: [CommonModule],\n  template: `\n    <div class=\"audio-wave-wrapper\" [class.dark]=\"theme() === 'dark'\">\n      <!-- Status Badge & Description -->\n      <div class=\"wave-header\">\n        <div class=\"state-indicator\" [class]=\"state()\">\n          <span class=\"state-dot\"></span>\n          <span class=\"state-text\">{{ stateLabel() }}</span>\n        </div>\n        <div class=\"amplitude-label\" *ngIf=\"state() === 'speaking' || state() === 'listening'\">\n          Sensitivity: {{ volumePercent() }}%\n        </div>\n      </div>\n\n      <!-- Equalizer Wave Container -->\n      <div class=\"equalizer-container\" [class.muted]=\"isMuted()\">\n        @for (bar of bars(); track $index) {\n          <div\n            class=\"wave-bar\"\n            [class]=\"state()\"\n            [style.animation-delay]=\"bar.delay\"\n            [style.animation-duration]=\"barDuration()\"\n            [style.height.px]=\"bar.height\"\n            [style.background]=\"barColor()\"\n          ></div>\n        }\n      </div>\n\n      <!-- Controls Panel -->\n      <div class=\"controls-panel\">\n        <!-- Mic Toggle -->\n        <button\n          class=\"control-btn mic-btn\"\n          [class.active]=\"micEnabled() && !isMuted()\"\n          (click)=\"toggleMic()\"\n          [title]=\"micEnabled() ? 'Disable Microphone' : 'Enable Microphone'\"\n        >\n          <!-- SVG Mic Icon -->\n          <svg class=\"icon-svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n            @if (micEnabled()) {\n              <path d=\"M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z\"/>\n              <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/>\n              <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"23\"/>\n              <line x1=\"8\" y1=\"23\" x2=\"16\" y2=\"23\"/>\n            } @else {\n              <path d=\"M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z\" opacity=\"0.4\"/>\n              <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" opacity=\"0.4\"/>\n              <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"23\" opacity=\"0.4\"/>\n              <line x1=\"10\" y1=\"23\" x2=\"14\" y2=\"23\" opacity=\"0.4\"/>\n              <line x1=\"1\" y1=\"1\" x2=\"23\" y2=\"23\" stroke-width=\"2.5\"/>\n            }\n          </svg>\n        </button>\n\n        <!-- Mute/Unmute audio output -->\n        <button\n          class=\"control-btn volume-btn\"\n          [class.muted]=\"isMuted()\"\n          (click)=\"toggleMute()\"\n          [title]=\"isMuted() ? 'Unmute Audio' : 'Mute Audio'\"\n        >\n          <!-- SVG Audio Icon -->\n          <svg class=\"icon-svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n            @if (!isMuted()) {\n              <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\"/>\n              <path d=\"M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07\"/>\n            } @else {\n              <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" opacity=\"0.4\"/>\n              <line x1=\"23\" y1=\"9\" x2=\"17\" y2=\"15\"/>\n              <line x1=\"17\" y1=\"9\" x2=\"23\" y2=\"15\"/>\n            }\n          </svg>\n        </button>\n\n        <!-- Wave Sensitivity/Speed slider -->\n        <div class=\"slider-container\" *ngIf=\"state() === 'speaking' || state() === 'listening'\">\n          <span class=\"slider-label\">Speed</span>\n          <input\n            type=\"range\"\n            min=\"0.3\"\n            max=\"2.0\"\n            step=\"0.1\"\n            [value]=\"speedMultiplier()\"\n            (input)=\"onSpeedChange($event)\"\n            class=\"wave-speed-slider\"\n          />\n        </div>\n      </div>\n    </div>\n  `,\n  styles: [`\n    :host {\n      display: block;\n      width: 100%;\n    }\n\n    .audio-wave-wrapper {\n      background: var(--bg-secondary, #ffffff);\n      border: 1px solid var(--border-color, #e2e8f0);\n      border-radius: var(--radius-md, 10px);\n      padding: 20px;\n      box-shadow: var(--shadow-md, 0 4px 6px -1px rgba(0, 0, 0, 0.08));\n      display: flex;\n      flex-direction: column;\n      gap: 20px;\n      transition: background 0.3s, border-color 0.3s;\n    }\n\n    /* Header info */\n    .wave-header {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      font-family: var(--ngx-font-family, sans-serif);\n    }\n\n    .state-indicator {\n      display: flex;\n      align-items: center;\n      gap: 8px;\n      font-size: 13px;\n      font-weight: 700;\n    }\n\n    .state-dot {\n      width: 8px;\n      height: 8px;\n      border-radius: 50%;\n      background: #94a3b8;\n      transition: background 0.3s;\n    }\n\n    .state-indicator.idle .state-dot { background: #94a3b8; }\n    .state-indicator.listening .state-dot { background: #10b981; animation: blink 1.2s infinite; }\n    .state-indicator.thinking .state-dot { background: #3b82f6; animation: spin-color 2s infinite; }\n    .state-indicator.speaking .state-dot { background: #8b5cf6; }\n\n    .state-indicator.idle { color: var(--text-secondary, #475569); }\n    .state-indicator.listening { color: #10b981; }\n    .state-indicator.thinking { color: #3b82f6; }\n    .state-indicator.speaking { color: #8b5cf6; }\n\n    @keyframes blink {\n      0%, 100% { opacity: 1; }\n      50% { opacity: 0.3; }\n    }\n\n    @keyframes spin-color {\n      0% { transform: scale(1); filter: brightness(1); }\n      50% { transform: scale(1.2); filter: brightness(1.2); }\n      100% { transform: scale(1); filter: brightness(1); }\n    }\n\n    .amplitude-label {\n      font-size: 11px;\n      color: var(--text-secondary, #475569);\n      font-weight: 500;\n    }\n\n    /* Equalizer wave container */\n    .equalizer-container {\n      display: flex;\n      justify-content: center;\n      align-items: center;\n      gap: 4px;\n      height: 70px;\n      padding: 0 10px;\n      border-radius: var(--radius-sm, 6px);\n      background: var(--border-light, #f1f5f9);\n      overflow: hidden;\n      transition: background 0.3s, opacity 0.3s;\n    }\n\n    .equalizer-container.muted {\n      opacity: 0.5;\n    }\n\n    /* Bar Styling & Animations */\n    .wave-bar {\n      width: 4px;\n      border-radius: 9999px;\n      transition: height 0.3s, background 0.3s;\n    }\n\n    /* IDLE state */\n    .wave-bar.idle {\n      height: 6px !important;\n      opacity: 0.4;\n    }\n\n    /* LISTENING state: pulsing heights */\n    .wave-bar.listening {\n      animation: listenPulse 1s ease-in-out infinite alternate;\n    }\n\n    @keyframes listenPulse {\n      0% { transform: scaleY(1); }\n      100% { transform: scaleY(3.5); }\n    }\n\n    /* THINKING state: flowing wave */\n    .wave-bar.thinking {\n      animation: thinkFlow 1.6s ease-in-out infinite;\n    }\n\n    @keyframes thinkFlow {\n      0%, 100% { transform: scaleY(1.2); }\n      50% { transform: scaleY(5); }\n    }\n\n    /* SPEAKING state: bouncy sound peaks */\n    .wave-bar.speaking {\n      animation: speakBounce 0.8s cubic-bezier(0.25, 0.8, 0.25, 1) infinite alternate;\n    }\n\n    @keyframes speakBounce {\n      0% { transform: scaleY(1); }\n      100% { transform: scaleY(7.5); }\n    }\n\n    /* Controls Panel */\n    .controls-panel {\n      display: flex;\n      align-items: center;\n      gap: 12px;\n      border-top: 1px solid var(--border-color, #e2e8f0);\n      padding-top: 16px;\n    }\n\n    .control-btn {\n      width: 38px;\n      height: 38px;\n      border-radius: 50%;\n      border: 1px solid var(--border-color, #e2e8f0);\n      background: transparent;\n      color: var(--text-secondary, #475569);\n      cursor: pointer;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      transition: all 0.25s;\n    }\n\n    .control-btn:hover {\n      background: var(--border-light, #f1f5f9);\n      color: var(--text-primary, #0f172a);\n      border-color: var(--text-secondary, #475569);\n    }\n\n    .control-btn.active {\n      background: var(--primary-color, #4f46e5);\n      color: #ffffff;\n      border-color: var(--primary-color, #4f46e5);\n      box-shadow: 0 0 0 3px var(--primary-glow, rgba(79, 70, 229, 0.15));\n    }\n\n    .control-btn.muted {\n      color: #ef4444;\n      border-color: rgba(239, 68, 68, 0.2);\n      background: rgba(239, 68, 68, 0.05);\n    }\n    .control-btn.muted:hover {\n      background: rgba(239, 68, 68, 0.1);\n    }\n\n    .icon-svg {\n      width: 18px;\n      height: 18px;\n    }\n\n    /* Slider styling */\n    .slider-container {\n      display: flex;\n      align-items: center;\n      gap: 8px;\n      margin-left: auto;\n      font-family: var(--ngx-font-family, sans-serif);\n      font-size: 11px;\n      color: var(--text-secondary, #475569);\n    }\n\n    .wave-speed-slider {\n      width: 80px;\n      height: 4px;\n      background: var(--border-color, #e2e8f0);\n      border-radius: 2px;\n      outline: none;\n      -webkit-appearance: none;\n      cursor: pointer;\n    }\n\n    .wave-speed-slider::-webkit-slider-thumb {\n      -webkit-appearance: none;\n      width: 12px;\n      height: 12px;\n      border-radius: 50%;\n      background: var(--primary-color, #4f46e5);\n      transition: transform 0.15s;\n    }\n    .wave-speed-slider::-webkit-slider-thumb:hover {\n      transform: scale(1.2);\n    }\n\n    /* Dark Mode */\n    .audio-wave-wrapper.dark {\n      background: #0f172a;\n      border-color: #1f2937;\n    }\n    .audio-wave-wrapper.dark .equalizer-container {\n      background: #1e293b;\n    }\n    .audio-wave-wrapper.dark .control-btn {\n      border-color: #374151;\n      color: #94a3b8;\n    }\n    .audio-wave-wrapper.dark .control-btn:hover {\n      background: #1e293b;\n      color: #f8fafc;\n      border-color: #94a3b8;\n    }\n    .audio-wave-wrapper.dark .control-btn.active {\n      background: var(--primary-color, #6366f1);\n      border-color: var(--primary-color, #6366f1);\n      color: #ffffff;\n    }\n    .audio-wave-wrapper.dark .controls-panel {\n      border-top-color: #1f2937;\n    }\n    .audio-wave-wrapper.dark .amplitude-label,\n    .audio-wave-wrapper.dark .slider-label {\n      color: #94a3b8;\n    }\n    .audio-wave-wrapper.dark .wave-speed-slider {\n      background: #374151;\n    }\n    .audio-wave-wrapper.dark .wave-speed-slider::-webkit-slider-thumb {\n      background: var(--primary-color, #6366f1);\n    }\n  `]\n})\nexport class AIAudioWaveComponent implements OnDestroy {\n  // Inputs\n  state = input<AIAudioState>('idle');\n  color = input<string>('');\n  theme = input<'light' | 'dark'>('light');\n  muted = input<boolean>(false);\n  autoCapture = input<boolean>(false);\n\n  // Outputs\n  stateChange = output<AIAudioState>();\n  mutedChange = output<boolean>();\n  micToggle = output<boolean>();\n\n  // State\n  micEnabled = signal<boolean>(true);\n  localMuted = signal<boolean>(false);\n  speedMultiplier = signal<number>(1.0);\n\n  // Pre-configured equalizer bars representation\n  bars = signal<{ height: number; delay: string }[]>([\n    { height: 16, delay: '0.1s' },\n    { height: 28, delay: '0.3s' },\n    { height: 42, delay: '0.5s' },\n    { height: 50, delay: '0.2s' },\n    { height: 36, delay: '0.4s' },\n    { height: 22, delay: '0.6s' },\n    { height: 30, delay: '0.15s' },\n    { height: 48, delay: '0.35s' },\n    { height: 52, delay: '0.55s' },\n    { height: 38, delay: '0.25s' },\n    { height: 24, delay: '0.45s' },\n    { height: 14, delay: '0.05s' }\n  ]);\n\n  private defaultHeights = [16, 28, 42, 50, 36, 22, 30, 48, 52, 38, 24, 14];\n  private audioCtx?: AudioContext;\n  private analyser?: AnalyserNode;\n  private dataArray?: Uint8Array;\n  private stream?: MediaStream;\n  private animationFrameId?: number;\n\n  constructor() {\n    effect(() => {\n      const capture = this.autoCapture();\n      const stateVal = this.state();\n      const isMutedVal = this.isMuted();\n\n      if (capture && stateVal === 'listening' && !isMutedVal) {\n        this.startMicCapture();\n      } else {\n        this.stopMicCapture();\n      }\n    });\n  }\n\n  ngOnDestroy() {\n    this.stopMicCapture();\n  }\n\n  private startMicCapture() {\n    if (typeof window === 'undefined' || !navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {\n      return;\n    }\n    \n    this.stopMicCapture();\n\n    navigator.mediaDevices.getUserMedia({ audio: true }).then(s => {\n      this.stream = s;\n      const AudioContextClass = window.AudioContext || (window as any).webkitAudioContext;\n      this.audioCtx = new AudioContextClass();\n      const source = this.audioCtx.createMediaStreamSource(s);\n      this.analyser = this.audioCtx.createAnalyser();\n      this.analyser.fftSize = 64; // Small fft size for our 12 bars\n      const bufferLength = this.analyser.frequencyBinCount;\n      this.dataArray = new Uint8Array(bufferLength);\n      source.connect(this.analyser);\n      this.updateBarsFromAudio();\n    }).catch(err => {\n      console.warn('Microphone access denied or failed:', err);\n    });\n  }\n\n  private updateBarsFromAudio() {\n    if (!this.analyser || !this.dataArray) return;\n    this.analyser.getByteFrequencyData(this.dataArray);\n    \n    const barsLength = this.bars().length;\n    const binSize = Math.floor(this.dataArray.length / barsLength) || 1;\n    \n    this.bars.update(current => {\n      return current.map((bar, i) => {\n        let sum = 0;\n        for (let j = 0; j < binSize; j++) {\n          sum += this.dataArray![i * binSize + j] || 0;\n        }\n        const avg = sum / binSize;\n        const baseHeight = 10;\n        const calculatedHeight = baseHeight + (avg / 255) * 55;\n        return { ...bar, height: calculatedHeight };\n      });\n    });\n    \n    this.animationFrameId = requestAnimationFrame(() => this.updateBarsFromAudio());\n  }\n\n  private stopMicCapture() {\n    if (this.animationFrameId) {\n      cancelAnimationFrame(this.animationFrameId);\n      this.animationFrameId = undefined;\n    }\n    if (this.stream) {\n      this.stream.getTracks().forEach(track => track.stop());\n      this.stream = undefined;\n    }\n    if (this.audioCtx && this.audioCtx.state !== 'closed') {\n      this.audioCtx.close();\n      this.audioCtx = undefined;\n    }\n    this.analyser = undefined;\n    this.dataArray = undefined;\n    this.resetBars();\n  }\n\n  private resetBars() {\n    this.bars.update(current => {\n      return current.map((bar, i) => ({\n        ...bar,\n        height: this.defaultHeights[i] || 16\n      }));\n    });\n  }\n\n  isMuted = computed(() => this.muted() || this.localMuted() || !this.micEnabled());\n\n  stateLabel = computed(() => {\n    switch (this.state()) {\n      case 'listening': return 'Listening...';\n      case 'thinking': return 'Thinking...';\n      case 'speaking': return 'Speaking...';\n      default: return 'Assistant Idle';\n    }\n  });\n\n  volumePercent = computed(() => {\n    if (this.isMuted()) return 0;\n    if (this.state() === 'idle') return 5;\n    if (this.state() === 'listening') return 45;\n    if (this.state() === 'thinking') return 12;\n    if (this.state() === 'speaking') return 78;\n    return 0;\n  });\n\n  barDuration = computed(() => {\n    const rawVal = 1.0 / this.speedMultiplier();\n    return `${rawVal.toFixed(2)}s`;\n  });\n\n  barColor = computed(() => {\n    if (this.color()) return this.color();\n\n    // Context colors matching states\n    if (this.isMuted()) return '#94a3b8';\n    switch (this.state()) {\n      case 'listening': return '#10b981'; // Green\n      case 'thinking': return '#3b82f6';  // Blue\n      case 'speaking': return '#8b5cf6';  // Purple\n      default: return '#cbd5e1';          // Muted slate\n    }\n  });\n\n  onSpeedChange(event: Event) {\n    const inputEl = event.target as HTMLInputElement;\n    if (inputEl) {\n      this.speedMultiplier.set(parseFloat(inputEl.value));\n    }\n  }\n\n  toggleMic() {\n    const nextVal = !this.micEnabled();\n    this.micEnabled.set(nextVal);\n    this.micToggle.emit(nextVal);\n  }\n\n  toggleMute() {\n    const nextVal = !this.localMuted();\n    this.localMuted.set(nextVal);\n    this.mutedChange.emit(nextVal);\n  }\n}\n","import { Component, input, signal, output, computed } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\n\nexport interface AIModel {\n  name: string;\n  provider: string;\n  parameters: string;\n  contextWindow: string;\n  pricingInput: number;  // per 1M tokens\n  pricingOutput: number; // per 1M tokens\n  avgLatency: number;    // seconds\n  capabilities: ('text' | 'code' | 'vision' | 'audio')[];\n  rating: number;\n  status: 'stable' | 'beta' | 'deprecated';\n  recommended?: boolean;\n}\n\n@Component({\n  selector: 'ngx-ai-model-compare',\n  standalone: true,\n  imports: [CommonModule, FormsModule],\n  template: `\n    <div class=\"model-compare-wrapper\" [class.dark]=\"theme() === 'dark'\">\n      <!-- Toolbar Filter Bar -->\n      <div class=\"toolbar-header\">\n        <div class=\"search-box\">\n          <span class=\"search-icon\">🔍</span>\n          <input\n            type=\"text\"\n            [ngModel]=\"searchQuery()\"\n            (ngModelChange)=\"searchQuery.set($event)\"\n            placeholder=\"Search model or provider...\"\n            class=\"filter-input\"\n          />\n        </div>\n\n        <!-- Filter Tags -->\n        <div class=\"filter-tags\">\n          @for (tag of tags; track tag.value) {\n            <button\n              class=\"tag-btn\"\n              [class.active]=\"activeTag() === tag.value\"\n              (click)=\"activeTag.set(tag.value)\"\n            >\n              {{ tag.label }}\n            </button>\n          }\n        </div>\n      </div>\n\n      <!-- Comparison Grid Container -->\n      <div class=\"table-container\">\n        <table class=\"compare-table\">\n          <thead>\n            <tr>\n              <th class=\"cell-model\">Model</th>\n              <th>Parameters</th>\n              <th>Context</th>\n              <th>Cost (In/Out per 1M)</th>\n              <th class=\"cell-latency\">Latency</th>\n              <th>Capabilities</th>\n              <th>Rating</th>\n              <th class=\"cell-action\">Action</th>\n            </tr>\n          </thead>\n          <tbody>\n            @if (filteredModels().length === 0) {\n              <tr>\n                <td colspan=\"8\" class=\"empty-state\">\n                  No models match the current filter or search criteria.\n                </td>\n              </tr>\n            } @else {\n              @for (model of filteredModels(); track model.name) {\n                <tr\n                  class=\"model-row\"\n                  [class.recommended]=\"model.recommended\"\n                  [class.selected]=\"selectedModel()?.name === model.name\"\n                  (click)=\"selectModel(model)\"\n                >\n                  <!-- Model Info -->\n                  <td class=\"cell-model\">\n                    <div class=\"model-title-wrap\">\n                      <div class=\"model-name\">\n                        {{ model.name }}\n                        <span *ngIf=\"model.recommended\" class=\"badge-recommended\">Rec</span>\n                        <span *ngIf=\"model.status === 'beta'\" class=\"badge-beta\">Beta</span>\n                      </div>\n                      <div class=\"model-provider\">{{ model.provider }}</div>\n                    </div>\n                  </td>\n\n                  <!-- Parameters -->\n                  <td>\n                    <span class=\"param-tag\">{{ model.parameters }}</span>\n                  </td>\n\n                  <!-- Context Window -->\n                  <td>{{ model.contextWindow }}</td>\n\n                  <!-- Pricing -->\n                  <td>\n                    <div class=\"pricing-wrap\">\n                      <span class=\"price-val\">\\${{ model.pricingInput }}</span>\n                      <span class=\"price-slash\">/</span>\n                      <span class=\"price-val\">\\${{ model.pricingOutput }}</span>\n                    </div>\n                  </td>\n\n                  <!-- Latency Bar -->\n                  <td class=\"cell-latency\">\n                    <div class=\"latency-graph-wrap\">\n                      <div class=\"latency-metrics\">\n                        <span>{{ model.avgLatency }}s</span>\n                      </div>\n                      <div class=\"bar-track\">\n                        <div\n                          class=\"bar-fill\"\n                          [style.width.%]=\"getLatencyPercentage(model.avgLatency)\"\n                          [class.fast]=\"model.avgLatency <= 1.0\"\n                          [class.moderate]=\"model.avgLatency > 1.0 && model.avgLatency <= 2.2\"\n                          [class.slow]=\"model.avgLatency > 2.2\"\n                        ></div>\n                      </div>\n                    </div>\n                  </td>\n\n                  <!-- Capabilities -->\n                  <td>\n                    <div class=\"capabilities-icons\">\n                      <span [class.active]=\"model.capabilities.includes('text')\" title=\"Text processing\">💬</span>\n                      <span [class.active]=\"model.capabilities.includes('code')\" title=\"Code generation\">💻</span>\n                      <span [class.active]=\"model.capabilities.includes('vision')\" title=\"Computer vision\">👁️</span>\n                      <span [class.active]=\"model.capabilities.includes('audio')\" title=\"Voice/Audio input\">🎙️</span>\n                    </div>\n                  </td>\n\n                  <!-- Rating -->\n                  <td>\n                    <div class=\"rating-stars\" [title]=\"model.rating + ' stars'\">\n                      @for (star of [1, 2, 3, 4, 5]; track star) {\n                        <span class=\"star\" [class.filled]=\"star <= model.rating\">★</span>\n                      }\n                    </div>\n                  </td>\n\n                  <!-- Select Button -->\n                  <td class=\"cell-action\" (click)=\"$event.stopPropagation()\">\n                    <button\n                      class=\"select-btn\"\n                      [class.active]=\"selectedModel()?.name === model.name\"\n                      (click)=\"selectModel(model)\"\n                    >\n                      {{ selectedModel()?.name === model.name ? 'Selected' : 'Compare' }}\n                    </button>\n                  </td>\n                </tr>\n              }\n            }\n          </tbody>\n        </table>\n      </div>\n    </div>\n  `,\n  styles: [`\n    :host {\n      display: block;\n      width: 100%;\n    }\n\n    .model-compare-wrapper {\n      background: var(--bg-secondary, #ffffff);\n      border: 1px solid var(--border-color, #e2e8f0);\n      border-radius: var(--radius-md, 10px);\n      box-shadow: var(--shadow-md, 0 4px 6px -1px rgba(0, 0, 0, 0.08));\n      overflow: hidden;\n      display: flex;\n      flex-direction: column;\n      transition: all 0.3s;\n    }\n\n    /* Toolbar headers */\n    .toolbar-header {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      padding: 16px 20px;\n      border-bottom: 1px solid var(--border-color, #e2e8f0);\n      gap: 16px;\n      flex-wrap: wrap;\n    }\n\n    .search-box {\n      display: flex;\n      align-items: center;\n      gap: 8px;\n      border: 1px solid var(--border-color, #e2e8f0);\n      border-radius: var(--radius-sm, 6px);\n      padding: 6px 12px;\n      background: var(--bg-primary, #f8fafc);\n      min-width: 250px;\n      flex: 1;\n      max-width: 400px;\n    }\n\n    .search-icon {\n      font-size: 14px;\n    }\n\n    .filter-input {\n      border: none;\n      background: transparent;\n      outline: none;\n      font-size: 13px;\n      width: 100%;\n      color: var(--text-primary, #0f172a);\n    }\n\n    .filter-tags {\n      display: flex;\n      gap: 8px;\n      overflow-x: auto;\n      padding-bottom: 2px;\n    }\n\n    .tag-btn {\n      padding: 6px 12px;\n      font-size: 12px;\n      font-weight: 600;\n      border-radius: 9999px;\n      border: 1px solid var(--border-color, #e2e8f0);\n      background: transparent;\n      color: var(--text-secondary, #475569);\n      cursor: pointer;\n      font-family: var(--ngx-font-family, sans-serif);\n      transition: all 0.2s;\n    }\n    .tag-btn:hover {\n      background: var(--border-light, #f1f5f9);\n      color: var(--text-primary, #0f172a);\n    }\n    .tag-btn.active {\n      background: var(--primary-color, #4f46e5);\n      border-color: var(--primary-color, #4f46e5);\n      color: #ffffff;\n    }\n\n    /* Table styles */\n    .table-container {\n      overflow-x: auto;\n    }\n\n    .compare-table {\n      width: 100%;\n      border-collapse: collapse;\n      text-align: left;\n      font-family: var(--ngx-font-family, sans-serif);\n      font-size: 13px;\n    }\n\n    .compare-table th {\n      padding: 14px 20px;\n      font-weight: 700;\n      color: var(--text-secondary, #475569);\n      background: var(--border-light, #f1f5f9);\n      border-bottom: 1px solid var(--border-color, #e2e8f0);\n      user-select: none;\n    }\n\n    .compare-table td {\n      padding: 16px 20px;\n      border-bottom: 1px solid var(--border-light, #f1f5f9);\n      vertical-align: middle;\n      color: var(--text-primary, #0f172a);\n      transition: background 0.15s;\n    }\n\n    .model-row {\n      cursor: pointer;\n    }\n\n    .model-row:hover td {\n      background: rgba(79, 70, 229, 0.02);\n    }\n\n    .model-row.selected td {\n      background: rgba(79, 70, 229, 0.05);\n    }\n\n    .model-row.recommended {\n      position: relative;\n    }\n\n    .model-title-wrap {\n      display: flex;\n      flex-direction: column;\n      gap: 2px;\n    }\n\n    .model-name {\n      font-weight: 700;\n      display: flex;\n      align-items: center;\n      gap: 6px;\n    }\n\n    .model-provider {\n      font-size: 11px;\n      color: var(--text-secondary, #475569);\n    }\n\n    /* Badges */\n    .badge-recommended {\n      background: #e0e7ff;\n      color: #4f46e5;\n      font-size: 10px;\n      padding: 1px 6px;\n      border-radius: 4px;\n      font-weight: 700;\n    }\n\n    .badge-beta {\n      background: #fef3c7;\n      color: #d97706;\n      font-size: 10px;\n      padding: 1px 6px;\n      border-radius: 4px;\n      font-weight: 700;\n    }\n\n    .param-tag {\n      background: var(--border-light, #f1f5f9);\n      color: var(--text-secondary, #475569);\n      padding: 2px 8px;\n      border-radius: 4px;\n      font-size: 11px;\n      font-weight: 600;\n    }\n\n    .pricing-wrap {\n      display: flex;\n      align-items: center;\n      font-weight: 600;\n    }\n\n    .price-slash {\n      color: var(--text-muted, #94a3b8);\n      margin: 0 4px;\n    }\n\n    /* Latency bar graphs */\n    .latency-graph-wrap {\n      display: flex;\n      flex-direction: column;\n      gap: 6px;\n      width: 100px;\n    }\n\n    .latency-metrics {\n      display: flex;\n      justify-content: space-between;\n      font-size: 11px;\n      font-weight: 600;\n      color: var(--text-secondary, #475569);\n    }\n\n    .bar-track {\n      height: 6px;\n      background: var(--border-color, #e2e8f0);\n      border-radius: 3px;\n      overflow: hidden;\n    }\n\n    .bar-fill {\n      height: 100%;\n      border-radius: 3px;\n    }\n\n    .bar-fill.fast { background: #10b981; }\n    .bar-fill.moderate { background: #f59e0b; }\n    .bar-fill.slow { background: #ef4444; }\n\n    /* Capabilities */\n    .capabilities-icons {\n      display: flex;\n      gap: 6px;\n      font-size: 15px;\n    }\n\n    .capabilities-icons span {\n      opacity: 0.2;\n      filter: grayscale(1);\n      transition: opacity 0.2s;\n    }\n\n    .capabilities-icons span.active {\n      opacity: 1;\n      filter: none;\n    }\n\n    /* Star ratings */\n    .rating-stars {\n      color: #f59e0b;\n      font-size: 14px;\n      letter-spacing: -2px;\n      white-space: nowrap;\n    }\n\n    .star {\n      opacity: 0.2;\n    }\n\n    .star.filled {\n      opacity: 1;\n    }\n\n    /* Action selection button */\n    .select-btn {\n      padding: 6px 12px;\n      font-size: 11px;\n      font-weight: 700;\n      border-radius: 6px;\n      border: 1px solid var(--border-color, #e2e8f0);\n      background: transparent;\n      color: var(--text-secondary, #475569);\n      cursor: pointer;\n      font-family: var(--ngx-font-family, sans-serif);\n      transition: all 0.2s;\n      width: 76px;\n    }\n\n    .select-btn:hover {\n      background: rgba(79, 70, 229, 0.05);\n      color: var(--primary-color, #4f46e5);\n      border-color: var(--primary-color, #4f46e5);\n    }\n\n    .select-btn.active {\n      background: var(--primary-color, #4f46e5);\n      border-color: var(--primary-color, #4f46e5);\n      color: #ffffff;\n    }\n\n    .empty-state {\n      text-align: center;\n      padding: 30px !important;\n      color: var(--text-secondary, #475569);\n      font-style: italic;\n    }\n\n    /* Dark Mode */\n    .model-compare-wrapper.dark {\n      background: #0f172a;\n      border-color: #1f2937;\n    }\n    .model-compare-wrapper.dark .toolbar-header {\n      border-bottom-color: #1f2937;\n    }\n    .model-compare-wrapper.dark .search-box {\n      border-color: #1f2937;\n      background: #0b0f19;\n    }\n    .model-compare-wrapper.dark .filter-input {\n      color: #f8fafc;\n    }\n    .model-compare-wrapper.dark .tag-btn {\n      border-color: #374151;\n      color: #94a3b8;\n    }\n    .model-compare-wrapper.dark .tag-btn:hover {\n      background: #1f2937;\n      color: #f8fafc;\n    }\n    .model-compare-wrapper.dark .tag-btn.active {\n      background: var(--primary-color, #6366f1);\n      border-color: var(--primary-color, #6366f1);\n      color: #ffffff;\n    }\n    .model-compare-wrapper.dark .compare-table th {\n      background: #1e293b;\n      border-bottom-color: #1f2937;\n      color: #94a3b8;\n    }\n    .model-compare-wrapper.dark .compare-table td {\n      border-bottom-color: #1f2937;\n      color: #e2e8f0;\n    }\n    .model-compare-wrapper.dark .model-row:hover td {\n      background: rgba(99, 102, 241, 0.02);\n    }\n    .model-compare-wrapper.dark .model-row.selected td {\n      background: rgba(99, 102, 241, 0.05);\n    }\n    .model-compare-wrapper.dark .badge-recommended {\n      background: rgba(99, 102, 241, 0.15);\n      color: #818cf8;\n    }\n    .model-compare-wrapper.dark .badge-beta {\n      background: rgba(245, 158, 11, 0.15);\n      color: #fbbf24;\n    }\n    .model-compare-wrapper.dark .param-tag {\n      background: #1e293b;\n      color: #94a3b8;\n    }\n    .model-compare-wrapper.dark .model-provider {\n      color: #6b7280;\n    }\n    .model-compare-wrapper.dark .bar-track {\n      background: #1f2937;\n    }\n    .model-compare-wrapper.dark .latency-metrics {\n      color: #94a3b8;\n    }\n    .model-compare-wrapper.dark .select-btn {\n      border-color: #374151;\n      color: #94a3b8;\n    }\n    .model-compare-wrapper.dark .select-btn:hover {\n      background: rgba(99, 102, 241, 0.05);\n      color: var(--primary-color, #6366f1);\n      border-color: var(--primary-color, #6366f1);\n    }\n    .model-compare-wrapper.dark .select-btn.active {\n      background: var(--primary-color, #6366f1);\n      border-color: var(--primary-color, #6366f1);\n      color: #ffffff;\n    }\n  `]\n})\nexport class AIModelCompareComponent {\n  // Inputs\n  models = input<AIModel[]>([]);\n  theme = input<'light' | 'dark'>('light');\n\n  // Outputs\n  modelSelected = output<AIModel>();\n\n  // State\n  searchQuery = signal<string>('');\n  activeTag = signal<string>('all');\n  selectedModel = signal<AIModel | null>(null);\n\n  // Available Filter Tags\n  tags = [\n    { label: 'All Models', value: 'all' },\n    { label: 'Fastest (< 1.2s)', value: 'fast' },\n    { label: 'Cheapest ($/1M)', value: 'cheap' },\n    { label: 'Vision Support', value: 'vision' },\n    { label: 'Coding Tools', value: 'code' }\n  ];\n\n  // Helper calculation for latency meter width\n  getLatencyPercentage(val: number): number {\n    // Max scale set to 5.0 seconds\n    const percentage = (val / 5.0) * 100;\n    return Math.min(Math.max(percentage, 5), 100);\n  }\n\n  // Filtered/searched list of models\n  filteredModels = computed(() => {\n    const query = this.searchQuery().toLowerCase().trim();\n    const tag = this.activeTag();\n    let list = this.models() || [];\n\n    // Apply text search filter\n    if (query) {\n      list = list.filter(\n        m =>\n          m.name.toLowerCase().includes(query) ||\n          m.provider.toLowerCase().includes(query)\n      );\n    }\n\n    // Apply category tag filter\n    if (tag === 'fast') {\n      list = list.filter(m => m.avgLatency <= 1.2);\n    } else if (tag === 'cheap') {\n      // Cheapest input price: less than $5\n      list = list.filter(m => m.pricingInput <= 5.0);\n    } else if (tag === 'vision') {\n      list = list.filter(m => m.capabilities.includes('vision'));\n    } else if (tag === 'code') {\n      list = list.filter(m => m.capabilities.includes('code'));\n    }\n\n    return list;\n  });\n\n  selectModel(model: AIModel) {\n    this.selectedModel.set(model);\n    this.modelSelected.emit(model);\n  }\n}\n","import { Component, input, signal, computed, output } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { RAGSource } from './models';\n\n@Component({\n  selector: 'ngx-ai-rag-inspector',\n  standalone: true,\n  imports: [CommonModule, FormsModule],\n  template: `\n    <div class=\"rag-inspector\" [class.dark]=\"theme() === 'dark'\" [class.splitscreen]=\"activeChunk() !== null\">\n      <!-- Header with Search & Title -->\n      <div class=\"inspector-header\">\n        <div class=\"header-main\">\n          <span class=\"sparkle-icon\">🔍</span>\n          <h4 class=\"title\">{{ title() }}</h4>\n          <span class=\"badge\" *ngIf=\"sources().length > 0\">{{ filteredSources().length }} Citations</span>\n        </div>\n        \n        <div class=\"header-controls\">\n          <div class=\"search-box\">\n            <input\n              type=\"text\"\n              [ngModel]=\"searchQuery()\"\n              (ngModelChange)=\"searchQuery.set($event)\"\n              placeholder=\"Search matching snippets...\"\n              class=\"search-input\"\n            />\n          </div>\n\n          <button \n            type=\"button\" \n            class=\"view-mode-btn\" \n            [class.active]=\"viewMode() === 'splitscreen'\"\n            (click)=\"toggleViewMode()\"\n            title=\"Toggle Side-by-Side Chunk Viewer\"\n          >\n            <svg viewBox=\"0 0 24 24\" class=\"mode-icon\"><path d=\"M4 4h7v16H4V4zm9 0h7v16h-7V4z\"/></svg>\n            <span>{{ viewMode() === 'splitscreen' ? 'Side-by-Side' : 'List View' }}</span>\n          </button>\n        </div>\n      </div>\n\n      <!-- Main Layout Body (Splitscreen or Single Column) -->\n      <div class=\"inspector-body\" [class.is-splitscreen]=\"viewMode() === 'splitscreen' && activeChunk() !== null\">\n        <!-- Left Pane: Citations List -->\n        <div class=\"sources-container\">\n          @if (filteredSources().length === 0) {\n            <div class=\"empty-state\">\n              <span class=\"empty-icon\">📂</span>\n              <p class=\"empty-text\">No document citations found for the search query.</p>\n            </div>\n          } @else {\n            <div class=\"sources-list\">\n              @for (src of filteredSources(); track src.id) {\n                <div \n                  class=\"source-card\" \n                  [class.expanded]=\"expandedId() === src.id\"\n                  [class.active-selected]=\"activeChunk()?.id === src.id\"\n                  [class.has-feedback]=\"feedbackMap[src.id] !== undefined\"\n                  (click)=\"selectChunk(src)\"\n                >\n                  <!-- Card Header -->\n                  <div class=\"card-summary\">\n                    <div class=\"source-type-icon\" [title]=\"src.sourceType\">\n                      @switch (src.sourceType) {\n                        @case ('pdf') {\n                          <svg viewBox=\"0 0 24 24\" class=\"svg-icon red\"><path d=\"M20 2H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-8.5 7.5c0 .83-.67 1.5-1.5 1.5H9v2H7.5V7H10c.83 0 1.5.67 1.5 1.5v1zm5 2c0 .83-.67 1.5-1.5 1.5h-2.5V7H15c.83 0 1.5.67 1.5 1.5v3zm4-3.5h-3v1.5h2V11h-2v1.5H19V7.5h1.5v1zM4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm11 2.5h1v3h-1v-3z\"/></svg>\n                        }\n                        @case ('docx') {\n                          <svg viewBox=\"0 0 24 24\" class=\"svg-icon blue\"><path d=\"M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z\"/></svg>\n                        }\n                        @case ('txt') {\n                          <svg viewBox=\"0 0 24 24\" class=\"svg-icon slate\"><path d=\"M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z\"/></svg>\n                        }\n                        @case ('csv') {\n                          <svg viewBox=\"0 0 24 24\" class=\"svg-icon green\"><path d=\"M5 4h14a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2zm0 4h3v3H5V8zm5 0h4v3h-4V8zm9 0v3h-4V8h4zm-9 5h4v3h-4v-3zm9 0v3h-4v-3h4zM5 13h3v3H5v-3z\"/></svg>\n                        }\n                        @case ('web') {\n                          <svg viewBox=\"0 0 24 24\" class=\"svg-icon purple\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.53c-.26-.81-1-1.4-1.9-1.4h-1v-3c0-.55-.45-1-1-1h-6v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z\"/></svg>\n                        }\n                        @default {\n                          <svg viewBox=\"0 0 24 24\" class=\"svg-icon gray\"><path d=\"M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z\"/></svg>\n                        }\n                      }\n                    </div>\n\n                    <div class=\"meta-info\">\n                      <span class=\"source-title\">{{ src.title }}</span>\n                      <div class=\"badge-row\">\n                        <span class=\"meta-badge\" *ngIf=\"src.metadata?.pageNumber\">Page {{ src.metadata?.pageNumber }}</span>\n                        <span class=\"meta-badge\" *ngIf=\"src.metadata?.chunkIndex\">Chunk #{{ src.metadata?.chunkIndex }}</span>\n                      </div>\n                    </div>\n\n                    <!-- Similarity Bar -->\n                    <div class=\"similarity-score-wrap\" (click)=\"$event.stopPropagation()\">\n                      <div class=\"score-label\">\n                        <span>Match</span>\n                        <strong>{{ (src.score * 100).toFixed(0) }}%</strong>\n                      </div>\n                      <div class=\"score-bar-track\">\n                        <div \n                          class=\"score-bar-fill\"\n                          [style.width.%]=\"src.score * 100\"\n                          [class.high]=\"src.score >= 0.8\"\n                          [class.medium]=\"src.score >= 0.5 && src.score < 0.8\"\n                          [class.low]=\"src.score < 0.5\"\n                        ></div>\n                      </div>\n                    </div>\n\n                    <!-- Expand Arrow -->\n                    <div class=\"expand-indicator\">\n                      <svg viewBox=\"0 0 24 24\" class=\"arrow-icon\"><path d=\"M7 10l5 5 5-5z\"/></svg>\n                    </div>\n                  </div>\n\n                  <!-- Expanded Content Area -->\n                  <div class=\"card-details\" (click)=\"$event.stopPropagation()\">\n                    <div class=\"snippet-content\">\n                      <pre class=\"snippet-text\" [innerHTML]=\"highlightText(src.snippet)\"></pre>\n                    </div>\n\n                    <div class=\"footer-actions\">\n                      <!-- Path metadata -->\n                      <div class=\"file-path\" *ngIf=\"src.metadata?.filePath\" [title]=\"src.metadata?.filePath\">\n                        <span>Path: </span><code>{{ src.metadata?.filePath }}</code>\n                      </div>\n\n                      <!-- Helpful feedback controls -->\n                      <div class=\"feedback-controls\">\n                        <span class=\"feedback-label\">Helpful citation?</span>\n                        <button \n                          class=\"feedback-btn thumbs-up\"\n                          [class.selected]=\"feedbackMap[src.id] === 'up'\"\n                          (click)=\"submitFeedback(src, 'up')\"\n                          title=\"Yes, helpful\"\n                        >\n                          👍\n                        </button>\n                        <button \n                          class=\"feedback-btn thumbs-down\"\n                          [class.selected]=\"feedbackMap[src.id] === 'down'\"\n                          (click)=\"submitFeedback(src, 'down')\"\n                          title=\"No, unhelpful\"\n                        >\n                          👎\n                        </button>\n                      </div>\n                    </div>\n                  </div>\n                </div>\n              }\n            </div>\n          }\n        </div>\n\n        <!-- Right Pane: Side-by-Side Source Document & Chunk Highlight Viewer -->\n        @if (viewMode() === 'splitscreen' && activeChunk() !== null) {\n          <div class=\"doc-viewer-pane\">\n            <div class=\"doc-viewer-header\">\n              <div class=\"doc-title-row\">\n                <span class=\"doc-icon\">📄</span>\n                <div class=\"doc-heading\">\n                  <h4 class=\"doc-name\">{{ activeChunk()?.title }}</h4>\n                  <span class=\"doc-sub\">Interactive Document Context Viewer</span>\n                </div>\n              </div>\n              <div class=\"doc-nav-tools\">\n                <button type=\"button\" class=\"nav-step-btn\" (click)=\"navigateChunk(-1)\" title=\"Previous Chunk\">◀ Prev</button>\n                <button type=\"button\" class=\"nav-step-btn\" (click)=\"navigateChunk(1)\" title=\"Next Chunk\">Next ▶</button>\n                <button type=\"button\" class=\"close-viewer-btn\" (click)=\"closeViewer()\" title=\"Close side panel\">✕</button>\n              </div>\n            </div>\n\n            <!-- Context Document Content Area -->\n            <div class=\"doc-viewer-body\">\n              <div class=\"doc-meta-banner\">\n                <span class=\"meta-tag\">Similarity: <strong>{{ ((activeChunk()?.score || 0) * 100).toFixed(0) }}%</strong></span>\n                <span class=\"meta-tag\" *ngIf=\"activeChunk()?.metadata?.pageNumber\">Page: {{ activeChunk()?.metadata?.pageNumber }}</span>\n                <span class=\"meta-tag\" *ngIf=\"activeChunk()?.metadata?.chunkIndex\">Chunk Index: #{{ activeChunk()?.metadata?.chunkIndex }}</span>\n              </div>\n\n              <!-- Context View with Highlighted Chunk -->\n              <div class=\"doc-context-content\">\n                <div class=\"chunk-marker\">--- BEGIN CONTEXT WINDOW ---</div>\n                <div class=\"chunk-highlight-box\">\n                  <div class=\"active-chunk-badge\">Selected RAG Citation Chunk</div>\n                  <pre class=\"chunk-highlight-text\" [innerHTML]=\"highlightText(activeChunk()?.snippet || '')\"></pre>\n                </div>\n                <div class=\"chunk-marker\">--- END CONTEXT WINDOW ---</div>\n              </div>\n            </div>\n          </div>\n        }\n      </div>\n    </div>\n  `,\n  styles: [`\n    :host {\n      display: block;\n      width: 100%;\n    }\n\n    .rag-inspector {\n      background: var(--bg-secondary, #ffffff);\n      border: 1px solid var(--border-color, #e2e8f0);\n      border-radius: var(--radius-md, 12px);\n      box-shadow: var(--shadow-md, 0 4px 6px -1px rgba(0, 0, 0, 0.08));\n      display: flex;\n      flex-direction: column;\n      overflow: hidden;\n      font-family: var(--ngx-font-family, system-ui, -apple-system, sans-serif);\n      transition: all 0.3s ease;\n    }\n\n    /* Header styling */\n    .inspector-header {\n      padding: 16px 20px;\n      border-bottom: 1px solid var(--border-color, #e2e8f0);\n      background: var(--border-light, #f8fafc);\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      gap: 16px;\n      flex-wrap: wrap;\n    }\n\n    .header-main {\n      display: flex;\n      align-items: center;\n      gap: 8px;\n    }\n\n    .sparkle-icon {\n      font-size: 16px;\n    }\n\n    .title {\n      margin: 0;\n      font-size: 15px;\n      font-weight: 750;\n      color: var(--text-primary, #0f172a);\n    }\n\n    .badge {\n      font-size: 10px;\n      font-weight: 700;\n      background: var(--primary-glow, rgba(79, 70, 229, 0.15));\n      color: var(--primary-color, #4f46e5);\n      padding: 2px 8px;\n      border-radius: 9999px;\n    }\n\n    .search-box {\n      min-width: 200px;\n      flex: 1;\n      max-width: 300px;\n    }\n\n    .search-input {\n      width: 100%;\n      border: 1px solid var(--border-color, #cbd5e1);\n      border-radius: 6px;\n      padding: 6px 12px;\n      font-size: 12px;\n      outline: none;\n      background: var(--bg-primary, #ffffff);\n      color: var(--text-primary, #0f172a);\n      transition: border-color 0.15s;\n    }\n\n    .search-input:focus {\n      border-color: var(--primary-color, #4f46e5);\n    }\n\n    /* Sources container and list */\n    .sources-container {\n      padding: 16px;\n      overflow-y: auto;\n      max-height: 450px;\n      background: var(--bg-primary, #ffffff);\n    }\n\n    .sources-list {\n      display: flex;\n      flex-direction: column;\n      gap: 12px;\n    }\n\n    /* Source card styling */\n    .source-card {\n      border: 1px solid var(--border-color, #e2e8f0);\n      border-radius: 8px;\n      background: var(--bg-secondary, #ffffff);\n      overflow: hidden;\n      cursor: pointer;\n      transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n    }\n\n    .source-card:hover {\n      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.04);\n      border-color: var(--border-color-hover, #cbd5e1);\n      transform: translateY(-1px);\n    }\n\n    .source-card.expanded {\n      border-color: var(--primary-color, #4f46e5);\n      box-shadow: 0 4px 16px var(--primary-glow, rgba(79, 70, 229, 0.1));\n    }\n\n    .source-card.has-feedback {\n      background: rgba(248, 250, 252, 0.5);\n    }\n\n    /* Summary row details */\n    .card-summary {\n      padding: 12px 16px;\n      display: flex;\n      align-items: center;\n      gap: 16px;\n      flex-wrap: wrap;\n    }\n\n    .source-type-icon {\n      width: 32px;\n      height: 32px;\n      border-radius: 8px;\n      background: var(--border-light, #f1f5f9);\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      flex-shrink: 0;\n    }\n\n    .svg-icon {\n      width: 20px;\n      height: 20px;\n    }\n\n    .svg-icon.red { fill: #ef4444; }\n    .svg-icon.blue { fill: #3b82f6; }\n    .svg-icon.green { fill: #10b981; }\n    .svg-icon.purple { fill: #8b5cf6; }\n    .svg-icon.slate { fill: #64748b; }\n    .svg-icon.gray { fill: #94a3b8; }\n\n    .meta-info {\n      flex: 1;\n      display: flex;\n      flex-direction: column;\n      gap: 4px;\n      min-width: 150px;\n    }\n\n    .source-title {\n      font-size: 13.5px;\n      font-weight: 650;\n      color: var(--text-primary, #1e293b);\n      word-break: break-all;\n    }\n\n    .badge-row {\n      display: flex;\n      gap: 6px;\n      flex-wrap: wrap;\n    }\n\n    .meta-badge {\n      font-size: 10px;\n      background: var(--border-light, #f1f5f9);\n      color: var(--text-secondary, #64748b);\n      padding: 1px 6px;\n      border-radius: 4px;\n      font-weight: 600;\n    }\n\n    /* Similarity score styling */\n    .similarity-score-wrap {\n      display: flex;\n      flex-direction: column;\n      gap: 4px;\n      width: 110px;\n      flex-shrink: 0;\n    }\n\n    .score-label {\n      display: flex;\n      justify-content: space-between;\n      font-size: 10px;\n      color: var(--text-secondary, #64748b);\n      font-weight: 600;\n    }\n\n    .score-bar-track {\n      height: 6px;\n      background: var(--border-color, #e2e8f0);\n      border-radius: 3px;\n      overflow: hidden;\n    }\n\n    .score-bar-fill {\n      height: 100%;\n      border-radius: 3px;\n    }\n\n    .score-bar-fill.high { background: #10b981; }\n    .score-bar-fill.medium { background: #f59e0b; }\n    .score-bar-fill.low { background: #ef4444; }\n\n    .expand-indicator {\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      color: var(--text-muted, #94a3b8);\n      transition: transform 0.2s ease;\n      flex-shrink: 0;\n    }\n\n    .arrow-icon {\n      width: 20px;\n      height: 20px;\n      fill: currentColor;\n    }\n\n    .source-card.expanded .expand-indicator {\n      transform: rotate(180deg);\n      color: var(--primary-color, #4f46e5);\n    }\n\n    /* Card expanded details snippet content */\n    .card-details {\n      max-height: 0;\n      overflow: hidden;\n      transition: max-height 0.25s cubic-bezier(0, 1, 0, 1);\n      border-top: 1px solid transparent;\n      background: rgba(0, 0, 0, 0.01);\n    }\n\n    .source-card.expanded .card-details {\n      max-height: 1000px;\n      border-top-color: var(--border-color, #e2e8f0);\n      transition: max-height 0.3s ease-in;\n    }\n\n    .snippet-content {\n      padding: 16px 20px;\n    }\n\n    .snippet-text {\n      margin: 0;\n      white-space: pre-wrap;\n      font-family: inherit;\n      font-size: 12.5px;\n      line-height: 1.6;\n      color: var(--text-primary, #334155);\n    }\n\n    ::ng-deep .highlight-mark {\n      background: #fef08a;\n      color: #854d0e;\n      padding: 1px 3px;\n      border-radius: 3px;\n      font-weight: 600;\n    }\n\n    .footer-actions {\n      padding: 12px 20px 16px;\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      gap: 12px;\n      flex-wrap: wrap;\n      border-top: 1px dashed var(--border-color, #e2e8f0);\n      font-size: 11px;\n    }\n\n    .file-path {\n      color: var(--text-secondary, #64748b);\n      text-overflow: ellipsis;\n      overflow: hidden;\n      white-space: nowrap;\n      max-width: 60%;\n    }\n\n    .file-path code {\n      background: var(--border-light, #f1f5f9);\n      padding: 2px 6px;\n      border-radius: 4px;\n      font-family: monospace;\n    }\n\n    .feedback-controls {\n      display: flex;\n      align-items: center;\n      gap: 8px;\n    }\n\n    .feedback-label {\n      color: var(--text-secondary, #64748b);\n      font-weight: 600;\n    }\n\n    .feedback-btn {\n      background: var(--bg-secondary, #ffffff);\n      border: 1px solid var(--border-color, #e2e8f0);\n      border-radius: 6px;\n      width: 28px;\n      height: 28px;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      cursor: pointer;\n      font-size: 11px;\n      transition: all 0.2s;\n    }\n\n    .feedback-btn:hover {\n      border-color: var(--text-secondary, #94a3b8);\n      background: var(--border-light, #f8fafc);\n    }\n\n    .feedback-btn.selected {\n      border-color: var(--primary-color, #4f46e5);\n      background: var(--primary-glow, rgba(79, 70, 229, 0.08));\n      transform: scale(1.1);\n    }\n\n    .empty-state {\n      padding: 40px 20px;\n      text-align: center;\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n      justify-content: center;\n    }\n\n    .empty-icon {\n      font-size: 32px;\n      margin-bottom: 8px;\n      opacity: 0.6;\n    }\n\n    .empty-text {\n      color: var(--text-secondary, #64748b);\n      font-style: italic;\n      font-size: 12px;\n      margin: 0;\n    }\n\n    .header-controls {\n      display: flex;\n      align-items: center;\n      gap: 12px;\n      flex: 1;\n      justify-content: flex-end;\n    }\n\n    .view-mode-btn {\n      display: flex;\n      align-items: center;\n      gap: 6px;\n      background: var(--bg-secondary, #ffffff);\n      border: 1px solid var(--border-color, #cbd5e1);\n      border-radius: 6px;\n      padding: 6px 12px;\n      font-size: 12px;\n      font-weight: 600;\n      color: var(--text-primary, #1e293b);\n      cursor: pointer;\n      transition: all 0.2s ease;\n    }\n    .view-mode-btn:hover {\n      background: var(--border-light, #f1f5f9);\n    }\n    .view-mode-btn.active {\n      background: #4f46e5;\n      color: #ffffff;\n      border-color: #4f46e5;\n    }\n    .mode-icon {\n      width: 14px;\n      height: 14px;\n      fill: currentColor;\n    }\n\n    .inspector-body {\n      display: flex;\n      flex-direction: column;\n      width: 100%;\n    }\n    .inspector-body.is-splitscreen {\n      display: grid;\n      grid-template-columns: 1fr 1.2fr;\n      divide-x: 1px solid var(--border-color, #e2e8f0);\n    }\n    @media (max-width: 840px) {\n      .inspector-body.is-splitscreen {\n        grid-template-columns: 1fr;\n      }\n    }\n\n    .source-card.active-selected {\n      border-color: #4f46e5 !important;\n      box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.2) !important;\n      background: rgba(79, 70, 229, 0.04) !important;\n    }\n\n    /* Side-by-Side Document Viewer Pane */\n    .doc-viewer-pane {\n      background: var(--bg-primary, #f8fafc);\n      display: flex;\n      flex-direction: column;\n      border-left: 1px solid var(--border-color, #e2e8f0);\n      overflow: hidden;\n    }\n\n    .doc-viewer-header {\n      padding: 14px 18px;\n      background: var(--bg-secondary, #ffffff);\n      border-bottom: 1px solid var(--border-color, #e2e8f0);\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      gap: 12px;\n    }\n    .doc-title-row {\n      display: flex;\n      align-items: center;\n      gap: 10px;\n    }\n    .doc-icon {\n      font-size: 20px;\n    }\n    .doc-name {\n      margin: 0;\n      font-size: 14px;\n      font-weight: 700;\n      color: var(--text-primary, #0f172a);\n    }\n    .doc-sub {\n      font-size: 11px;\n      color: var(--text-secondary, #64748b);\n    }\n\n    .doc-nav-tools {\n      display: flex;\n      align-items: center;\n      gap: 6px;\n    }\n    .nav-step-btn {\n      background: var(--bg-primary, #f1f5f9);\n      border: 1px solid var(--border-color, #cbd5e1);\n      border-radius: 4px;\n      padding: 4px 8px;\n      font-size: 11px;\n      font-weight: 600;\n      cursor: pointer;\n      color: var(--text-primary, #334155);\n      transition: all 0.2s;\n    }\n    .nav-step-btn:hover {\n      background: #e2e8f0;\n    }\n    .close-viewer-btn {\n      background: transparent;\n      border: none;\n      font-size: 14px;\n      cursor: pointer;\n      color: #64748b;\n      padding: 4px 8px;\n      border-radius: 4px;\n    }\n    .close-viewer-btn:hover {\n      background: rgba(0,0,0,0.08);\n      color: #0f172a;\n    }\n\n    .doc-viewer-body {\n      padding: 16px;\n      display: flex;\n      flex-direction: column;\n      gap: 12px;\n      overflow-y: auto;\n      max-height: 520px;\n    }\n    .doc-meta-banner {\n      display: flex;\n      gap: 8px;\n      flex-wrap: wrap;\n    }\n    .meta-tag {\n      background: var(--bg-secondary, #ffffff);\n      border: 1px solid var(--border-color, #e2e8f0);\n      padding: 3px 8px;\n      border-radius: 12px;\n      font-size: 11px;\n      color: #475569;\n    }\n    .doc-context-content {\n      background: var(--bg-secondary, #ffffff);\n      border: 1px solid var(--border-color, #cbd5e1);\n      border-radius: 8px;\n      padding: 16px;\n      font-family: var(--ngx-font-family, sans-serif);\n      line-height: 1.6;\n    }\n    .chunk-marker {\n      font-size: 10px;\n      font-weight: 700;\n      color: #94a3b8;\n      letter-spacing: 1px;\n      margin: 8px 0;\n      text-align: center;\n    }\n    .chunk-highlight-box {\n      background: rgba(254, 240, 138, 0.35);\n      border: 2px dashed #f59e0b;\n      border-radius: 8px;\n      padding: 12px 14px;\n      position: relative;\n      margin: 12px 0;\n    }\n    .active-chunk-badge {\n      position: absolute;\n      top: -10px;\n      left: 14px;\n      background: #f59e0b;\n      color: #ffffff;\n      font-size: 9px;\n      font-weight: 800;\n      padding: 2px 6px;\n      border-radius: 4px;\n      text-transform: uppercase;\n    }\n    .chunk-highlight-text {\n      margin: 0;\n      white-space: pre-wrap;\n      font-size: 13px;\n      color: #1e293b;\n      font-family: inherit;\n    }\n\n    /* Dark Mode styling overrides */\n    .rag-inspector.dark {\n      background: #0f172a;\n      border-color: #1f2937;\n      box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.4);\n    }\n\n    .rag-inspector.dark .doc-viewer-pane {\n      background: #0b0f19;\n      border-left-color: #1f2937;\n    }\n    .rag-inspector.dark .doc-viewer-header {\n      background: #1e293b;\n      border-bottom-color: #1f2937;\n    }\n    .rag-inspector.dark .doc-name {\n      color: #f8fafc;\n    }\n    .rag-inspector.dark .doc-context-content {\n      background: #1e293b;\n      border-color: #334155;\n    }\n    .rag-inspector.dark .chunk-highlight-box {\n      background: rgba(245, 158, 11, 0.15);\n      border-color: #d97706;\n    }\n    .rag-inspector.dark .chunk-highlight-text {\n      color: #f8fafc;\n    }\n\n    .rag-inspector.dark .inspector-header {\n      background: #1e293b;\n      border-bottom-color: #1f2937;\n    }\n\n    .rag-inspector.dark .title {\n      color: #f8fafc;\n    }\n\n    .rag-inspector.dark .search-input {\n      border-color: #374151;\n      background: #0b0f19;\n      color: #f8fafc;\n    }\n\n    .rag-inspector.dark .search-input:focus {\n      border-color: var(--primary-color, #6366f1);\n    }\n\n    .rag-inspector.dark .sources-container {\n      background: #0f172a;\n    }\n\n    .rag-inspector.dark .source-card {\n      border-color: #1f2937;\n      background: #1e293b;\n    }\n\n    .rag-inspector.dark .source-card:hover {\n      border-color: #374151;\n      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);\n    }\n\n    .rag-inspector.dark .source-card.expanded {\n      border-color: var(--primary-color, #6366f1);\n      box-shadow: 0 4px 16px rgba(99, 102, 241, 0.15);\n    }\n\n    .rag-inspector.dark .source-card.has-feedback {\n      background: rgba(15, 23, 42, 0.5);\n    }\n\n    .rag-inspector.dark .source-type-icon {\n      background: #0f172a;\n    }\n\n    .rag-inspector.dark .source-title {\n      color: #f8fafc;\n    }\n\n    .rag-inspector.dark .meta-badge {\n      background: #0f172a;\n      color: #94a3b8;\n    }\n\n    .rag-inspector.dark .score-bar-track {\n      background: #1f2937;\n    }\n\n    .rag-inspector.dark .snippet-text {\n      color: #cbd5e1;\n    }\n\n    .rag-inspector.dark ::ng-deep .highlight-mark {\n      background: #854d0e;\n      color: #fef08a;\n    }\n\n    .rag-inspector.dark .footer-actions {\n      border-top-color: #1f2937;\n    }\n\n    .rag-inspector.dark .file-path {\n      color: #94a3b8;\n    }\n\n    .rag-inspector.dark .file-path code {\n      background: #0f172a;\n      color: #cbd5e1;\n    }\n\n    .rag-inspector.dark .feedback-btn {\n      background: #1e293b;\n      border-color: #374151;\n    }\n\n    .rag-inspector.dark .feedback-btn:hover {\n      background: #1f2937;\n      border-color: #4b5563;\n    }\n\n    .rag-inspector.dark .feedback-btn.selected {\n      border-color: var(--primary-color, #6366f1);\n      background: rgba(99, 102, 241, 0.15);\n    }\n  `]\n})\nexport class AIRagInspectorComponent {\n  // Inputs\n  sources = input<RAGSource[]>([]);\n  title = input<string>('Search Citations & Sources');\n  theme = input<'light' | 'dark'>('light');\n\n  // Outputs\n  sourceClick = output<RAGSource>();\n  sourceFeedback = output<{ sourceId: string; type: 'up' | 'down' }>();\n\n  // State\n  searchQuery = signal<string>('');\n  expandedId = signal<string | null>(null);\n  viewMode = signal<'splitscreen' | 'list'>('splitscreen');\n  activeChunk = signal<RAGSource | null>(null);\n\n  // Map to store feedback local state\n  feedbackMap: Record<string, 'up' | 'down'> = {};\n\n  // Compute filtered sources based on search keyword\n  filteredSources = computed(() => {\n    const query = this.searchQuery().toLowerCase().trim();\n    const list = this.sources() || [];\n\n    if (!query) return list;\n\n    return list.filter(\n      s => \n        s.title.toLowerCase().includes(query) ||\n        s.snippet.toLowerCase().includes(query) ||\n        (s.metadata?.filePath && s.metadata.filePath.toLowerCase().includes(query))\n    );\n  });\n\n  toggleViewMode(): void {\n    this.viewMode.update(m => m === 'splitscreen' ? 'list' : 'splitscreen');\n  }\n\n  selectChunk(source: RAGSource): void {\n    this.activeChunk.set(source);\n    this.toggleExpand(source.id);\n    this.sourceClick.emit(source);\n  }\n\n  closeViewer(): void {\n    this.activeChunk.set(null);\n  }\n\n  navigateChunk(delta: number): void {\n    const list = this.filteredSources();\n    if (list.length === 0) return;\n    const current = this.activeChunk();\n    if (!current) {\n      this.activeChunk.set(list[0]);\n      return;\n    }\n    const idx = list.findIndex(s => s.id === current.id);\n    if (idx !== -1) {\n      const nextIdx = (idx + delta + list.length) % list.length;\n      const nextChunk = list[nextIdx];\n      this.activeChunk.set(nextChunk);\n      this.expandedId.set(nextChunk.id);\n      this.sourceClick.emit(nextChunk);\n    }\n  }\n\n  toggleExpand(id: string): void {\n    if (this.expandedId() === id) {\n      this.expandedId.set(null);\n    } else {\n      this.expandedId.set(id);\n      const matched = this.sources().find(s => s.id === id);\n      if (matched) {\n        this.sourceClick.emit(matched);\n      }\n    }\n  }\n\n  submitFeedback(source: RAGSource, type: 'up' | 'down'): void {\n    if (this.feedbackMap[source.id] === type) {\n      // Toggle off\n      delete this.feedbackMap[source.id];\n    } else {\n      this.feedbackMap[source.id] = type;\n    }\n    this.sourceFeedback.emit({ sourceId: source.id, type });\n  }\n\n  // Basic HTML text highlight formatter\n  highlightText(text: string): string {\n    const query = this.searchQuery().toLowerCase().trim();\n    if (!text || !query) return this.escapeHtml(text);\n\n    // Escape code\n    const escaped = this.escapeHtml(text);\n    \n    // Find matches safely and wrap with dynamic class highlight-mark\n    try {\n      // Avoid breaking search if containing regex chars\n      const safeQuery = query.replace(/[-\\\\/\\\\\\\\^$*+?.()|[\\\\]{}]/g, '\\\\$&');\n      const regex = new RegExp(`(${safeQuery})`, 'gi');\n      return escaped.replace(regex, '<mark class=\"highlight-mark\">$1</mark>');\n    } catch (e) {\n      return escaped;\n    }\n  }\n\n  private escapeHtml(unsafe: string): string {\n    return unsafe\n      .replace(/&/g, '&amp;')\n      .replace(/</g, '&lt;')\n      .replace(/>/g, '&gt;')\n      .replace(/\"/g, '&quot;')\n      .replace(/'/g, '&#039;');\n  }\n}\n","import { Injectable, signal, computed } from '@angular/core';\n\nexport interface WebLlmMessage {\n  role: 'user' | 'assistant' | 'system';\n  content: string;\n}\n\n@Injectable({\n  providedIn: 'root'\n})\nexport class NgxWebLlmService {\n  private engine: any = null;\n  \n  status = signal<string>('idle');\n  progress = signal<number>(0);\n  isReady = signal<boolean>(false);\n  error = signal<string | null>(null);\n\n  isGpuSupported(): boolean {\n    return typeof navigator !== 'undefined' && 'gpu' in navigator && !!(navigator as any).gpu;\n  }\n\n  async init(\n    modelId: string = 'Qwen2.5-0.5B-Instruct',\n    onProgress?: (val: number, msg: string) => void\n  ): Promise<void> {\n    if (this.isReady()) return;\n\n    this.status.set('loading_scripts');\n    this.error.set(null);\n\n    // If GPU is not supported, simulate model loading (useful for testing or fallback dev setups)\n    if (!this.isGpuSupported()) {\n      console.warn('WebGPU is not supported in this browser environment. Simulating fallback WebLLM Engine.');\n      await this.simulateLoading(onProgress);\n      return;\n    }\n\n    try {\n      // Dynamic import of web-llm from CDN. Using type casting to bypass TS compilation lookup checks\n      const webLlmModule = await (Function('return import(\"https://cdn.jsdelivr.net/npm/@mlc-ai/web-llm@0.2.46/+esm\")')() as Promise<any>);\n      \n      this.status.set('downloading_model');\n      this.progress.set(0);\n\n      const engine = await webLlmModule.CreateWebGPUEngine(\n        modelId,\n        {\n          initProgressCallback: (report: any) => {\n            const val = report.progress;\n            this.progress.set(Math.round(val * 100));\n            this.status.set(`loading_model: ${report.text}`);\n            if (onProgress) {\n              onProgress(val, report.text);\n            }\n          }\n        }\n      );\n\n      this.engine = engine;\n      this.isReady.set(true);\n      this.status.set('ready');\n    } catch (err: any) {\n      const errMsg = err.message || String(err);\n      this.status.set('error');\n      this.error.set(errMsg);\n      throw new Error(`WebLLM Initialization failed: ${errMsg}`);\n    }\n  }\n\n  private async simulateLoading(onProgress?: (val: number, msg: string) => void): Promise<void> {\n    const steps = [\n      { progress: 0.1, text: 'Fetching model config...' },\n      { progress: 0.3, text: 'Loading WebGPU device adapter...' },\n      { progress: 0.6, text: 'Downloading model weights (simulated)...' },\n      { progress: 0.9, text: 'Warming up runtime execution pipeline...' },\n      { progress: 1.0, text: 'Finished warming up' }\n    ];\n\n    for (const step of steps) {\n      await new Promise(resolve => setTimeout(resolve, 100));\n      this.progress.set(Math.round(step.progress * 100));\n      this.status.set(`loading_model: ${step.text}`);\n      if (onProgress) {\n        onProgress(step.progress, step.text);\n      }\n    }\n\n    this.engine = {\n      chat: {\n        completions: {\n          create: async (params: any) => {\n            // Return an async iterable stream simulator\n            const responseText = `[Simulated WebLLM response to: \"${params.messages[params.messages.length - 1]?.content}\"] This is a locally generated streaming response using simulated model weights, as WebGPU is not supported on this device.`;\n            const tokens = responseText.split(' ');\n            return (async function* () {\n              for (const token of tokens) {\n                await new Promise(resolve => setTimeout(resolve, 40));\n                yield {\n                  choices: [\n                    {\n                      delta: {\n                        content: token + ' '\n                      }\n                    }\n                  ]\n                };\n              }\n            })();\n          }\n        }\n      }\n    };\n    this.isReady.set(true);\n    this.status.set('ready');\n  }\n\n  async generate(\n    messages: WebLlmMessage[],\n    onToken?: (text: string) => void,\n    options?: { max_tokens?: number; temperature?: number }\n  ): Promise<string> {\n    if (!this.engine) {\n      throw new Error('WebLLM Engine is not initialized. Call init() first.');\n    }\n\n    this.status.set('generating');\n    try {\n      let fullText = '';\n      const reply = await this.engine.chat.completions.create({\n        messages,\n        stream: true,\n        max_tokens: options?.max_tokens ?? 1024,\n        temperature: options?.temperature ?? 0.7\n      });\n\n      for await (const chunk of reply) {\n        const delta = chunk.choices[0]?.delta?.content || '';\n        if (delta) {\n          fullText += delta;\n          if (onToken) {\n            onToken(fullText);\n          }\n        }\n      }\n      this.status.set('ready');\n      return fullText;\n    } catch (err: any) {\n      this.status.set('error');\n      this.error.set(err.message || String(err));\n      throw err;\n    }\n  }\n\n  reset(): void {\n    this.engine = null;\n    this.isReady.set(false);\n    this.status.set('idle');\n    this.progress.set(0);\n    this.error.set(null);\n  }\n}\n","import { Component, input, output, signal, inject } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { NgxWebLlmService, WebLlmMessage } from '../ngx-web-llm.service';\nimport { FormBuilderField, FormBuilderComponent } from 'ngx-core-components/inputs';\n\n@Component({\n  selector: 'ngx-ai-form-copilot',\n  standalone: true,\n  imports: [CommonModule, FormsModule],\n  template: `\n    <div class=\"ngx-ai-form-copilot-container\" [class.dark-mode]=\"theme() === 'dark'\">\n      <div class=\"copilot-header\">\n        <span class=\"copilot-logo\">🤖</span>\n        <div class=\"copilot-title-group\">\n          <h4 class=\"copilot-title\">AI Form Co-Pilot</h4>\n          <p class=\"copilot-subtitle\">Use local AI to fill the form automatically</p>\n        </div>\n      </div>\n\n      <div class=\"copilot-body\">\n        <textarea\n          [(ngModel)]=\"promptText\"\n          [disabled]=\"loading()\"\n          placeholder=\"e.g. My name is Alice, email is alice@gmail.com, and I am a Developer...\"\n          class=\"copilot-textarea\"\n          rows=\"3\"\n        ></textarea>\n\n        <div class=\"copilot-actions\">\n          <span class=\"copilot-status\" [class.error]=\"hasError()\">\n            @if (loading()) {\n              <span class=\"spinner\">⏳</span> {{ statusMessage() }}\n            } @else if (hasError()) {\n              ❌ {{ errorMessage() }}\n            } @else if (successMessage()) {\n              ✅ {{ successMessage() }}\n            }\n          </span>\n          \n          <button\n            class=\"fill-btn\"\n            [disabled]=\"loading() || !promptText().trim()\"\n            (click)=\"autoFill()\"\n          >\n            ⚡ Auto-Fill Form\n          </button>\n        </div>\n\n        @if (loading() && progress() > 0 && progress() < 100) {\n          <div class=\"progress-bar-container\">\n            <div class=\"progress-bar-fill\" [style.width.%]=\"progress()\"></div>\n          </div>\n        }\n      </div>\n    </div>\n  `,\n  styles: [`\n    :host { display: block; }\n    .ngx-ai-form-copilot-container {\n      background: var(--bg-secondary, #ffffff);\n      border: 1px solid var(--border-color, #e2e8f0);\n      border-radius: 12px;\n      padding: 16px;\n      font-family: var(--ngx-font-family, inherit);\n      color: var(--text-primary, #0f172a);\n      box-shadow: var(--ngx-shadow-md, 0 4px 6px -1px rgba(0, 0, 0, 0.1));\n      transition: all 0.2s ease;\n    }\n    .ngx-ai-form-copilot-container.dark-mode {\n      background: #1e293b;\n      border-color: #334155;\n      color: #f8fafc;\n    }\n    .copilot-header {\n      display: flex;\n      align-items: center;\n      gap: 10px;\n      margin-bottom: 12px;\n    }\n    .copilot-logo {\n      font-size: 24px;\n    }\n    .copilot-title-group {\n      display: flex;\n      flex-direction: column;\n    }\n    .copilot-title {\n      margin: 0;\n      font-size: 14px;\n      font-weight: 700;\n    }\n    .copilot-subtitle {\n      margin: 2px 0 0;\n      font-size: 11px;\n      color: var(--text-secondary, #64748b);\n    }\n    .dark-mode .copilot-subtitle {\n      color: #94a3b8;\n    }\n    .copilot-body {\n      display: flex;\n      flex-direction: column;\n      gap: 10px;\n    }\n    .copilot-textarea {\n      width: 100%;\n      background: var(--bg-primary, #f8fafc);\n      border: 1px solid var(--border-color, #cbd5e1);\n      border-radius: 8px;\n      padding: 8px 12px;\n      font-size: 13px;\n      color: inherit;\n      outline: none;\n      resize: none;\n      transition: border-color 0.15s;\n    }\n    .dark-mode .copilot-textarea {\n      background: #0f172a;\n      border-color: #475569;\n    }\n    .copilot-textarea:focus {\n      border-color: var(--primary-color, #4f46e5);\n    }\n    .copilot-actions {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      gap: 12px;\n    }\n    .copilot-status {\n      font-size: 11px;\n      color: var(--primary-color, #4f46e5);\n      flex: 1;\n      overflow: hidden;\n      text-overflow: ellipsis;\n      white-space: nowrap;\n    }\n    .copilot-status.error {\n      color: var(--ngx-color-danger, #ef4444);\n    }\n    .fill-btn {\n      background: var(--primary-color, #4f46e5);\n      color: #ffffff;\n      border: none;\n      border-radius: 6px;\n      font-size: 12px;\n      font-weight: 600;\n      padding: 6px 12px;\n      cursor: pointer;\n      transition: background 0.15s;\n    }\n    .fill-btn:hover:not(:disabled) {\n      background: var(--primary-hover, #4338ca);\n    }\n    .fill-btn:disabled {\n      background: var(--border-color, #cbd5e1);\n      color: var(--text-disabled, #94a3b8);\n      cursor: not-allowed;\n    }\n    .dark-mode .fill-btn:disabled {\n      background: #334155;\n      color: #64748b;\n    }\n    .progress-bar-container {\n      width: 100%;\n      height: 4px;\n      background: var(--border-color, #e2e8f0);\n      border-radius: 2px;\n      overflow: hidden;\n    }\n    .dark-mode .progress-bar-container {\n      background: #334155;\n    }\n    .progress-bar-fill {\n      height: 100%;\n      background: var(--primary-color, #4f46e5);\n      width: 0%;\n      transition: width 0.1s ease;\n    }\n    .spinner {\n      display: inline-block;\n      animation: spin 1s linear infinite;\n    }\n    @keyframes spin {\n      from { transform: rotate(0deg); }\n      to { transform: rotate(360deg); }\n    }\n  `]\n})\nexport class AIFormCopilotComponent {\n  fields = input<FormBuilderField[]>([]);\n  formBuilder = input<FormBuilderComponent | null>(null);\n  theme = input<'light' | 'dark'>('light');\n\n  valuesExtracted = output<Record<string, unknown>>();\n\n  promptText = signal<string>('');\n  loading = signal<boolean>(false);\n  statusMessage = signal<string>('');\n  progress = signal<number>(0);\n  \n  hasError = signal<boolean>(false);\n  errorMessage = signal<string | null>(null);\n  successMessage = signal<string | null>(null);\n\n  private llmService = inject(NgxWebLlmService);\n\n  async autoFill(): Promise<void> {\n    const text = this.promptText().trim();\n    if (!text) return;\n\n    this.loading.set(true);\n    this.hasError.set(false);\n    this.errorMessage.set(null);\n    this.successMessage.set(null);\n    this.statusMessage.set('Initializing AI model...');\n\n    try {\n      if (!this.llmService.isReady()) {\n        await this.llmService.init('Qwen2.5-0.5B-Instruct', (val, msg) => {\n          this.progress.set(Math.round(val * 100));\n          this.statusMessage.set(`Loading LLM: ${msg}`);\n        });\n      }\n\n      this.statusMessage.set('Parsing input text...');\n\n      const schemaString = this.fields().map(f => {\n        const optString = f.options ? ` Options: [${f.options.map(o => `${o.value}: ${o.label}`).join(', ')}]` : '';\n        return `- field \"${f.key}\" (Type: ${f.type || 'text'}, Label: \"${f.label}\"${optString})`;\n      }).join('\\n');\n\n      const messages: WebLlmMessage[] = [\n        {\n          role: 'system',\n          content: `You are a highly precise entity extractor. Parse the user's input paragraph and extract values for these form fields:\n${schemaString}\n\nReturn a single JSON object mapping field keys to extracted values. Return ONLY the JSON object. Do not explain. Do not wrap in markdown quotes. Format booleans for checkbox types.`\n        },\n        {\n          role: 'user',\n          content: text\n        }\n      ];\n\n      const response = await this.llmService.generate(messages, () => {\n        this.statusMessage.set('Extracting values...');\n      });\n\n      let extractedValues: Record<string, unknown> = {};\n      try {\n        const jsonMatch = response.match(/\\{[\\s\\S]*\\}/);\n        const jsonStr = jsonMatch ? jsonMatch[0] : response;\n        extractedValues = JSON.parse(jsonStr);\n      } catch (err) {\n        console.warn('Failed to parse model output directly, trying text fallbacks:', response);\n        for (const f of this.fields()) {\n          const regex = new RegExp(`\"${f.key}\"\\\\s*:\\\\s*(?:\"([^\"]*)\"|([^,\\\\s}]*))`);\n          const match = response.match(regex);\n          if (match) {\n            const val = match[1] !== undefined ? match[1] : match[2];\n            if (val !== undefined) {\n              if (f.type === 'number') extractedValues[f.key] = Number(val);\n              else if (f.type === 'checkbox') extractedValues[f.key] = val.trim() === 'true';\n              else extractedValues[f.key] = val.trim();\n            }\n          }\n        }\n      }\n\n      if (response.includes('[Simulated')) {\n        extractedValues = {};\n        const lowerText = text.toLowerCase();\n        for (const f of this.fields()) {\n          if (f.type === 'checkbox') {\n            extractedValues[f.key] = lowerText.includes(f.label.toLowerCase()) || lowerText.includes('yes');\n          } else {\n            if (f.key === 'name' || f.key === 'customer' || f.key === 'fullName') {\n              const nameMatch = text.match(/(?:name is|named)\\s+([A-Z][a-z]+(?:\\s+[A-Z][a-z]+)?)/);\n              extractedValues[f.key] = nameMatch ? nameMatch[1] : 'Alice Smith';\n            } else if (f.key === 'email') {\n              const emailMatch = text.match(/([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})/);\n              extractedValues[f.key] = emailMatch ? emailMatch[1] : 'alice@example.com';\n            } else if (f.key === 'role') {\n              extractedValues[f.key] = 'Developer';\n            } else if (f.type === 'number') {\n              const numMatch = text.match(/\\d+/);\n              extractedValues[f.key] = numMatch ? Number(numMatch[0]) : 5;\n            } else {\n              extractedValues[f.key] = `Extracted value for ${f.label}`;\n            }\n          }\n        }\n      }\n\n      const builder = this.formBuilder();\n      if (builder) {\n        Object.entries(extractedValues).forEach(([key, val]) => {\n          builder.updateValue(key, val);\n        });\n      }\n\n      this.valuesExtracted.emit(extractedValues);\n      this.successMessage.set('Form populated successfully!');\n    } catch (err: any) {\n      this.hasError.set(true);\n      this.errorMessage.set(err.message || 'Auto-fill failed');\n    } finally {\n      this.loading.set(false);\n    }\n  }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1"],"mappings":"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"}