<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap" rel="stylesheet">
    <!-- Vazirmatn covers Arabic + Persian script; applied only under [dir="rtl"]
         (see base.css). Lato stays the sole LTR typeface. -->
    <link href="https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;700;900&display=swap" rel="stylesheet">
    <!-- MDI icon font from CDN (not self-hosted) — bypasses the Cloudflare proxy
         on app.mbset.com which resets self-hosted /assets/*.woff2 requests.
         Keep @7.4.47 in sync with @mdi/font in package.json. -->
    <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
    <link href="https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/css/materialdesignicons.min.css" rel="stylesheet">
    
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>MBset</title>

    <!-- Telegram Web App SDK -->
    <script src="https://telegram.org/js/telegram-web-app.js"></script>
    <script type="module" crossorigin src="/assets/index-41f7d18d.js"></script>
    <link rel="modulepreload" crossorigin href="/assets/vendor-vue-21f1d2e0.js">
    <link rel="modulepreload" crossorigin href="/assets/vendor-firebase-d96e7937.js">
    <link rel="modulepreload" crossorigin href="/assets/vendor-utils-afc41d2f.js">
    <link rel="modulepreload" crossorigin href="/assets/vendor-ui-8c9d9dcb.js">
    <link rel="stylesheet" href="/assets/index-56a91ca5.css">
  <link rel="manifest" href="/manifest.webmanifest"><script id="vite-plugin-pwa:register-sw" src="/registerSW.js"></script></head>
  <!-- GA4: no manual gtag snippet. Firebase Analytics (utils/firebase.js
       getAnalytics, G-WD3YL2KYRW) loads gtag.js and provides window.gtag —
       ONE property for all events (SDK logEvent + useAnalytics gtag). -->
  <body>
    <div id="app"></div>
    <!-- Boot watchdog and recovery screen (founder 2026-10-22). A phone that held
         an old build after a deploy showed a blank page with no message, and a
         restart did not help. Plain script, no module: it must run even when the
         app bundle cannot load. window.__mbsetBoot:
           done()            the app finished its first navigation (router afterEach)
           showRecovery(r)   show the screen now (chunk recovery gave up)
           report(kind, msg) send one error to POST /client-errors
         The watchdog shows the screen when the app has not booted after 20 s,
         and hides it again if the app boots later. The Reload button deletes the
         service workers and the caches, then reloads from the network. -->
    <div id="mbset-boot-recovery" hidden role="alertdialog" aria-labelledby="mbset-boot-recovery-title">
      <div class="mbr-card">
        <p id="mbset-boot-recovery-title" class="mbr-title"></p>
        <p class="mbr-text"></p>
        <button type="button" class="mbr-reload"></button>
        <button type="button" class="mbr-continue"></button>
      </div>
    </div>
    <style>
      #mbset-boot-recovery { position: fixed; inset: 0; z-index: 2147483647; display: flex; align-items: center; justify-content: center; padding: 16px; background: #ffffff; color: #1e293b; font-family: Lato, system-ui, sans-serif; }
      #mbset-boot-recovery[hidden] { display: none; }
      #mbset-boot-recovery .mbr-card { max-width: 360px; width: 100%; text-align: center; }
      #mbset-boot-recovery .mbr-title { font-size: 20px; font-weight: 700; margin: 0 0 8px; }
      #mbset-boot-recovery .mbr-text { font-size: 15px; line-height: 1.5; margin: 0 0 24px; color: #475569; }
      #mbset-boot-recovery button { display: block; width: 100%; min-height: 48px; border-radius: 12px; font: inherit; font-size: 16px; cursor: pointer; }
      #mbset-boot-recovery .mbr-reload { border: 0; background: #21827B; color: #ffffff; font-weight: 700; }
      #mbset-boot-recovery .mbr-continue { margin-top: 8px; border: 0; background: transparent; color: #1b6f69; }
      @media (prefers-color-scheme: dark) {
        #mbset-boot-recovery { background: #1a2332; color: rgba(255, 255, 255, 0.87); }
        #mbset-boot-recovery .mbr-text { color: rgba(255, 255, 255, 0.70); }
        #mbset-boot-recovery .mbr-continue { color: #59EAA9; }
      }
    </style>
    <script>
      (function () {
        var API = 'https://api.mbset.com/';
        var COPY = {
          en: ['MBset did not load', 'Your device may still hold an old version of the app. Reload to get the new one.', 'Reload', 'Continue anyway'],
          fr: ["MBset ne s'est pas chargé", "Votre appareil garde peut-être une ancienne version de l'application. Rechargez pour obtenir la nouvelle.", 'Recharger', 'Continuer quand même'],
          ar: ['لم يتم تحميل MBset', 'قد يحتفظ جهازك بنسخة قديمة من التطبيق. أعد التحميل للحصول على النسخة الجديدة.', 'إعادة التحميل', 'المتابعة على أي حال'],
          vi: ['MBset không tải được', 'Thiết bị của bạn có thể vẫn giữ phiên bản cũ của ứng dụng. Tải lại để nhận phiên bản mới.', 'Tải lại', 'Vẫn tiếp tục']
        };
        var booted = false, sticky = false, sent = 0;
        function lang() {
          var l = '';
          try { l = localStorage.getItem('userLanguage') || ''; } catch (e) {}
          l = String(l || navigator.language || 'en').slice(0, 2).toLowerCase();
          return COPY[l] ? l : 'en';
        }
        function shell() {
          try {
            if (window.ReactNativeWebView || window.Android) return /iPhone|iPad|iPod/.test(navigator.userAgent) ? 'ios' : 'android';
            if (window.Telegram && window.Telegram.WebApp && window.Telegram.WebApp.initData) return 'telegram';
          } catch (e) {}
          return 'web';
        }
        function report(kind, message, extra) {
          if (sent >= 10 || !API || API.charAt(0) === '%') return;
          sent += 1;
          var err = { kind: kind, message: String(message || '').slice(0, 1000), url: location.pathname, shell: shell() };
          if (extra && extra.build) err.build = String(extra.build).slice(0, 200);
          if (extra && extra.stack) err.stack = String(extra.stack).slice(0, 4000);
          var headers = { 'Content-Type': 'application/json' };
          if (extra && extra.token) headers.Authorization = 'Bearer ' + extra.token;
          try {
            fetch(API.replace(/\/$/, '') + '/client-errors', { method: 'POST', headers: headers, body: JSON.stringify({ errors: [err] }), keepalive: true }).catch(function () {});
          } catch (e) {}
        }
        function el() { return document.getElementById('mbset-boot-recovery'); }
        function show() {
          var box = el();
          if (!box || !box.hidden) return;
          var c = COPY[lang()];
          box.setAttribute('dir', lang() === 'ar' ? 'rtl' : 'ltr');
          box.querySelector('.mbr-title').textContent = c[0];
          box.querySelector('.mbr-text').textContent = c[1];
          box.querySelector('.mbr-reload').textContent = c[2];
          box.querySelector('.mbr-continue').textContent = c[3];
          box.hidden = false;
        }
        function hide() { var box = el(); if (box) box.hidden = true; }
        function reload() {
          var jobs = [];
          try { sessionStorage.removeItem('mbset_chunk_recovery'); } catch (e) {}
          try {
            if (navigator.serviceWorker) {
              jobs.push(navigator.serviceWorker.getRegistrations().then(function (rs) {
                return Promise.all(rs.map(function (r) { return r.unregister(); }));
              }));
            }
          } catch (e) {}
          try {
            if (window.caches) {
              jobs.push(caches.keys().then(function (ks) {
                return Promise.all(ks.map(function (k) { return caches.delete(k); }));
              }));
            }
          } catch (e) {}
          var go = function () { location.reload(); };
          Promise.all(jobs).then(go, go);
          setTimeout(go, 4000);
        }
        document.addEventListener('click', function (e) {
          var t = e.target;
          if (!t || !t.closest) return;
          if (t.closest('#mbset-boot-recovery .mbr-reload')) reload();
          else if (t.closest('#mbset-boot-recovery .mbr-continue')) { sticky = false; hide(); }
        });
        window.__mbsetBoot = {
          done: function () { booted = true; if (!sticky) hide(); },
          showRecovery: function () { sticky = true; show(); },
          report: report
        };
        setTimeout(function () {
          if (booted) return;
          show();
          report('boot-timeout', 'The app did not finish its first navigation after 20 s');
        }, 20000);
      })();
    </script>
    
  </body>
</html>
