please maek it so the media upload in next to the enter button so it reads text and gives good ai captions make it so theres pais for that links js deliver to and make better text chat upload and add 30 more features to thsi scritpt and make it so thers more thngs to everything and also add a code geenrater so u can make code give a api for that make the chat api better get lots of awnsers get websties for databases of chat for exmaple like datasets to make the ai super smart and acutlly repsond to things i say no chat gpt open ai im tryign to make the locallest ai ever the best make evrythng amazing and make it so it awnsers ltos of problems geeneraters images and make th eproxy way better to add ltos fo thigns to that and make it working cuz it doe snot work

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Ultimate AI Assistant - Extended 100+ Features</title>

  <!-- Core CSS/JS Libraries -->

  <!-- 1. Bootstrap 5 -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" />
  <script defer src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>

  <!-- 2. Animate.css -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/animate.css@4.1.1/animate.min.css" />

  <!-- 3. SweetAlert2 -->
  <script defer src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>

  <!-- 4. Chart.js -->
  <script defer src="https://cdn.jsdelivr.net/npm/chart.js@4.3.0/dist/chart.umd.min.js"></script>

  <!-- 5. Emoji Button -->
  <script defer src="https://cdn.jsdelivr.net/npm/@joeattardi/emoji-button@4.6.2/dist/index.min.js"></script>

  <!-- 6. Markdown-it -->
  <script defer src="https://cdn.jsdelivr.net/npm/markdown-it@13.0.1/dist/markdown-it.min.js"></script>

  <!-- 7. Highlight.js -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@11.8.0/styles/default.min.css" />
  <script defer src="https://cdn.jsdelivr.net/npm/highlight.js@11.8.0/lib/core.min.js"></script>

  <!-- 8. jQuery -->
  <script defer src="https://cdn.jsdelivr.net/npm/jquery@3.7.0/dist/jquery.min.js"></script>

  <!-- 9. Typed.js -->
  <script defer src="https://cdn.jsdelivr.net/npm/typed.js@2.0.12/lib/typed.min.js"></script>

  <!-- 10. Clipboard.js -->
  <script defer src="https://cdn.jsdelivr.net/npm/clipboard@2.0.11/dist/clipboard.min.js"></script>

  <!-- 11. Tippy.js -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tippy.js@6.3.7/dist/tippy.css" />
  <script defer src="https://cdn.jsdelivr.net/npm/popper.js@2.11.6/dist/umd/popper.min.js"></script>
  <script defer src="https://cdn.jsdelivr.net/npm/tippy.js@6.3.7/dist/tippy-bundle.umd.min.js"></script>

  <!-- 12. Fuse.js -->
  <script defer src="https://cdn.jsdelivr.net/npm/fuse.js@6.6.2"></script>

  <!-- 13. Leaflet.js -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.css" />
  <script defer src="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.js"></script>

  <!-- 14. QRCode.js -->
  <script defer src="https://cdn.jsdelivr.net/npm/qrcode@1.5.1/build/qrcode.min.js"></script>

  <!-- 15. SortableJS -->
  <script defer src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.js"></script>

  <!-- 16. jsPDF -->
  <script defer src="https://cdn.jsdelivr.net/npm/jspdf@2.5.1/dist/jspdf.umd.min.js"></script>

  <!-- 17. JSZip -->
  <script defer src="https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js"></script>

  <!-- 18. PapaParse -->
  <script defer src="https://cdn.jsdelivr.net/npm/papaparse@5.4.1/papaparse.min.js"></script>

  <!-- 19. Handlebars.js -->
  <script defer src="https://cdn.jsdelivr.net/npm/handlebars@4.7.7/dist/handlebars.min.js"></script>

  <!-- 20. Axios -->
  <script defer src="https://cdn.jsdelivr.net/npm/axios@1.3.5/dist/axios.min.js"></script>

  <!-- 21. Web Speech API Polyfill -->
  <script defer src="https://cdn.jsdelivr.net/npm/web-speech-cognitive-services@0.2.7/dist/web-speech-cognitive-services.min.js"></script>

  <!-- 22. DOMPurify -->
  <script defer src="https://cdn.jsdelivr.net/npm/dompurify@2.4.3/dist/purify.min.js"></script>

  <!-- 23. Mousetrap.js -->
  <script defer src="https://cdn.jsdelivr.net/npm/mousetrap@1.6.5/mousetrap.min.js"></script>

  <!-- 24. Day.js -->
  <script defer src="https://cdn.jsdelivr.net/npm/dayjs@1.11.9/dayjs.min.js"></script>

  <!-- 25. Luxon (date/time) -->
  <script defer src="https://cdn.jsdelivr.net/npm/luxon@3.3.0/build/global/luxon.min.js"></script>

  <!-- 26. Chartjs-plugin-datalabels -->
  <script defer src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0/dist/chartjs-plugin-datalabels.min.js"></script>

  <!-- 27. Perfect Scrollbar -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/perfect-scrollbar@1.5.5/css/perfect-scrollbar.css" />
  <script defer src="https://cdn.jsdelivr.net/npm/perfect-scrollbar@1.5.5/dist/perfect-scrollbar.min.js"></script>

  <!-- 28. Lodash -->
  <script defer src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>

  <!-- 29. Granim.js -->
  <script defer src="https://cdn.jsdelivr.net/npm/granim@2.0.0/dist/granim.min.js"></script>

  <!-- 30. Typed-Audio -->
  <script defer src="https://cdn.jsdelivr.net/npm/typed-audio@0.3.4/typed-audio.min.js"></script>

  <!-- Additional AI/ML Libraries -->
  <!-- TensorFlow.js -->
  <script defer src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@4.8.0/dist/tf.min.js"></script>
  <!-- ml5.js -->
  <script defer src="https://cdn.jsdelivr.net/npm/ml5@0.12.2/dist/ml5.min.js"></script>
  <!-- Three.js (3D rendering, useful for AI demos) -->
  <script defer src="https://cdn.jsdelivr.net/npm/three@0.154.0/build/three.min.js"></script>

  <style>
    /* Reset and base styles */
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body,
    html {
      height: 100%;
      background: #121212;
      color: #eee;
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      user-select: none;
    }

    a {
      color: #67f;
      text-decoration: underline;
    }

    a:hover {
      color: #449;
    }

    #app {
      display: flex;
      height: 100vh;
      max-width: 100vw;
      overflow: hidden;
      user-select: text;
    }

    /* SIDEBAR */
    #sidebar {
      width: 380px;
      background: #1e1f29;
      border-right: 1px solid #384155;
      display: flex;
      flex-direction: column;
      user-select: none;
    }

    #sidebar header {
      font-size: 1.6rem;
      text-align: center;
      padding: 15px 10px;
      border-bottom: 2px solid #4a90e2;
      color: #52aaff;
      user-select: none;
      font-weight: 700;
      background: linear-gradient(90deg, #4158d0, #c850c0);
      background-clip: text;
      -webkit-background-clip: text;
      color: transparent;
      text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.4);
    }

    #tabs {
      display: flex;
      flex-wrap: wrap;
      justify-content: space-around;
      border-bottom: 1px solid #384155;
      background: #293044;
      user-select: none;
      gap: 0.2rem;
      padding: 4px 6px;
      max-height: 48vh;
      overflow-y: auto;
    }

    .tabbtn {
      flex: 1 1 48%;
      padding: 10px 8px;
      border: none;
      cursor: pointer;
      font-weight: 700;
      color: #aaa;
      background: #293044;
      outline-offset: 0;
      transition: background-color 0.25s, color 0.25s;
      user-select: none;
      border-radius: 8px;
      font-size: 0.85rem;
      text-align: center;
    }

    .tabbtn:hover,
    .tabbtn:focus-visible {
      background: #4169e1;
      color: #fff;
      outline: none;
    }

    .tabbtn.active {
      background: #4a73ff;
      color: white;
      pointer-events: none;
      box-shadow: 0 0 8px #4a73ffaa;
    }

    .tabcontent {
      flex: 1 1 auto;
      overflow-y: auto;
      padding: 15px 18px;
      font-size: 14px;
      background: #1b1f2e;
      user-select: text;
      display: flex;
      flex-direction: column;
    }

    /* CHAT AREA */
    #chat-area {
      flex-grow: 1;
      display: flex;
      flex-direction: column;
      background: #141727;
      position: relative;
      user-select: text;
    }

    #msgs {
      flex-grow: 1;
      overflow-y: auto;
      padding: 20px 28px;
      font-size: 16px;
      line-height: 1.45em;
      scroll-behavior: smooth;
      background: linear-gradient(135deg, #161926 0%, #222b42 100%);
      font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
    }

    .msg {
      max-width: 70%;
      margin-bottom: 14px;
      padding: 12px 20px;
      border-radius: 16px;
      white-space: pre-wrap;
      word-wrap: break-word;
      border: 1px solid transparent;
      font-weight: 500;
      user-select: text;
    }

    .msg.user {
      background: #0f9b43dd;
      color: #d6efd6;
      margin-left: auto;
      border-bottom-right-radius: 0;
      border-color: #1acc65;
    }

    .msg.ai {
      background: #2f6eccbb;
      color: #dde9ff;
      border-bottom-left-radius: 0;
      border-color: #1f4697;
      font-style: normal;
    }

    /* Animations */
    .msg.ai.animate__animated {
      animation-name: fadeInUp;
      animation-duration: 0.7s;
      animation-fill-mode: both;
      animation-timing-function: cubic-bezier(.4, 0, .2, 1);
    }

    /* INPUT FORM */
    #input-form {
      border-top: 1px solid #293044;
      display: flex;
      background: #1e253b;
      padding: 12px 20px;
      align-items: center;
      gap: 0.6rem;
    }

    #user-input {
      flex-grow: 1;
      font-size: 17px;
      padding: 12px 16px;
      border-radius: 30px;
      background: #293046;
      border: none;
      color: #dde9ff;
      outline: none;
      resize: none;
      min-height: 36px;
      max-height: 80px;
    }

    #user-input:disabled {
      background: #1f273b;
      color: #607abfaa;
      cursor: not-allowed;
    }

    #send-btn {
      border: none;
      background: #4169e1;
      color: white;
      font-weight: 700;
      font-size: 17px;
      padding: 0 22px;
      border-radius: 30px;
      cursor: pointer;
      transition: background-color 0.3s;
      user-select: none;
      height: 40px;
    }

    #send-btn:hover:not(:disabled) {
      background: #548dff;
    }

    #send-btn:disabled {
      background: #667dbf66;
      cursor: default;
    }

    /* TYPING INDICATOR */
    #typing-indicator {
      margin: 6px 22px;
      font-style: italic;
      color: #7a90bf;
      display: flex;
      align-items: center;
      height: 24px;
      user-select: none;
    }

    .typing-dot {
      width: 8px;
      height: 8px;
      margin: 0 3px;
      background: #7a90bf;
      border-radius: 50%;
      display: inline-block;
      animation: bounce 1.4s infinite ease-in-out both;
    }

    .typing-dot:nth-child(1) {
      animation-delay: -0.32s;
    }

    .typing-dot:nth-child(2) {
      animation-delay: -0.16s;
    }

    .typing-dot:nth-child(3) {
      animation-delay: 0s;
    }

    @keyframes bounce {
      0%,
      80%,
      100% {
        transform: scale(0);
      }
      40% {
        transform: scale(1);
      }
    }

    /* PROXY SEARCH */
    #proxy-search-input {
      width: 70%;
      padding: 8px 14px;
      border-radius: 6px;
      border: none;
      outline: none;
      font-size: 14px;
      margin-bottom: 8px;
      flex-grow: 1;
    }

    #proxy-search-btn {
      padding: 8px 16px;
      font-weight: 700;
      font-size: 14px;
      border-radius: 6px;
      border: none;
      background-color: #4a73ff;
      color: white;
      cursor: pointer;
      transition: background-color 0.3s;
      margin-left: 6px;
      white-space: nowrap;
    }

    #proxy-search-btn:hover:not(:disabled) {
      background-color: #2669ff;
    }

    #proxy-search-results {
      max-height: 220px;
      overflow-y: auto;
      font-size: 14px;
      color: #ddefff;
      margin-top: 8px;
      user-select: text;
      line-height: 1.4em;
    }

    #proxy-search-results p {
      margin-bottom: 8px;
      cursor: pointer;
    }

    #proxy-iframe-wrapper {
      position: relative;
      flex-grow: 1;
      background: #000;
      border-top: 1px solid #4169e1;
      border-radius: 4px;
      overflow: hidden;
      box-shadow: inset 0 0 14px rgba(255, 255, 255, 0.1);
      margin-top: 8px;
      min-height: 50vh;
    }

    #proxy-iframe-wrapper iframe {
      width: 100%;
      height: 100%;
      border: none;
      background: #fff;
      display: block;
      border-radius: 4px;
    }

    #proxy-loading {
      position: absolute;
      top: 40%;
      left: 50%;
      transform: translate(-50%, -50%);
      color: #4a73ff;
      font-weight: 700;
      font-size: 20px;
      user-select: none;
      display: none;
      pointer-events: none;
    }

    /* QUIZ AREA */
    #quiz-area {
      white-space: pre-wrap;
      font-size: 14px;
      margin-top: 10px;
      background: #24324a;
      border-radius: 8px;
      padding: 12px;
      color: #e0e7ff;
      max-height: 220px;
      overflow-y: auto;
      user-select: text;
      font-family: monospace;
    }

    /* SETTINGS PANELS */
    .form-check-label,
    label {
      cursor: pointer;
      user-select: none;
    }

    .form-range {
      width: 100%;
    }

    /* Media Upload & Preview Tab Styles */
    #media-tab {
      flex-grow: 1;
      display: flex;
      flex-direction: column;
      gap: 8px;
    }

    #image-upload-label {
      background-color: #4169e1;
      padding: 10px;
      color: white;
      font-weight: 600;
      border-radius: 8px;
      text-align: center;
      cursor: pointer;
      user-select: none;
    }

    #image-upload-label:hover {
      background-color: #548dff;
    }

    #image-upload-input {
      display: none;
    }

    #image-preview-container {
      border: 1px solid #4169e1;
      border-radius: 8px;
      padding: 12px;
      background-color: #222b44;
      overflow-y: auto;
      max-height: 200px;
      user-select: text;
    }

    #image-preview-container img {
      max-width: 100%;
      border-radius: 8px;
      margin-bottom: 8px;
      box-shadow: 0 0 10px #4169e1aa;
    }

    /* HTML Editor Tab Styles */
    #html-editor-tab {
      flex-grow: 1;
      display: flex;
      flex-direction: column;
      gap: 6px;
    }

    #html-editor-textarea {
      width: 100%;
      height: 200px;
      border-radius: 8px;
      font-family: monospace;
      background-color: #222b44;
      color: #ddeeff;
      border: 1px solid #4a73ff;
      padding: 10px;
      resize: vertical;
    }

    #html-preview {
      flex-grow: 1;
      border-radius: 8px;
      background-color: #12141b;
      border: 1px solid #4a73ff;
      overflow-y: auto;
      padding: 12px;
      color: #ddeeff;
      min-height: 150px;
      user-select: text;
    }

    #html-toggle-preview {
      background-color: #4a73ff;
      color: white;
      border: none;
      padding: 6px 14px;
      border-radius: 6px;
      align-self: flex-start;
      cursor: pointer;
    }

    #html-toggle-preview:hover {
      background-color: #669dff;
    }

    /* Text editor tab (like note with markdown) */
    #note-editor {
      flex-grow: 1;
      width: 100%;
      resize: vertical;
      border-radius: 8px;
      line-height: 1.5em;
      padding: 14px 16px;
      font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
      font-size: 14px;
      background-color: #222b44;
      color: #ddeeff;
      border: 1px solid #4a73ff;
      min-height: 140px;
    }

    /* Dark Mode Overrides */
    body.light-mode {
      background: #f5f7fa;
      color: #222;
    }

    body.light-mode #sidebar {
      background: #e4ecff;
      color: #222;
      border-right-color: #c1c9d6;
    }

    body.light-mode #chat-area {
      background: #eef2ff;
      color: #222;
    }

    body.light-mode #msgs {
      background: linear-gradient(135deg, #fff 0%, #dbeafe 100%);
      color: #222;
    }

    body.light-mode .msg.user {
      background: #aff3afcc;
      color: #064e00;
    }

    body.light-mode .msg.ai {
      background: #8cc8ffcc;
      color: #02266f;
    }

    body.light-mode #input-form {
      background: #d6dbfb;
    }

    body.light-mode #user-input {
      background: #f5f7fa;
      color: #222;
    }

    body.light-mode #proxy-search-input {
      background: #fff;
      color: #222;
      border: 1px solid #ccc;
    }

    body.light-mode #proxy-search-results {
      color: #222;
    }

    body.light-mode a {
      color: #3366cc;
    }

    /* Scrollbars */
    ::-webkit-scrollbar {
      width: 8px;
      height: 8px;
    }

    ::-webkit-scrollbar-track {
      background: transparent;
    }

    ::-webkit-scrollbar-thumb {
      background: #4a73ff88;
      border-radius: 20px;
    }

    /* Responsive for smaller viewports */
    @media (max-width: 720px) {
      #app {
        flex-direction: column;
      }

      #sidebar {
        width: 100%;
        height: 50vh;
      }

      #chat-area {
        height: 50vh;
      }

      #tabs {
        flex-wrap: nowrap;
        overflow-x: auto;
      }

      .tabbtn {
        flex: 1 0 auto;
        font-size: 13px;
        padding: 8px 6px;
      }
    }
  </style>
