<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>RAG Pipeline Architecture · 10xLab</title>
  <meta name="description" content="Interactive deep-dive into the multi-model RAG architecture powering enterprise engineering document analysis. Built by 10xLab." />
  <link rel="stylesheet" href="css/style.css" />
  <link rel="stylesheet" href="css/animations.css" />
  <link rel="preconnect" href="https://fonts.googleapis.com" />
  <link href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=Fraunces:ital,opsz,wght@0,9..144,300;0,9..144,600;1,9..144,300&family=DM+Sans:wght@300;400;500&family=Orbitron:wght@400;600;700&family=Share+Tech+Mono&family=Rajdhani:wght@400;600&display=swap" rel="stylesheet" />
  <script src="vendor/pdf.min.js"></script>
  <style>
    /* Embedded Core Cyberpunk Overlay Styles from index.html */
    .upload-overlay {
      position: fixed;
      top: 0;
      left: 0;
      width: 100vw;
      height: 100vh;
      background: rgba(10, 15, 24, 0.85);
      backdrop-filter: blur(12px);
      z-index: 10000;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 20px;
    }
    .upload-panel.tron-card {
      background: #0d1527;
      border: 1px solid #00e5ff;
      box-shadow: 0 0 30px rgba(0, 229, 255, 0.2);
      width: 100%;
      max-width: 600px;
      padding: 30px;
      border-radius: 8px;
      font-family: 'Rajdhani', sans-serif;
      color: #fff;
    }
    .tron-card-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 20px;
      border-bottom: 1px solid rgba(0, 229, 255, 0.2);
      padding-bottom: 10px;
    }
    .tron-card-title {
      font-family: 'Orbitron', sans-serif;
      font-weight: 700;
      color: #00e5ff;
      letter-spacing: 2px;
    }
    .close-panel-btn {
      background: none;
      border: none;
      color: rgba(255,255,255,0.6);
      cursor: pointer;
      transition: color 0.2s;
    }
    .close-panel-btn:hover { color: #00e5ff; }
    .upload-zone {
      border: 2px dashed rgba(0, 229, 255, 0.4);
      background: rgba(0, 229, 255, 0.03);
      padding: 40px 20px;
      text-align: center;
      cursor: pointer;
      border-radius: 6px;
      transition: all 0.3s;
    }
    .upload-zone:hover {
      border-color: #00e5ff;
      background: rgba(0, 229, 255, 0.08);
    }
    .upload-title {
      font-family: 'Orbitron', sans-serif;
      font-weight: 600;
      margin-top: 15px;
      letter-spacing: 1px;
    }
    .upload-link { color: #00e5ff; text-decoration: underline; }
    .upload-sub { font-size: 0.85rem; color: #8fa0dd; margin-top: 5px; }
    .file-list { list-style: none; padding: 0; margin: 20px 0; max-height: 150px; overflow-y: auto; }
    .file-item {
      display: flex;
      justify-content: space-between;
      align-items: center;
      background: rgba(255,255,255,0.04);
      padding: 10px;
      margin-bottom: 8px;
      border-left: 3px solid #00e5ff;
      font-size: 0.9rem;
    }
    .btn-primary {
      width: 100%;
      background: #00e5ff;
      color: #0a0f18;
      border: none;
      padding: 14px;
      font-family: 'Orbitron', sans-serif;
      font-weight: 700;
      cursor: pointer;
      letter-spacing: 2px;
      transition: all 0.2s;
    }
    .btn-primary:disabled {
      background: #1c2e4a;
      color: #4a628a;
      cursor: not-allowed;
    }
    .progress-panel { margin-top: 20px; }
    .progress-bar-wrap { background: rgba(255,255,255,0.05); height: 6px; border-radius: 3px; overflow: hidden; margin-bottom: 15px; }
    .progress-bar-fill { background: #00e5ff; height: 100%; width: 0%; transition: width 0.1s; }
    .log-details { margin-top: 15px; background: #060a13; border: 1px solid rgba(0,229,255,0.2); padding: 10px; }
    .log-summary { font-family: 'Share Tech Mono', monospace; color: #00e5ff; cursor: pointer; font-size: 0.85rem; }
    .progress-log { font-family: 'Share Tech Mono', monospace; font-size: 0.8rem; color: #a4b3d6; max-height: 120px; overflow-y: auto; white-space: pre-wrap; margin-top: 8px; }
    
    /* Live Automated Connectivity Bar adjustments */
    .pg-status[data-mode="live"] .pg-status-dot { background: #00ff88; box-shadow: 0 0 8px #00ff88; }
    .pg-status[data-mode="error"] .pg-status-dot { background: #ff3b3b; box-shadow: 0 0 8px #ff3b3b; }
    .pg-status[data-mode="loading"] .pg-status-dot { background: #ffb300; box-shadow: 0 0 8px #ffb300; }
    
    /* Inline Loading States inside Chat Elements */
    .answer-loading { display: flex; align-items: center; gap: 10px; color: #8fa0dd; font-family: 'DM Mono', monospace; font-size: 0.95rem; }
    .thinking-box { background: rgba(255,255,255,0.03); border-left: 2px solid rgba(255,255,255,0.2); padding: 12px; margin: 10px 0; font-size: 0.85rem; color: #a4b3d6; font-family: 'DM Mono', monospace; }
  </style>
</head>
<body>

  <nav class="nav">
    <div class="nav-inner">
      <a href="#" class="logo">10x<span>Lab</span></a>
      <div class="nav-links">
        <a href="#overview">Overview</a>
        <a href="#ragdemo">Live Demo</a>
        <a href="#pipeline">Pipeline</a>
        <a href="#models">Models</a>
        <a href="#techstack">TechStack</a>
        <a href="#playground">Playground</a>
        <a href="#contact">Contact</a>
      </div>
    </div>
  </nav>

  <section class="hero" id="overview">
    <div class="hero-grid-bg" aria-hidden="true"></div>
    <div class="hero-inner">
      <div class="hero-eyebrow">Enterprise AI Architecture</div>
      <h1 class="hero-title">
        Three models.<br/>
        One pipeline.<br/>
        <em>Runs locally or Cloud &mdash; Your Choice?</em>
      </h1>
      <p class="hero-sub">
        A production RAG architecture for deep technical document analysis —
        built on open-source models, deployed fully on-premise.
      </p>
      <div class="hero-badges">
        <span class="badge badge-amber">Mistral 7B · Router</span>
        <span class="badge badge-blue">Qwen 2.5-32B · Retrieval</span>
        <span class="badge badge-purple">DeepSeek-R1 · Inference</span>
      </div>
      <a href="#pipeline" class="cta-btn">Explore the pipeline ↓</a>
    </div>
    <div class="hero-visual" aria-hidden="true">
      <div class="model-orbit">
        <div class="orbit-ring ring-1"></div>
        <div class="orbit-ring ring-2"></div>
        <div class="orbit-ring ring-3"></div>
        <div class="orbit-center">RAG</div>
        <div class="orbit-node node-a">M7B</div>
        <div class="orbit-node node-b">Q32B</div>
        <div class="orbit-node node-c">R1</div>
      </div>
    </div>
  </section>

  <section class="ragdemo-section" id="ragdemo">
    <div class="section-inner">
      <div class="section-label">Live RAG Demo</div>
      <h2 class="section-title">Upload Documents. Ask anything.</h2>
      <p class="section-sub">Interface with your local neural search database. Drop in your operational engineering files or specifications, initiate indexing, and queries will process sequentially across the pipeline layers.</p>

      <div class="pg-status" id="dbStatus" data-mode="loading">
        <span class="pg-status-dot" id="statusDot"></span>
        <span class="pg-status-text" id="statusText">Establishing network matrix connection...</span>
      </div>

      <div class="rag-grid">

        <div class="rag-doc-panel">
          <div class="rag-dropzone" id="ragDrop">
            <div class="rag-drop-inner">
              <svg class="rag-drop-icon" viewBox="0 0 24 24" width="34" height="34" fill="none" stroke="currentColor" stroke-width="1.5">
                <path d="M12 16V4m0 0L8 8m4-4l4 4" stroke-linecap="round" stroke-linejoin="round"/>
                <path d="M4 16v2a2 2 0 002 2h12a2 2 0 002-2v-2" stroke-linecap="round" stroke-linejoin="round"/>
              </svg>
              <div class="rag-drop-title">Open Data Ingestion Module</div>
              <div class="rag-drop-sub">Click to browse or drop items into the server indexing queue</div>
            </div>
          </div>

          <div class="rag-docinfo" id="ragDocInfo" hidden>
            <div class="rag-docinfo-row">
              <span class="rag-doc-name" id="ragDocName">0 files staged</span>
              <button class="rag-doc-clear" id="clearBtn" type="button" title="Purge local storage database">Purge DB</button>
            </div>
            <div class="rag-doc-stats" id="ragDocStats" style="display: block; font-family: 'DM Mono', monospace; font-size:0.8rem; color:#8fa0dd; margin-top:8px;"></div>
          </div>
        </div>

        <div class="rag-chat-panel">
          <div class="rag-chat-log" id="ragLog">
            <div class="rag-empty" id="ragEmpty">
              <p class="rag-empty-title">System initialized. Awaiting vector instructions.</p>
              <p class="rag-empty-sub">Load documents via the ingestion layer, then feed text inputs below. The system will track reasoning pathways before showing complete answers.</p>
            </div>
          </div>
          <div class="rag-ask-wrap">
            <input type="text" id="questionInput" class="rag-ask-input" placeholder="ENTER QUERY SEQUENCE..." disabled autocomplete="off" />
            <button class="rag-ask-btn" id="queryBtn" type="button" disabled>
              <span class="rag-ask-label">Ask</span>
            </button>
          </div>
        </div>
      </div>
    </div>
  </section>

  <div class="upload-overlay" id="uploadPanel" style="display:none">
    <div class="upload-panel tron-card">
      <div class="tron-card-header">
        <span class="tron-card-title">DATA INGESTION MODULE</span>
        <button class="close-panel-btn" id="closeUploadBtn">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <line x1="18" y1="6" x2="6" y2="18"/>
            <line x1="6" y1="6" x2="18" y2="18"/>
          </svg>
        </button>
      </div>

      <div class="upload-zone" id="uploadZone">
        <div class="upload-icon">
          <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
            <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
            <polyline points="14 2 14 8 20 8"/>
            <line x1="12" y1="18" x2="12" y2="12"/>
            <line x1="9" y1="15" x2="15" y2="15"/>
          </svg>
        </div>
        <p class="upload-title">DROP FILES OR <span class="upload-link">BROWSE</span></p>
        <p class="upload-sub">PDF · DOCX · TXT · Images — 50 MB max</p>
      </div>

      <input type="file" id="fileInput" multiple accept=".pdf,.docx,.doc,.txt,.png,.jpg,.jpeg,.bmp,.tiff,.gif,.webp" hidden />

      <ul class="file-list" id="fileList"></ul>

      <button class="btn-primary" id="ingestBtn" disabled>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="vertical-align: middle; margin-right: 4px;">
          <polyline points="16 16 12 12 8 16"/>
          <line x1="12" y1="12" x2="12" y2="21"/>
          <path d="M20.39 18.39A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.3"/>
        </svg>
        INITIATE INDEXING
      </button>

      <div class="progress-panel" id="ingestProgress" style="display:none">
        <div class="progress-bar-wrap">
          <div class="progress-bar-fill" id="progressBarFill"></div>
        </div>
        <details class="log-details" id="logDetails" open>
          <summary class="log-summary">TRANSMISSION LOG</summary>
          <div class="progress-log" id="ingestLog"></div>
        </details>
      </div>
    </div>
  </div>

  <section class="stats-bar">
    <div class="stats-inner">
      <div class="stat"><span class="stat-num">3</span><span class="stat-label">Models in pipeline</span></div>
      <div class="stat-divider"></div>
      <div class="stat"><span class="stat-num">6</span><span class="stat-label">Pipeline stages</span></div>
      <div class="stat-divider"></div>
      <div class="stat"><span class="stat-num">128K</span><span class="stat-label">Max context tokens</span></div>
      <div class="stat-divider"></div>
      <div class="stat"><span class="stat-num">100%</span><span class="stat-label">On-premise · No cloud</span></div>
    </div>
  </section>

  <section class="pipeline-section" id="pipeline">
    <div class="section-inner">
      <div class="section-label">Interactive architecture</div>
      <h2 class="section-title">The six-stage pipeline</h2>
      <p class="section-sub">Each stage is handled by the model best suited for that task. Click any stage to see what happens inside.</p>

      <div class="pipeline-tabs">
        <button class="tab-btn active" data-stage="0"><span class="tab-num">0</span><span class="tab-label">Routing</span></button>
        <div class="tab-connector"></div>
        <button class="tab-btn" data-stage="1"><span class="tab-num">1</span><span class="tab-label">Ingestion</span></button>
        <div class="tab-connector"></div>
        <button class="tab-btn" data-stage="2"><span class="tab-num">2</span><span class="tab-label">Retrieval</span></button>
        <div class="tab-connector"></div>
        <button class="tab-btn" data-stage="3"><span class="tab-num">3</span><span class="tab-label">Reranking</span></button>
        <div class="tab-connector"></div>
        <button class="tab-btn" data-stage="4"><span class="tab-num">4</span><span class="tab-label">Inference</span></button>
        <div class="tab-connector"></div>
        <button class="tab-btn" data-stage="5"><span class="tab-num">5</span><span class="tab-label">Audit</span></button>
      </div>

      <div class="stage-panels">
        <div class="stage-panel active" data-stage="0">
          <div class="stage-header">
            <div class="stage-icon icon-amber">⇌</div>
            <div>
              <h3 class="stage-name">Layer 0 — Query Router</h3>
              <p class="stage-model">Model: <strong>Mistral 7B</strong> · Always-on · ~5GB VRAM · &lt;50ms latency</p>
            </div>
          </div>
          <div class="flow-diagram">
            <div class="flow-node">Incoming query</div>
            <div class="flow-arrow">→</div>
            <div class="flow-node flow-highlight-amber">Mistral 7B classifies intent</div>
            <div class="flow-arrow">→</div>
            <div class="flow-node">Route decision → Redis Streams</div>
          </div>
        </div>
        </div>
    </div>
  </section>

  <section class="contact-section" id="contact">
    <div class="section-inner contact-inner">
      <div class="contact-text">
        <div class="section-label">10xLab</div>
        <h2 class="section-title">Build this for your enterprise</h2>
        <p class="section-sub">We design and implement on-premise RAG pipelines tailored to your engineering domain. Full data sovereignty. No cloud dependency.</p>
        <a href="mailto:james@10xlab.org" class="cta-btn cta-btn-light">james@10xlab.org →</a>
      </div>
    </div>
  </section>

  <footer class="footer">
    <div class="footer-inner">
      <span class="logo">10x<span>Lab</span></span>
      <span class="footer-copy">&copy; 2026 10xLab. All rights reserved.</span>
    </div>
  </footer>

  <script>
    // Configuration Setup alignment from index.html
    const BASE_URL = window.location.origin; 
    let stagedFiles = [];
    let isConnected = false;

    // Element selection
    const ragDrop = document.getElementById('ragDrop');
    const uploadPanel = document.getElementById('uploadPanel');
    const closeUploadBtn = document.getElementById('closeUploadBtn');
    const uploadZone = document.getElementById('uploadZone');
    const fileInput = document.getElementById('fileInput');
    const fileList = document.getElementById('fileList');
    const ingestBtn = document.getElementById('ingestBtn');
    const ingestProgress = document.getElementById('ingestProgress');
    const progressBarFill = document.getElementById('progressBarFill');
    const ingestLog = document.getElementById('ingestLog');
    
    const ragStatus = document.getElementById('dbStatus');
    const statusDot = document.getElementById('statusDot');
    const statusText = document.getElementById('statusText');
    
    const ragLog = document.getElementById('ragLog');
    const ragEmpty = document.getElementById('ragEmpty');
    const questionInput = document.getElementById('questionInput');
    const queryBtn = document.getElementById('queryBtn');
    const ragDocInfo = document.getElementById('ragDocInfo');
    const ragDocName = document.getElementById('ragDocName');
    const ragDocStats = document.getElementById('ragDocStats');
    const clearBtn = document.getElementById('clearBtn');

    // 1. Connectivity Check Sequence from index.html
    async function checkConnectivity() {
      try {
        ragStatus.setAttribute('data-mode', 'loading');
        statusText.textContent = "Connecting to pipeline matrix vectors...";
        
        const res = await fetch(`${BASE_URL}/api/status`, { method: 'GET' }).catch(() => null) 
                    || await fetch(`${BASE_URL}/api/health`, { method: 'GET' }).catch(() => null);
        
        if (res && res.ok) {
          const data = await res.json().catch(() => ({}));
          isConnected = true;
          ragStatus.setAttribute('data-mode', 'live');
          statusText.textContent = `Live Mode — Connected to Neural Backend (${data.provider || 'Ollama Local'})`;
          
          // Sync existing vector inventory metadata if available
          if (data.total_documents !== undefined) {
            updateIndexedView(data.total_documents, data.total_chunks || 0);
          }
        } else {
          throw new Error();
        }
      } catch (err) {
        isConnected = false;
        ragStatus.setAttribute('data-mode', 'error');
        statusText.textContent = "Matrix offline — Run local container backend endpoint (port 8787/8000)";
      }
    }

    function updateIndexedView(docCount, chunkCount) {
      if (docCount > 0) {
        ragDocInfo.hidden = false;
        ragDocName.textContent = `${docCount} Document${docCount > 1 ? 's' : ''} Indexed`;
        ragDocStats.textContent = `Vector Memory Space: ${chunkCount} Semantic Neural Chunks Generated.`;
        questionInput.disabled = false;
        questionInput.placeholder = "Ask a question about the document database...";
      } else {
        ragDocInfo.hidden = true;
        questionInput.disabled = true;
        questionInput.placeholder = "INITIALIZATION REQUIRED — Index documents to start query loop.";
      }
    }

    // 2. Open / Close Data Ingestion Overlay logic
    ragDrop.addEventListener('click', () => {
      uploadPanel.style.display = 'flex';
      resetUploadOverlay();
    });
    closeUploadBtn.addEventListener('click', () => {
      uploadPanel.style.display = 'none';
    });

    uploadZone.addEventListener('click', () => fileInput.click());
    fileInput.addEventListener('change', handleFileSelection);

    // Drag-and-drop actions
    ['dragenter', 'dragover'].forEach(name => {
      uploadZone.addEventListener(name, (e) => { e.preventDefault(); uploadZone.style.background = "rgba(0, 229, 255, 0.15)"; }, false);
    });
    ['dragleave', 'drop'].forEach(name => {
      uploadZone.addEventListener(name, (e) => { e.preventDefault(); uploadZone.style.background = "rgba(0, 229, 255, 0.03)"; }, false);
    });
    uploadZone.addEventListener('drop', (e) => {
      if (e.dataTransfer.files.length > 0) {
        fileInput.files = e.dataTransfer.files;
        handleFileSelection();
      }
    });

    function resetUploadOverlay() {
      stagedFiles = [];
      fileList.innerHTML = '';
      ingestBtn.disabled = true;
      ingestProgress.style.display = 'none';
      progressBarFill.style.width = '0%';
      ingestLog.textContent = '';
    }

    function handleFileSelection() {
      stagedFiles = Array.from(fileInput.files);
      fileList.innerHTML = '';
      if (stagedFiles.length === 0) {
        ingestBtn.disabled = true;
        return;
      }
      stagedFiles.forEach((f, idx) => {
        const li = document.createElement('li');
        li.className = 'file-item';
        li.innerHTML = `<span>${f.name}</span><span style="color:#00e5ff;">(${(f.size/1024/1024).toFixed(2)} MB)</span>`;
        fileList.appendChild(li);
      });
      ingestBtn.disabled = false;
    }

    // 3. Document Ingestion Loop
    ingestBtn.addEventListener('click', async () => {
      if (stagedFiles.length === 0) return;
      ingestBtn.disabled = true;
      ingestProgress.style.display = 'block';
      progressBarFill.style.width = '10%';
      ingestLog.textContent = ">>> Initializing vector pipe payload...\n";

      const formData = new FormData();
      stagedFiles.forEach(f => formData.append('files', f));

      try {
        ingestLog.textContent += `>>> Uploading ${stagedFiles.length} file(s) to pipeline cluster...\n`;
        progressBarFill.style.width = '35%';

        const response = await fetch(`${BASE_URL}/api/rag/ingest`, {
          method: 'POST',
          body: formData
        });

        if (!response.ok) throw new Error(`Transmission failure. Code: ${response.status}`);
        
        progressBarFill.style.width = '75%';
        ingestLog.textContent += ">>> Server received documents. Generating semantic partitions and matrix tokens...\n";

        const result = await response.json();
        progressBarFill.style.width = '100%';
        ingestLog.textContent += `>>> SUCCESS: Vector allocation active.\n>>> Total documents indexed: ${result.total_documents || stagedFiles.length}\n>>> Matrix chunks: ${result.total_chunks || 'Calculated'}\n`;
        
        // Refresh local dashboard view states
        updateIndexedView(result.total_documents || stagedFiles.length, result.total_chunks || 0);

        setTimeout(() => {
          uploadPanel.style.display = 'none';
        }, 1500);

      } catch (err) {
        progressBarFill.style.width = '100%';
        progressBarFill.style.background = '#ff3b3b';
        ingestLog.textContent += `!! NETWORK INTERRUPT: ${err.message}\n!! Process terminated. Check server configurations.\n`;
        ingestBtn.disabled = false;
      }
    });

    // 4. Purge Database functionality
    clearBtn.addEventListener('click', async () => {
      if (!confirm("Are you sure you want to completely purge the on-premise vector index database?")) return;
      try {
        const res = await fetch(`${BASE_URL}/api/rag/clear`, { method: 'POST' });
        if (res.ok) {
          updateIndexedView(0, 0);
          ragLog.innerHTML = `
            <div class="rag-empty" id="ragEmpty">
              <p class="rag-empty-title">Database successfully purged.</p>
              <p class="rag-empty-sub">All vectorized knowledge files have been securely dropped from standard runtime environments.</p>
            </div>`;
        }
      } catch (err) {
        alert("Failed to communicate clear command instruction to node.");
      }
    });

    // Input monitoring configuration
    questionInput.addEventListener('input', () => {
      queryBtn.disabled = !questionInput.value.trim();
    });

    questionInput.addEventListener('keydown', (e) => {
      if (e.key === 'Enter' && !e.shiftKey && !queryBtn.disabled) {
        e.preventDefault();
        sendQuerySequence();
      }
    });

    queryBtn.addEventListener('click', sendQuerySequence);

    // 5. Chat Query Loop via Server-Sent Events (SSE) or Fetch Streams from index.html
    async function sendQuerySequence() {
      const queryText = questionInput.value.trim();
      if (!queryText) return;

      // Reset empty notification templates
      if (ragEmpty) ragEmpty.remove();

      // Append user instruction prompt bubble immediately matching index2 style layout
      const userBubble = document.createElement('div');
      userBubble.style.cssText = "align-self: flex-end; background: #1c2e4a; color: #fff; padding: 12px 16px; border-radius: 8px; margin-bottom: 16px; max-width: 80%; font-family: 'DM Sans', sans-serif;";
      userBubble.textContent = queryText;
      ragLog.appendChild(userBubble);

      // Setup response placeholder container with an embedded reasoning tracking structure
      const systemMsgBox = document.createElement('div');
      systemMsgBox.style.cssText = "align-self: flex-start; background: rgba(255,255,255,0.02); border: 1px solid rgba(255,255,255,0.08); padding: 16px; border-radius: 8px; margin-bottom: 16px; width: 100%; font-family: 'DM Sans', sans-serif; color: #e2e8f0;";
      
      systemMsgBox.innerHTML = `
        <div class="answer-loading">
          <span class="pg-run-spinner" style="display:inline-block; width:14px; height:14px; border:2px solid #00e5ff; border-top-color:transparent; border-radius:50%; animation:spin 1s linear infinite;"></span>
          <span>Accessing cluster routing layers...</span>
        </div>
        <div class="thinking-box" style="display:none;"></div>
        <div class="final-text-content" style="margin-top:10px;"></div>
      `;
      ragLog.appendChild(systemMsgBox);
      ragLog.scrollTop = ragLog.scrollHeight;

      // Clean interactive elements fields
      questionInput.value = '';
      queryBtn.disabled = true;

      const thinkingBlock = systemMsgBox.querySelector('.thinking-box');
      const textBlock = systemMsgBox.querySelector('.final-text-content');
      const loaderHeader = systemMsgBox.querySelector('.answer-loading');

      try {
        const response = await fetch(`${BASE_URL}/api/rag/query`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ question: queryText })
        });

        if (!response.ok) throw new Error("An internal pipe error occurred reading this stream.");

        // Read stream lines or handle dynamic JSON tracking fallback structures
        const reader = response.body.getReader();
        const decoder = new TextDecoder();
        let buffer = '';
        let isThinkingActive = false;

        loaderHeader.remove(); // Remove temporary connection trace loop

        while (true) {
          const { value, done } = await reader.read();
          if (done) break;

          buffer += decoder.decode(value, { stream: true });
          const parts = buffer.split('\n');
          buffer = parts.pop(); // Hold remaining slice fragment

          for (const chunkLine of parts) {
            if (!chunkLine.trim()) continue;
            
            // Clean standard server stream tags if format matches SSE 'data: ' lines
            let cleanData = chunkLine.replace(/^data:\s*/, '').trim();
            if (cleanData === '[DONE]') break;

            try {
              const parsed = JSON.parse(cleanData);
              
              if (parsed.type === 'status') {
                // Render lightweight progress states dynamically
                textBlock.innerHTML = `<em style="color:#00e5ff; font-size:0.85rem;">[Pipeline Monitor: ${parsed.message}]</em>`;
              }
              else if (parsed.type === 'think') {
                if (!isThinkingActive) {
                  thinkingBlock.style.display = 'block';
                  isThinkingActive = true;
                }
                thinkingBlock.textContent += parsed.content;
              } 
              else if (parsed.type === 'text') {
                // Clear any lingering transitional status logs 
                if (textBlock.querySelector('em')) textBlock.innerHTML = '';
                textBlock.textContent += parsed.content;
              }
              else if (parsed.type === 'full_response') {
                // Fallback for complete package outputs
                if (parsed.thinking) {
                  thinkingBlock.style.display = 'block';
                  thinkingBlock.textContent = parsed.thinking;
                }
                textBlock.textContent = parsed.answer || parsed.content || '';
              }
            } catch {
              // Direct string text buffer handling if server returns non-JSON tokens
              textBlock.textContent += chunkLine + '\n';
            }
          }
          ragLog.scrollTop = ragLog.scrollHeight;
        }

      } catch (err) {
        if(loaderHeader) loaderHeader.remove();
        textBlock.innerHTML = `<span style="color:#ff3b3b; font-family:'DM Mono', monospace;">Matrix query trace fault: ${err.message}</span>`;
      }
    }

    // Run connection layer initialization sequences automatically on load
    window.addEventListener('DOMContentLoaded', () => {
      checkConnectivity();
      // Periodically poll backend status health points every 15 seconds
      setInterval(checkConnectivity, 15000);
    });
  </script>
</body>
</html>