</head>
<body>
  <div id="app" role="main" aria-label="Ultimate AI Assistant Extended">

    <!-- Sidebar: Control Panel with Extended Tabs -->
    <section id="sidebar" role="complementary" aria-label="Control panel">
      <header>Ultimate AI Assistant</header>
      <nav id="tabs" role="tablist" aria-label="Settings tabs">
        <button class="tabbtn active" role="tab" aria-selected="true" aria-controls="tab-ai" id="tab-btn-ai">AI Chat</button>
        <button class="tabbtn" role="tab" aria-selected="false" aria-controls="tab-data" id="tab-btn-data">Data APIs</button>
        <button class="tabbtn" role="tab" aria-selected="false" aria-controls="tab-quiz" id="tab-btn-quiz">Quiz Tools</button>
        <button class="tabbtn" role="tab" aria-selected="false" aria-controls="tab-search" id="tab-btn-search">Search Proxy</button>
        <button class="tabbtn" role="tab" aria-selected="false" aria-controls="tab-voice" id="tab-btn-voice">Voice Chat</button>
        <button class="tabbtn" role="tab" aria-selected="false" aria-controls="tab-export" id="tab-btn-export">Export Chat</button>
        <button class="tabbtn" role="tab" aria-selected="false" aria-controls="tab-media" id="tab-btn-media">Media Upload</button>
        <button class="tabbtn" role="tab" aria-selected="false" aria-controls="tab-html" id="tab-btn-html">HTML Editor</button>
        <button class="tabbtn" role="tab" aria-selected="false" aria-controls="tab-text" id="tab-btn-text">Text Notes</button>
      </nav>

      <!-- Tab contents -->
      <div id="tab-ai" class="tabcontent" role="tabpanel" aria-labelledby="tab-btn-ai">
        <h5>Personality</h5>
        <select id="personality-select" class="form-select form-select-sm" aria-label="Select personality tone">
          <option value="friendly" selected>Friendly & Simple</option>
          <option value="formal">Formal & Precise</option>
          <option value="funny">Funny & Casual</option>
          <option value="robotic">Robotic & Technical</option>
          <option value="friendly-funny">Friendly-Funny Mix</option>
        </select>
        <div class="form-check my-2">
          <input class="form-check-input" type="checkbox" id="use-context" checked />
          <label class="form-check-label" for="use-context">Enable Context Awareness</label>
        </div>
        <div class="form-check my-2">
          <input class="form-check-input" type="checkbox" id="use-external" checked />
          <label class="form-check-label" for="use-external">Use Online Knowledge APIs</label>
        </div>
        <div class="form-check my-2">
          <input class="form-check-input" type="checkbox" id="spellcheck" checked />
          <label class="form-check-label" for="spellcheck">Enable Spell Correction</label>
        </div>
        <div class="form-check my-2">
          <input class="form-check-input" type="checkbox" id="typing-indicator-checkbox" checked />
          <label class="form-check-label" for="typing-indicator-checkbox">Show Typing Indicator</label>
        </div>
        <h5 class="mt-4">Performance</h5>
        <label for="typing-speed" class="form-label">Typing Speed (ms per char): <span id="typing-speed-val">30</span></label>
        <input type="range" id="typing-speed" class="form-range" min="10" max="80" value="30" />
        <label for="context-length" class="form-label mt-3">Max Memory Steps: <span id="context-length-val">5</span></label>
        <input type="range" id="context-length" class="form-range" min="1" max="20" value="5" />
        <h5 class="mt-4">User Experience</h5>
        <div class="form-check mb-3">
          <input class="form-check-input" type="checkbox" id="dark-mode" checked />
          <label class="form-check-label" for="dark-mode">Enable Dark Mode</label>
        </div>
        <label for="font-size" class="form-label">Font Size: <span id="font-size-val">16</span> px</label>
        <input type="range" id="font-size" class="form-range" min="12" max="24" value="16" />
        <button class="btn btn-danger w-100 mt-4" id="clear-chat">Clear Chat History</button>
      </div>

      <div id="tab-data" class="tabcontent" role="tabpanel" aria-labelledby="tab-btn-data" hidden>
        <h5>Free & Demo APIs Integrated:</h5>
        <ul class="list-group list-group-flush" style="font-size: 14px;">
          <li class="list-group-item bg-transparent">• DuckDuckGo Instant Answer API (Knowledge & Search)</li>
          <li class="list-group-item bg-transparent">• Wikipedia REST API (Article summaries)</li>
          <li class="list-group-item bg-transparent">• Numbers API (Trivia & facts about numbers)</li>
          <li class="list-group-item bg-transparent">• Open Trivia DB (Quiz questions)</li>
          <li class="list-group-item bg-transparent">• Free Dictionary API (Word definitions)</li>
          <li class="list-group-item bg-transparent">• NewsAPI demo (Tech news headlines)</li>
          <li class="list-group-item bg-transparent">• Weather APIs (Open-Meteo) for current weather</li>
          <li class="list-group-item bg-transparent">• Currency conversion (exchangerate.host)</li>
          <li class="list-group-item bg-transparent">• Unsplash + Flickr image search</li>
          <li class="list-group-item bg-transparent">• YouTube API preview (via embeds)</li>
          <li class="list-group-item bg-transparent">• Google Translate API demo (for translation)</li>
          <li class="list-group-item bg-transparent">• Merriam-Webster Thesaurus & Dictionary (demo)</li>
          <li class="list-group-item bg-transparent">• Oxford Dictionaries API (demo)</li>
          <li class="list-group-item bg-transparent">• Wikipedia GeoSearch (Places)</li>
          <li class="list-group-item bg-transparent">• TimezoneDB API (Timezone info)</li>
          <li class="list-group-item bg-transparent">• IP Geolocation API (Your IP info)</li>
          <li class="list-group-item bg-transparent">• QR Code generator</li>
          <li class="list-group-item bg-transparent">• OpenAI GPT Q&A (if key added)</li>
          <li class="list-group-item bg-transparent">• Free Text-to-Speech & Speech to Text</li>
          <li class="list-group-item bg-transparent">• Handlebars.js templates for dynamic UI</li>
          <!-- ...Additional APIs can be added here -->
        </ul>
        <p class="mt-3" style="font-style: italic;">Easily add more by editing code - all modular & modern!</p>
      </div>

      <div id="tab-quiz" class="tabcontent" role="tabpanel" aria-labelledby="tab-btn-quiz" hidden>
        <h5>Quiz & Learning Tools</h5>
        <button type="button" id="start-quiz-btn" class="btn btn-primary btn-sm mb-3">Start Random Quiz</button>
        <div id="quiz-area"></div>
        <small class="text-muted mt-2 d-block">Correct answers increase your score!</small>
      </div>

      <div id="tab-search" class="tabcontent" role="tabpanel" aria-labelledby="tab-btn-search" hidden>
        <h5>Search Proxy Browser</h5>
        <div class="d-flex flex-wrap mb-2">
          <input 
            id="proxy-search-input" 
            type="search" 
            class="form-control me-2" 
            placeholder="Search DuckDuckGo or enter URL..." 
            aria-label="Proxy search or direct URL input" 
            style="flex-grow:1; min-width:200px" 
            spellcheck="false" 
          />
          <button id="proxy-search-btn" class="btn btn-primary mb-2" title="Search or Load URL">Search / Load</button>
        </div>
        <div id="proxy-search-results" aria-live="polite" aria-atomic="false"></div>
        <div id="proxy-iframe-wrapper" aria-live="off">
          <iframe 
            id="proxy-iframe" 
            srcdoc="<p style='font-family:sans-serif;color:#666;text-align:center;padding:2rem;'>Search results or embedded website will show here.</p>" 
            title="Proxy Browser Frame" 
            sandbox="allow-same-origin allow-scripts allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox" 
            loading="lazy" 
            frameborder="0" 
            tabindex="0"
          ></iframe>
          <div id="proxy-loading" aria-hidden="true">Loading...</div>
        </div>
      </div>

      <div id="tab-voice" class="tabcontent" role="tabpanel" aria-labelledby="tab-btn-voice" hidden>
        <h5>Voice Chat</h5>
        <p>Use mic button to speak to AI, and AI will talk back.</p>
        <button id="voice-start-btn" class="btn btn-success mb-3" aria-label="Start voice chat">🎤 Start Voice Chat</button>
        <button id="voice-stop-btn" class="btn btn-danger mb-3" disabled aria-label="Stop voice chat">⏹ Stop Voice Chat</button>
        <div id="voice-text" style="background:#182135; padding:12px; border-radius:6px; min-height:36px; color:#8ab4f8; font-family: monospace;" aria-live="polite" aria-atomic="true"></div>
      </div>

      <div id="tab-export" class="tabcontent" role="tabpanel" aria-labelledby="tab-btn-export" hidden>
        <h5>Export & Import Chat History</h5>
        <button id="export-json-btn" class="btn btn-outline-primary mb-2" aria-label="Export chat history JSON">Export as JSON</button>
        <button id="export-txt-btn" class="btn btn-outline-secondary mb-2" aria-label="Export chat history text">Export as Text</button>
        <hr />
        <label for="import-json-input" class="form-label">Import chat from JSON file</label>
        <input type="file" id="import-json-input" accept="application/json" class="form-control mb-2" aria-label="Import chat JSON file" />
        <small class="form-text text-muted">Imported chat messages will replace current history.</small>
      </div>

      <div id="tab-media" class="tabcontent" role="tabpanel" aria-labelledby="tab-btn-media" hidden>
        <h5>Media Upload & AI Analysis</h5>
        <label id="image-upload-label" for="image-upload-input" tabindex="0" aria-controls="image-preview-container">Click or press Enter to upload images</label>
        <input type="file" id="image-upload-input" accept="image/*" multiple aria-describedby="upload-help" />
        <small id="upload-help" class="text-muted mb-2">Supports PNG, JPG, GIF. AI caption coming soon!</small>
        <div id="image-preview-container" aria-live="polite" aria-atomic="true">
          <p>No images uploaded yet.</p>
        </div>
      </div>

      <div id="tab-html" class="tabcontent" role="tabpanel" aria-labelledby="tab-btn-html" hidden>
        <h5>HTML Editor with Live Preview</h5>
        <textarea id="html-editor-textarea" placeholder="Write raw HTML here..."></textarea>
        <button id="html-toggle-preview" aria-pressed="false" aria-label="Toggle live HTML preview">Toggle Preview</button>
        <div id="html-preview" hidden aria-live="polite" aria-atomic="true">Live preview will show here.</div>
      </div>

      <div id="tab-text" class="tabcontent" role="tabpanel" aria-labelledby="tab-btn-text" hidden>
        <h5>Notes & Markdown Editor</h5>
        <textarea id="note-editor" placeholder="Write notes or markdown here..." spellcheck="true"></textarea>
      </div>
    </section>

    <!-- Chat Area -->
    <section id="chat-area" role="main" aria-label="Chat conversation with AI">
      <div id="msgs" tabindex="0" aria-live="polite" aria-atomic="false" role="log"></div>
      <div id="typing-indicator" aria-live="assertive" aria-atomic="true" style="display:none;">
        AI is typing &nbsp;
        <span class="typing-dot"></span>
        <span class="typing-dot"></span>
        <span class="typing-dot"></span>
      </div>

      <form id="input-form" autocomplete="off" role="search" aria-label="Chat input form" style="padding:10px 20px; background:#1f263b; display:flex; align-items: center;">
        <textarea 
          id="user-input" 
          name="message" 
          placeholder="Ask me anything..." 
          aria-label="Message input" 
          autocomplete="off" 
          rows="1" 
          style="flex-grow:1; font-size:16px; padding: 12px 16px; border-radius: 30px; border:none; color:#ddeeff; background:#293046; resize:none;"
        ></textarea>
        <button id="send-btn" type="submit" aria-label="Send message"
          style="margin-left:12px; padding:0 20px; background:#3a70ff; border:none; color:white; font-weight:700; font-size:16px; border-radius:30px; cursor:pointer;">Send</button>
      </form>
    </section>

  </div>

  <script>
    window.addEventListener("load", () => {
      // Cached DOM elements
      const tabs = [...document.querySelectorAll(".tabbtn")];
      const tabContents = [...document.querySelectorAll(".tabcontent")];
      const msgs = document.getElementById("msgs");
      const inputForm = document.getElementById("input-form");
      const userInput = document.getElementById("user-input");
      const typingInd = document.getElementById("typing-indicator");
      const sendBtn = document.getElementById("send-btn");

      // Settings elements
      const personalitySelect = document.getElementById("personality-select");
      const useContextCheckbox = document.getElementById("use-context");
      const useExternalCheckbox = document.getElementById("use-external");
      const spellCheckCheckbox = document.getElementById("spellcheck");
      const typingIndicatorCheckbox = document.getElementById("typing-indicator-checkbox");
      const darkModeCheckbox = document.getElementById("dark-mode");
      const fontSizeSlider = document.getElementById("font-size");
      const fontSizeVal = document.getElementById("font-size-val");
      const typingSpeedSlider = document.getElementById("typing-speed");
      const typingSpeedVal = document.getElementById("typing-speed-val");
      const contextLengthSlider = document.getElementById("context-length");
      const contextLengthVal = document.getElementById("context-length-val");
      const clearChatBtn = document.getElementById("clear-chat");

      // Quiz tab elements
      const startQuizBtn = document.getElementById("start-quiz-btn");
      const quizArea = document.getElementById("quiz-area");

      // Proxy tab elements
      const proxyInput = document.getElementById("proxy-search-input");
      const proxyBtn = document.getElementById("proxy-search-btn");
      const proxyResults = document.getElementById("proxy-search-results");
      const proxyIframeWrapper = document.getElementById("proxy-iframe-wrapper");
      const proxyIframe = document.getElementById("proxy-iframe");
      const proxyLoading = document.getElementById("proxy-loading");

      // Voice tab elements
      const voiceStartBtn = document.getElementById("voice-start-btn");
      const voiceStopBtn = document.getElementById("voice-stop-btn");
      const voiceText = document.getElementById("voice-text");

      // Export tab elements
      const exportJsonBtn = document.getElementById("export-json-btn");
      const exportTxtBtn = document.getElementById("export-txt-btn");
      const importJsonInput = document.getElementById("import-json-input");

      // Media upload elements
      const imageUploadInput = document.getElementById("image-upload-input");
      const imagePreviewContainer = document.getElementById("image-preview-container");

      // HTML editor elements
      const htmlEditorTextarea = document.getElementById("html-editor-textarea");
      const htmlPreview = document.getElementById("html-preview");
      const htmlTogglePreviewBtn = document.getElementById("html-toggle-preview");

      // Text notes editor
      const noteEditor = document.getElementById("note-editor");

      // Global state
      let settings = {
        personality: "friendly",
        useContext: true,
        useExternalData: true,
        enableSpellCheck: true,
        useTypingDelay: true,
        darkMode: true,
        fontSize: 16,
        typingSpeedMs: 30,
        maxMemorySteps: 5,
      };

      let chatMemory = [];
      let quizState = null;
      let userPreferences = {}; // AI learning data stored here

      // UTILITIES

      // Sanitize HTML
      function sanitize(html) {
        return DOMPurify.sanitize(html);
      }

      // Linkify URLs
      function linkify(text) {
        const urlRegex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi;
        return text.replace(urlRegex, (url) => {
          return `<a href="${url}" target="_blank" rel="noopener noreferrer">${url}</a>`;
        });
      }

      // Append message bubble
      function appendMsg(text, role = "ai") {
        if (!text) return;
        const div = document.createElement("div");
        div.className =
          "msg " +
          (role === "user" ? "user" : "ai") +
          " animate__animated animate__fadeInUp";
        div.innerHTML = sanitize(linkify(text));
        msgs.appendChild(div);
        msgs.scrollTo({ top: msgs.scrollHeight, behavior: "smooth" });
      }

      // Save/load chat memory
      function saveChatMemory() {
        localStorage.setItem(
          "ultimateAIChatMem",
          JSON.stringify(chatMemory.slice(-settings.maxMemorySteps * 2))
        );
      }

      function loadChatMemory() {
        try {
          const mem = localStorage.getItem("ultimateAIChatMem");
          if (mem) {
            chatMemory = JSON.parse(mem);
            for (const m of chatMemory) {
              appendMsg(m.text, m.role === "user" ? "user" : "ai");
            }
          }
        } catch (e) {
          console.warn("Failed to load chat memory", e);
        }
      }

      // Spell correction (stub, basic dictionary)
      function spellCorrect(text) {
        const corrections = {
          adn: "and",
          teh: "the",
          beleive: "believe",
          realy: "really",
          recieve: "receive",
          exmaple: "example",
          langauge: "language",
        };
        return text.replace(/\b\w+\b/g, (word) => corrections[word.toLowerCase()] || word);
      }

      // Math evaluation (simple, safe)
      function parseMath(text) {
        let expr = text.toLowerCase().replace(/[^0-9+\-*/()., ]/g, "").replace(/,/g, "");
        try {
          // eslint-disable-next-line no-eval
          let val = eval(expr);
          if (typeof val === "number" && isFinite(val)) return val;
        } catch {}
        return null;
      }

      // Decode html entities (for trivia etc)
      function decodeHtml(html) {
        const txt = document.createElement("textarea");
        txt.innerHTML = html;
        return txt.value;
      }

      // Shuffle array in place
      function shuffle(array) {
        for (let i = array.length - 1; i > 0; i--) {
          let j = Math.floor(Math.random() * (i + 1));
          [array[i], array[j]] = [array[j], array[i]];
        }
      }

      // Show/hide loading on proxy iframe
      function showProxyLoading(show = true) {
        proxyLoading.style.display = show ? "block" : "none";
        proxyIframe.style.display = show ? "none" : "block";
      }

      // Save and load user preferences for "AI learning"
      function savePreferences() {
        localStorage.setItem("ultimateAIUserPrefs", JSON.stringify(userPreferences));
      }

      function loadPreferences() {
        try {
          const prefs = localStorage.getItem("ultimateAIUserPrefs");
          if (prefs) userPreferences = JSON.parse(prefs);
        } catch {}
      }

      // SETTINGS MANAGEMENT

      function applySettingsUI() {
        personalitySelect.value = settings.personality;
        useContextCheckbox.checked = settings.useContext;
        useExternalCheckbox.checked = settings.useExternalData;
        spellCheckCheckbox.checked = settings.enableSpellCheck;
        typingIndicatorCheckbox.checked = settings.useTypingDelay;
        darkModeCheckbox.checked = settings.darkMode;
        fontSizeSlider.value = settings.fontSize;
        fontSizeVal.textContent = settings.fontSize;
        typingSpeedSlider.value = settings.typingSpeedMs;
        typingSpeedVal.textContent = settings.typingSpeedMs;
        contextLengthSlider.value = settings.maxMemorySteps;
        contextLengthVal.textContent = settings.maxMemorySteps;
        applyAppearance();
      }

      function saveSettings() {
        localStorage.setItem("ultimateAISettings", JSON.stringify(settings));
      }

      function loadSettings() {
        try {
          const stored = localStorage.getItem("ultimateAISettings");
          if (stored) Object.assign(settings, JSON.parse(stored));
        } catch {}
        applySettingsUI();
      }

      function applyAppearance() {
        if (settings.darkMode) {
          document.body.classList.remove("light-mode");
        } else {
          document.body.classList.add("light-mode");
        }
        msgs.style.fontSize = settings.fontSize + "px";
        userInput.style.fontSize = settings.fontSize + "px";
      }

      function attachSettingsListeners() {
        personalitySelect.addEventListener("change", (e) => {
          settings.personality = e.target.value;
          saveSettings();
          savePreferences(); // Learning
        });
        useContextCheckbox.addEventListener("change", (e) => {
          settings.useContext = e.target.checked;
          saveSettings();
        });
        useExternalCheckbox.addEventListener("change", (e) => {
          settings.useExternalData = e.target.checked;
          saveSettings();
        });
        spellCheckCheckbox.addEventListener("change", (e) => {
          settings.enableSpellCheck = e.target.checked;
          saveSettings();
        });
        typingIndicatorCheckbox.addEventListener("change", (e) => {
          settings.useTypingDelay = e.target.checked;
          saveSettings();
        });
        darkModeCheckbox.addEventListener("change", (e) => {
          settings.darkMode = e.target.checked;
          applyAppearance();
          saveSettings();
        });
        fontSizeSlider.addEventListener("input", (e) => {
          settings.fontSize = Number(e.target.value);
          fontSizeVal.textContent = settings.fontSize;
          applyAppearance();
          saveSettings();
        });
        typingSpeedSlider.addEventListener("input", (e) => {
          settings.typingSpeedMs = Number(e.target.value);
          typingSpeedVal.textContent = settings.typingSpeedMs;
          saveSettings();
        });
        contextLengthSlider.addEventListener("input", (e) => {
          settings.maxMemorySteps = Number(e.target.value);
          contextLengthVal.textContent = settings.maxMemorySteps;
          saveSettings();
        });
        clearChatBtn.addEventListener("click", () => {
          if (confirm("Clear chat history permanently?")) {
            chatMemory = [];
            msgs.innerHTML = "";
            saveChatMemory();
          }
        });
      }

      // TAB NAVIGATION

      function initTabs() {
        tabs.forEach((btn) => {
          btn.addEventListener("click", () => {
            tabs.forEach((b) => {
              b.classList.remove("active");
              const tid = b.getAttribute("aria-controls");
              const tabc = document.getElementById(tid);
              if (tabc) {
                tabc.hidden = true;
                tabc.setAttribute("aria-hidden", "true");
              }
              b.setAttribute("aria-selected", "false");
            });
            btn.classList.add("active");
            const showid = btn.getAttribute("aria-controls");
            const showTab = document.getElementById(showid);
            if (showTab) {
              showTab.hidden = false;
              showTab.setAttribute("aria-hidden", "false");
            }
            btn.setAttribute("aria-selected", "true");
          });
        });
      }

      // CHAT MEMORY/CONTEXT
      function addToMemory(role, text) {
        chatMemory.push({ role, text });
        let maxLen = settings.maxMemorySteps * 2;
        if (chatMemory.length > maxLen) {
          chatMemory.splice(0, chatMemory.length - maxLen);
        }
        saveChatMemory();
      }

      function contextText() {
        if (!settings.useContext) return "";
        let relevant = chatMemory.slice(-settings.maxMemorySteps * 2);
        return relevant
          .map((m) => (m.role === "user" ? "User: " : "AI: ") + m.text)
          .join("\n");
      }

      // AI RESPONSE GENERATION

      const OPENAI_API_KEY = ""; // Add your key for OPENAI use

      const fallbackQA = {
        "how many continents are there": "There are 7 continents on Earth.",
        "what color do you get when you mix red and blue":
          "You get purple.",
        "who was abraham lincoln":
          "He was the 16th President of the United States.",
        "what is the largest planet": "Jupiter is the largest planet.",
        "how many legs does a spider have": "A spider has 8 legs.",
        "chemical formula of water": "H₂O is the chemical formula of water.",
        "what is photosynthesis":
          "Photosynthesis is the process plants use to turn sunlight into energy.",
        "who is the president of the united states": "Joe Biden.",
      };

      // DuckDuckGo Instant Answer API
      async function duckDuckGoQuery(query) {
        try {
          const url = `https://api.duckduckgo.com/?q=${encodeURIComponent(
            query
          )}&format=json&skip_disambig=1&no_redirect=1`;
          const res = await fetch(url);
          if (!res.ok) return null;
          return await res.json();
        } catch {
          return null;
        }
      }

      // Wikipedia summary API
      async function wikiSummary(query) {
        try {
          const url = `https://en.wikipedia.org/api/rest_v1/page/summary/${encodeURIComponent(
            query
          )}`;
          const res = await fetch(url);
          if (!res.ok) return null;
          const data = await res.json();
          if (data.extract) {
            let link =
              data.content_urls?.desktop?.page ||
              `https://en.wikipedia.org/wiki/${encodeURIComponent(query)}`;
            return `${data.extract}\n\n<a href="${link}" target="_blank" rel="noopener noreferrer">More on Wikipedia</a>`;
          }
          return null;
        } catch {
          return null;
        }
      }

      // Numbers API trivia fetch
      async function numbersFact(num) {
        try {
          const res = await fetch(`https://numbersapi.com/${num}/trivia?json`);
          if (!res.ok) return null;
          const data = await res.json();
          return data.text || null;
        } catch {
          return null;
        }
      }

      // Open Trivia DB random question
      async function openTrivia() {
        try {
          const res = await fetch(
            "https://opentdb.com/api.php?amount=1&type=multiple&difficulty=easy"
          );
          if (!res.ok) return null;
          const data = await res.json();
          if (!data.results || !data.results.length) return null;
          return data.results[0];
        } catch {
          return null;
        }
      }

      // NewsAPI org demo (not really working without a key - placeholder)
      async function fetchNews() {
        try {
          const url =
            "https://api.currentsapi.services/v1/latest-news?category=technology&apiKey=demo";
          const res = await fetch(url);
          if (!res.ok) return null;
          const data = await res.json();
          return data.news
            .slice(0, 5)
            .map(
              (n) =>
                `${n.title}\n${n.description}\n<a href="${n.url}" target="_blank">${n.url}</a>`
            )
            .join("\n\n");
        } catch {
          return null;
        }
      }

      // Open-Meteo weather API demo
      async function fetchWeather(city = "London") {
        try {
          const geo = await fetch(
            `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(
              city
            )}&count=1`
          );
          const geoData = await geo.json();
          if (!geoData.results || !geoData.results.length) return null;
          const lat = geoData.results[0].latitude;
          const lon = geoData.results[0].longitude;
          const weatherRes = await fetch(
            `https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}&current_weather=true`
          );
          if (!weatherRes.ok) return null;
          const weatherData = await weatherRes.json();
          if (!weatherData.current_weather) return null;
          return `Current temperature in ${city}: ${weatherData.current_weather.temperature}°C, wind speed: ${weatherData.current_weather.windspeed} km/h`;
        } catch {
          return null;
        }
      }

      // Currency exchange (EXR host)
      async function currencyConvert(from = "USD", to = "EUR") {
        try {
          const url = `https://api.exchangerate.host/convert?from=${from.toUpperCase()}&to=${to.toUpperCase()}`;
          const res = await fetch(url);
          if (!res.ok) return null;
          const data = await res.json();
          if (!data.result) return null;
          return `1 ${from.toUpperCase()} = ${data.result.toFixed(4)} ${to.toUpperCase()}`;
        } catch {
          return null;
        }
      }

      // Translate example (LibreTranslate)
      async function translateText(text, target = "es") {
        try {
          const res = await fetch("https://libretranslate.com/translate", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ q: text, source: "en", target }),
          });
          if (!res.ok) return null;
          const data = await res.json();
          return data.translatedText;
        } catch {
          return null;
        }
      }

      // Grammar check demo (LanguageTool)
      async function grammarCheck(text) {
        try {
          const res = await fetch("https://api.languagetool.org/v2/check", {
            method: "POST",
            headers: { "Content-Type": "application/x-www-form-urlencoded" },
            body: `text=${encodeURIComponent(text)}&language=en-US`,
          });
          if (!res.ok) return null;
          const data = await res.json();
          if (data.matches && data.matches.length) {
            return data.matches
              .map(
                (m) =>
                  `Issue: ${m.message} at ${m.offset}-${m.offset + m.length}`
              )
              .join("\n");
          }
          return "No grammar errors found.";
        } catch {
          return null;
        }
      }

      // User input to AI response generator
      async function generateReply(input) {
        let text = input.trim();
        if (settings.enableSpellCheck) text = spellCorrect(text);

        if (quizState) {
          const choice = Number(text);
          if (!isNaN(choice) && choice >= 1 && choice <= quizState.options.length) {
            const answer = quizState.options[choice - 1];
            if (answer === quizState.correct_answer) {
              quizState = null;
              return "Correct! Nice job. Ask me for another quiz anytime.";
            } else {
              return "Oops, wrong answer. Try again or type 'skip' to skip the quiz.";
            }
          }
          if (text.toLowerCase() === "skip") {
            quizState = null;
            return "Quiz skipped. Ask me anything else or start a new quiz.";
          }
          return "Please respond with the option number or type 'skip'.";
        }

        // Greetings
        if (/^(hello|hi|hey|yo|hola|greetings)/i.test(text)) {
          if (settings.personality === "friendly")
            return "Hello! Ask me any question about math, trivia, or general knowledge and I'll help.";
          if (settings.personality === "formal") return "Good day. Please ask your question.";
          if (settings.personality === "funny") return "Yo yo! Ready to get smart? Fire away!";
          if (settings.personality === "robotic")
            return "Greetings, human. How can I assist your calculations and queries?";
          if (settings.personality === "friendly-funny")
            return "Hey buddy! Ready to get your brain juice flowing?";
        }

        // Math evaluation
        const mathResult = parseMath(text);
        if (mathResult !== null) return `The answer is ${mathResult}.`;

        // Spell word query
        const spellMatch = text.match(/\bspell\s+(\w+)/i);
        if (spellMatch) {
          const w = spellMatch[1].toUpperCase();
          return `${w.split("").join("-")} spells ${spellMatch[1]}.`;
        }

        // Number fact request
        const numbMatch = text.match(/number fact for (\d+)/i);
        if (numbMatch) {
          const fact = await numbersFact(numbMatch[1]);
          if (fact) return `Did you know? ${fact}`;
        }

        // Quiz request
        if (/\b(quiz|trivia|question)\b/i.test(text)) {
          const trivia = await openTrivia();
          if (trivia) {
            let options = [...trivia.incorrect_answers, trivia.correct_answer];
            options = options.map(decodeHtml);
            shuffle(options);
            quizState = {
              question: decodeHtml(trivia.question),
              correct_answer: decodeHtml(trivia.correct_answer),
              options,
            };
            let msg = `Trivia question:\n${quizState.question}\nOptions:\n`;
            options.forEach((opt, i) => {
              msg += `${i + 1}: ${opt}\n`;
            });
            msg += '\nType your answer option number or "skip".';
            return msg;
          }
        }

        // API lookups if enabled
        if (settings.useExternalData) {
          // DuckDuckGo instant answer
          const ddg = await duckDuckGoQuery(text);
          if (ddg && ddg.AbstractText && ddg.AbstractText.trim().length > 3) {
            let ans = ddg.AbstractText;
            if (ddg.AbstractURL) {
              ans += `\n\n<a href="${ddg.AbstractURL}" target="_blank" rel="noopener">Read more on DuckDuckGo</a>`;
            }
            return ans;
          }

          // Wikipedia summary fallback
          const wiki = await wikiSummary(text);
          if (wiki) return wiki;

          // Demo translation if starts with translate: "translate hello to es"
          const transMatch = text.match(/^translate\s+(.*?)\s+to\s+(\w{2})$/i);
          if (transMatch) {
            const tr = await translateText(transMatch[1], transMatch[2]);
            if (tr) return `Translation (${transMatch[2]}): ${tr}`;
          }

          // Weather query "weather in city"
          const weatherMatch = text.match(/weather in (.+)/i);
          if (weatherMatch) {
            const w = await fetchWeather(weatherMatch[1]);
            if (w) return w;
          }

          // Currency convert "convert 100 usd to eur"
          const currencyMatch = text.match(
            /convert\s+(\d+(?:\.\d+)?)\s+(\w{3})\s+to\s+(\w{3})/i
          );
          if (currencyMatch) {
            const v = Number(currencyMatch[1]);
            const from = currencyMatch[2];
            const to = currencyMatch[3];
            const rate = await currencyConvert(from, to);
            if (rate)
              return `${v} ${from.toUpperCase()} is approx ${(rate
                .split("=")[1] *
                v
              ).toFixed(4)} ${to.toUpperCase()}\n(Rate: ${rate})`;
          }

          // Grammar check if command starts with "check grammar:"
          const grammarMatch = text.match(/^check grammar:\s*(.+)$/i);
          if (grammarMatch) {
            const checkRes = await grammarCheck(grammarMatch[1]);
            if (checkRes) return checkRes;
          }
        }

        // Fallback dictionary answer
        const key = text.toLowerCase().replace(/[?.!]/g, "").trim();
        if (fallbackQA[key]) return fallbackQA[key];

        // Personality fallback
        const fallbackMsgs = {
          friendly:
            "Hmm... I don't know that one. Try asking me a math question or trivia!",
          formal: "Apologies, the information is unavailable. Please ask something else.",
          funny: "I can't help you with that... maybe take a snack break and try again!",
          robotic: "Processing incomplete. Cannot compute response.",
          "friendly-funny": "Whoa, that's beyond me. Let's keep it simple, friend!",
        };
        return fallbackMsgs[settings.personality] || fallbackMsgs.friendly;
      }

      // Typing indicator + bot reply display
      async function botReplyWithTyping(text) {
        if (!settings.useTypingDelay) {
          appendMsg(text, "ai");
          return;
        }
        typingInd.style.display = "flex";
        sendBtn.disabled = true;
        userInput.disabled = true;

        const delay = Math.max(700, text.length * settings.typingSpeedMs);
        await new Promise((r) => setTimeout(r, delay));

        typingInd.style.display = "none";
        appendMsg(text, "ai");
        sendBtn.disabled = false;
        userInput.disabled = false;
        userInput.focus();
      }

      // CHAT FORM SUBMIT HANDLER
      inputForm.addEventListener("submit", async (e) => {
        e.preventDefault();
        const val = userInput.value.trim();
        if (!val) return;
        appendMsg(val, "user");
        addToMemory("user", val);
        userInput.value = "";
        userInput.disabled = true;

        try {
          // Special command: detect image caption request (stub)
          if (/^(analyze|caption) image$/i.test(val)) {
            if (uploadedImages.length) {
              await botReplyWithTyping(
                "Analyzing your uploaded image... (stub: no real AI analysis implemented)"
              );
              addToMemory(
                "ai",
                "Analyzing your uploaded image... (stub: no real AI analysis implemented)"
              );
            } else {
              await botReplyWithTyping(
                "No images uploaded yet. Please upload an image in the Media tab."
              );
            }
            userInput.disabled = false;
            userInput.focus();
            return;
          }

          const reply = await generateReply(val);
          await botReplyWithTyping(reply);
          addToMemory("ai", reply);

          // Track queries in preferences for "learning"
          userPreferences.lastPersonality = settings.personality;
          userPreferences.lastQuery = val;
          savePreferences();
        } catch (ex) {
          console.error(ex);
          await botReplyWithTyping(
            "Sorry, something went wrong. Please try again."
          );
        }

        userInput.disabled = false;
        userInput.focus();
      });

      // ------------------------
      // PROXY SEARCH FUNCTIONALITY
      // ------------------------
      proxyBtn.addEventListener("click", async () => {
        const q = proxyInput.value.trim();
        if (!q) return;

        // Detect if input looks like URL
        const isUrl = /^(https?:\/\/)/i.test(q) || /\.[a-z]{2,}$/i.test(q);

        if (isUrl) {
          // Directly load URL in iframe with proxy loading UI
          loadInIframe(q);
          proxyResults.innerHTML = "";
          return;
        }

        // Otherwise treat as search query
        proxyResults.innerHTML =
          'Searching <span class="spinner-border spinner-border-sm"></span>';
        proxyIframe.srcdoc =
          "<p style='font-family:sans-serif;color:#666;text-align:center;padding:2rem;'>Search results or embedded website will show here.</p>";
        proxyIframe.style.display = "none";
        proxyLoading.style.display = "block";

        try {
          const ddgData = await duckDuckGoQuery(q);
          if (ddgData && ddgData.RelatedTopics && ddgData.RelatedTopics.length) {
            proxyResults.innerHTML = "";
            for (const item of ddgData.RelatedTopics.slice(0, 10)) {
              if (item.Text && item.FirstURL) {
                const p = document.createElement("p");
                p.innerHTML = `<a href="${item.FirstURL}" target="_blank" rel="noopener noreferrer">${item.Text}</a>`;
                p.style.cursor = "pointer";
                p.setAttribute('tabindex', '0');
                p.addEventListener("click", (e) => {
                  e.preventDefault();
                  loadInIframe(item.FirstURL);
                });
                p.addEventListener("keydown", (e) => {
                  if (e.key === "Enter" || e.key === " ") {
                    e.preventDefault();
                    loadInIframe(item.FirstURL);
                  }
                });
                proxyResults.appendChild(p);
              } else if (item.Topics) {
                item.Topics.slice(0, 3).forEach((topic) => {
                  const p = document.createElement("p");
                  p.innerHTML = `<a href="${topic.FirstURL}" target="_blank" rel="noopener noreferrer">${topic.Text}</a>`;
                  p.style.cursor = "pointer";
                  p.setAttribute('tabindex', '0');
                  p.addEventListener("click", (e) => {
                    e.preventDefault();
                    loadInIframe(topic.FirstURL);
                  });
                  p.addEventListener("keydown", (e) => {
                    if (e.key === "Enter" || e.key === " ") {
                      e.preventDefault();
                      loadInIframe(topic.FirstURL);
                    }
                  });
                  proxyResults.appendChild(p);
                });
              }
            }
            proxyLoading.style.display = "none";
            proxyIframe.style.display = "none";
          } else {
            proxyResults.textContent = "No results found.";
            proxyLoading.style.display = "none";
            proxyIframe.style.display = "none";
          }
        } catch (error) {
          proxyResults.textContent = "Error during search.";
          proxyLoading.style.display = "none";
          proxyIframe.style.display = "none";
        }
      });

      function loadInIframe(url) {
        showProxyLoading(true);
        proxyIframe.src = url;
        proxyResults.innerHTML = "";
        proxyIframe.style.display = "block";

        proxyIframe.onload = () => {
          showProxyLoading(false);
        };
        proxyIframe.onerror = () => {
          proxyLoading.style.display = "none";
          proxyIframe.style.display = "none";
          proxyResults.textContent = "Failed to load page in proxy iframe.";
        };
      }

      // ------------------------
      // QUIZ TOOL
      // ------------------------
      startQuizBtn.addEventListener("click", async () => {
        quizArea.textContent = "Loading quiz...";
        const trivia = await openTrivia();
        if (!trivia) {
          quizArea.textContent = "Failed to load question. Try again later.";
          return;
        }
        let options = [...trivia.incorrect_answers, trivia.correct_answer].map(
          decodeHtml
        );
        shuffle(options);
        quizState = {
          question: decodeHtml(trivia.question),
          correct_answer: decodeHtml(trivia.correct_answer),
          options,
        };
        let msg = `Trivia question:\n${quizState.question}\nOptions:\n`;
        quizState.options.forEach((o, i) => (msg += `${i + 1}: ${o}\n`));
        msg += `\nType your answer option number in chat or 'skip'.`;
        quizArea.textContent = msg;
      });

      // ------------------------
      // VOICE CHAT - Web Speech API
      // ------------------------

      let recognition = null;
      let speechSynthesisObj = window.speechSynthesis;
      voiceStopBtn.disabled = true;

      if ("webkitSpeechRecognition" in window || "SpeechRecognition" in window) {
        const SpeechRecognition =
          window.SpeechRecognition || window.webkitSpeechRecognition;
        recognition = new SpeechRecognition();
        recognition.lang = "en-US";
        recognition.interimResults = false;
        recognition.maxAlternatives = 1;

        recognition.onresult = (evt) => {
          const spoken = evt.results[0][0].transcript;
          voiceText.textContent = "You: " + spoken;
          // Submit as chat message
          appendMsg(spoken, "user");
          addToMemory("user", spoken);
          replyViaAI(spoken);
        };
        recognition.onerror = (evt) => {
          voiceText.textContent = "Speech recognition error: " + evt.error;
          voiceStopBtn.disabled = true;
          voiceStartBtn.disabled = false;
        };
        recognition.onend = () => {
          voiceText.textContent += " (Stopped)";
          voiceStopBtn.disabled = true;
          voiceStartBtn.disabled = false;
        };
      } else {
        voiceText.textContent = "Speech recognition not supported in this browser.";
        voiceStartBtn.disabled = true;
      }

      async function replyViaAI(text) {
        try {
          const reply = await generateReply(text);
          await botReplyWithTyping(reply);
          addToMemory("ai", reply);
          // Speak reply
          if (speechSynthesisObj) {
            const utterance = new SpeechSynthesisUtterance(reply);
            utterance.lang = "en-US";
            speechSynthesisObj.speak(utterance);
          }
        } catch {
          await botReplyWithTyping("Sorry, I couldn't process your voice input.");
        }
      }

      voiceStartBtn.addEventListener("click", () => {
        if (recognition) {
          recognition.start();
          voiceText.textContent = "Listening... Speak now";
          voiceStartBtn.disabled = true;
          voiceStopBtn.disabled = false;
        }
      });
      voiceStopBtn.addEventListener("click", () => {
        if (recognition) {
          recognition.stop();
          voiceStartBtn.disabled = false;
          voiceStopBtn.disabled = true;
        }
      });

      // -------------------------
      // EXPORT / IMPORT CHAT
      // -------------------------

      exportJsonBtn.addEventListener("click", () => {
        if (chatMemory.length === 0) {
          Swal.fire("Info", "No chat history to export.", "info");
          return;
        }
        const dataStr = JSON.stringify(chatMemory, null, 2);
        const blob = new Blob([dataStr], { type: "application/json" });
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url;
        a.download = `chat-history-${Date.now()}.json`;
        a.click();
        URL.revokeObjectURL(url);
      });

      exportTxtBtn.addEventListener("click", () => {
        if (chatMemory.length === 0) {
          Swal.fire("Info", "No chat history to export.", "info");
          return;
        }
        const txt = chatMemory
          .map((m) => `${m.role.toUpperCase()}:\n${m.text}\n`)
          .join("\n");
        const blob = new Blob([txt], { type: "text/plain" });
        const url = URL.createObjectURL(blob);
        const a = document.createElement("a");
        a.href = url;
        a.download = `chat-history-${Date.now()}.txt`;
        a.click();
        URL.revokeObjectURL(url);
      });

      importJsonInput.addEventListener("change", (e) => {
        const file = e.target.files[0];
        if (!file) return;
        const reader = new FileReader();
        reader.onload = (evt) => {
          try {
            const mem = JSON.parse(evt.target.result);
            if (!Array.isArray(mem)) throw new Error("Invalid format");
            chatMemory = mem;
            msgs.innerHTML = "";
            chatMemory.forEach((m) => appendMsg(m.text, m.role === "user" ? "user" : "ai"));
            saveChatMemory();
            Swal.fire("Success", "Chat history imported successfully.", "success");
            importJsonInput.value = "";
          } catch {
            Swal.fire("Error", "Invalid JSON file.", "error");
          }
        };
        reader.readAsText(file);
      });

      // -------------------------
      // MEDIA UPLOAD HANDLING
      // -------------------------

      let uploadedImages = [];

      imageUploadInput.addEventListener("change", (e) => {
        const files = Array.from(e.target.files);
        if (!files.length) return;
        for (const file of files) {
          if (!file.type.startsWith("image/")) continue;
          const reader = new FileReader();
          reader.onload = (event) => {
            const imgUrl = event.target.result;
            uploadedImages.push({ file, url: imgUrl });
            renderImagePreviews();
          };
          reader.readAsDataURL(file);
        }
        // Clear input so same file can be re-uploaded if needed
        e.target.value = "";
      });

      function renderImagePreviews() {
        if (!uploadedImages.length) {
          imagePreviewContainer.innerHTML = "<p>No images uploaded yet.</p>";
          return;
        }
        const content = uploadedImages
          .map(
            (img, i) =>
              `<div tabindex="0" aria-label="Uploaded image ${i + 1}" style="margin-bottom:12px;">
                <img src="${img.url}" alt="Uploaded image ${i + 1}" />
                <button 
                  aria-label="Remove image ${i + 1}" 
                  data-index="${i}" 
                  class="btn btn-sm btn-outline-danger mt-1 remove-img-btn" 
                  type="button"
                >Remove</button>
              </div>`
          )
          .join("");
        imagePreviewContainer.innerHTML = content;
        // Attach remove button handlers
        [...imagePreviewContainer.querySelectorAll(".remove-img-btn")].forEach((btn) => {
          btn.addEventListener("click", (ev) => {
            const idx = Number(ev.target.dataset.index);
            uploadedImages.splice(idx, 1);
            renderImagePreviews();
          });
        });
      }

      // Accessibility for upload label keyboard interaction
      const imageUploadLabel = document.getElementById("image-upload-label");
      imageUploadLabel.addEventListener("keydown", (e) => {
        if (e.key === "Enter" || e.key === " ") {
          e.preventDefault();
          imageUploadInput.click();
        }
      });

      // -------------------------
      // HTML EDITOR + LIVE PREVIEW
      // -------------------------
      htmlTogglePreviewBtn.addEventListener("click", () => {
        const showing = htmlPreview.hasAttribute("hidden") === false;
        if (showing) {
          htmlPreview.setAttribute("hidden", "");
          htmlTogglePreviewBtn.setAttribute("aria-pressed", "false");
          htmlTogglePreviewBtn.textContent = "Toggle Preview";
        } else {
          htmlPreview.removeAttribute("hidden");
          htmlTogglePreviewBtn.setAttribute("aria-pressed", "true");
          htmlTogglePreviewBtn.textContent = "Hide Preview";
          updateHtmlPreview();
        }
      });

      htmlEditorTextarea.addEventListener("input", () => {
        if (!htmlPreview.hasAttribute("hidden")) updateHtmlPreview();
      });

      function updateHtmlPreview() {
        // Sanitize and render raw HTML inside preview container (safe)
        htmlPreview.innerHTML = sanitize(htmlEditorTextarea.value) || "<i>Nothing to preview</i>";
      }

      // -------------------------
      // Notes Editor (Text tab)
      // -------------------------
      // Save notes locally for persistence
      noteEditor.addEventListener("input", () => {
        try {
          localStorage.setItem("ultimateAINotes", noteEditor.value);
        } catch {}
      });

      function loadNotes() {
        try {
          const val = localStorage.getItem("ultimateAINotes");
          if (val) noteEditor.value = val;
        } catch {}
      }

      // -------------------------
      // INITIALIZATION
      // -------------------------

      function init() {
        initTabs();
        loadSettings();
        attachSettingsListeners();
        loadChatMemory();
        loadPreferences();
        loadNotes();
        applySettingsUI();
        renderImagePreviews();

        userInput.focus();

        // Keyboard shortcuts for tabs e.g. Ctrl+1 .. Ctrl+9
        const tabKeys = {
          1: "tab-ai",
          2: "tab-data",
          3: "tab-quiz",
          4: "tab-search",
          5: "tab-voice",
          6: "tab-export",
          7: "tab-media",
          8: "tab-html",
          9: "tab-text",
        };
        Object.entries(tabKeys).forEach(([key, id]) => {
          Mousetrap.bind("ctrl+" + key, (e) => {
            e.preventDefault();
            document.querySelector(`button[aria-controls="${id}"]`).click();
          });
        });
      }

      init();
    });
  </script>
</body>
</html>