<!doctype html>
<html lang="en" translate="yes">
  <head>
    <meta charset="utf-8" />
    <title>Free Online Form Builder | MobyForm</title>
    <meta
      name="description"
      content="The simplest way to create forms. Say goodbye to boring forms. Meet MobyForm — the free, intuitive form builder you've been looking for."
    />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
    <link rel="icon" type="image/x-icon" href="/favicon.ico" />
    <meta property="og:type" content="website" />
    <meta property="og:site_name" content="MobyForm Forms" />
    <meta property="og:url" content="https://mobyform.com/" />
    <meta name="title" property="og:title" content="Free Online Form Builder | MobyForm" />
    <meta
      property="og:description"
      content="The simplest way to create forms. Say goodbye to boring forms. Meet MobyForm — the free, intuitive form builder you've been looking for."
    />
    <meta name="image" property="og:image" content="https://mobyform.com/images/og.jpg" />
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:site" content="@MobyForm" />
    <meta name="twitter:title" content="Free Online Form Builder | MobyForm" />
    <meta
      name="twitter:description"
      content="The simplest way to create forms. Say goodbye to boring forms. Meet MobyForm — the free, intuitive form builder you've been looking for."
    />
    <meta name="twitter:image" content="https://mobyform.com/images/og.jpg" />

    <!-- 🔒 Content Security Policy (CSP) - World-class security implementation -->
    <meta
      http-equiv="Content-Security-Policy"
      content="
        default-src 'self';
        script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdnjs.cloudflare.com https://cdn.jsdelivr.net https://www.google.com https://www.gstatic.com https://maps.googleapis.com https://maps.gstatic.com https://static.cloudflareinsights.com;
        style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdnjs.cloudflare.com;
        font-src 'self' data: https://fonts.gstatic.com https://cdnjs.cloudflare.com https://at.alicdn.com http://at.alicdn.com;
        img-src 'self' data: https: blob: https://maps.googleapis.com https://maps.gstatic.com https://*.googleapis.com https://*.gstatic.com;
        connect-src 'self' https: wss: http://localhost:* http://127.0.0.1:* https://maps.googleapis.com https://maps.gstatic.com;
        frame-src 'self' https: https://www.google.com https://www.gstatic.com;
        object-src 'none';
        media-src 'self' data: https:;
        worker-src 'self' blob:;
        child-src 'self' blob:;
        form-action 'self';
        base-uri 'self';
        manifest-src 'self';
      "
    />

    <!-- 🔒 Security headers (valid as meta tags) -->
    <meta http-equiv="Referrer-Policy" content="strict-origin-when-cross-origin" />
    <meta http-equiv="Permissions-Policy" content="geolocation=(), microphone=(), camera=()" />
    <!-- Note: X-Frame-Options, X-Content-Type-Options, X-XSS-Protection must be set via HTTP headers (see public/_headers) -->

    <!-- Critical resource preload optimization for FCP -->
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link rel="dns-prefetch" href="//cdnjs.cloudflare.com" />

    <!-- Minimize critical CSS - avoid blocking rendering -->
    <style>
      /* Essential critical CSS only */
      body {
        margin: 0;
        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
      }
      #app {
        min-height: 100vh;
        position: relative;
      }
      /* Loading skeleton for better perceived performance */
      .app-loading {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        text-align: center;
      }
      .app-loading-spinner {
        width: 40px;
        height: 40px;
        border: 3px solid #e5e7eb;
        border-top-color: #3b82f6;
        border-radius: 50%;
        animation: spin 1s linear infinite;
        margin: 0 auto 20px;
      }
      @keyframes spin {
        to {
          transform: rotate(360deg);
        }
      }
      .app-loading-text {
        color: #6b7280;
        font-size: 14px;
      }

      /* Fix LuckySheet toolbar icon visibility - use dark colors instead of default white/light colors */
      #luckysheet .luckysheet-wa-editor .luckysheet-icon-img-container,
      #luckysheet .luckysheet-wa-editor .iconfont,
      #luckysheet .luckysheet-wa-editor .iconfont-luckysheet,
      #luckysheet .luckysheet-wa-editor .luckysheet-icon,
      #luckysheet .luckysheet-wa-editor .luckysheet-inline-block {
        color: #333333 !important;
      }
      #luckysheet .luckysheet-wa-editor .luckysheet-toolbar-button,
      #luckysheet .luckysheet-wa-editor .luckysheet-toolbar-menu-button,
      #luckysheet .luckysheet-wa-editor .luckysheet-toolbar-button-inner-box,
      #luckysheet .luckysheet-wa-editor .luckysheet-toolbar-menu-button-inner-box {
        color: #333333 !important;
      }
      #luckysheet .luckysheet-icon-img-container {
        opacity: 1 !important;
      }
    </style>

    <script nomodule="">
      window.location.href = "https://mobyform.com/browser-not-supported.html";
    </script>
    <noscript data-n-css=""></noscript>
    <!-- modulepreload for main.ts removed - Vite generates it automatically during build -->
    <script type="module" crossorigin src="/assets/js/index-CtAGxMVZ.js"></script>
    <link rel="modulepreload" crossorigin href="/assets/vendor/vendor-utils-COFIlpNr.js">
    <link rel="modulepreload" crossorigin href="/assets/vendor/vendor-http-B9hWEOHd.js">
    <link rel="modulepreload" crossorigin href="/assets/vendor/vendor-crypto-BTlRTi5_.js">
    <link rel="stylesheet" crossorigin href="/assets/css/index-BfAK93WQ.css">
    <link rel="manifest" href="/manifest.json">
  <meta name="theme-color" content="#3b82f6">
  <meta name="background-color" content="#ffffff">
  <meta name="mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="default">
  <meta name="apple-mobile-web-app-title" content="MobyForm">
  <link rel="apple-touch-icon" href="/icons/icon-192x192.png">
  <meta name="msapplication-TileColor" content="#3b82f6">
  <meta name="msapplication-config" content="/browserconfig.xml">
</head>
  <body>
    <div id="app">
      <!-- Loading skeleton - will be replaced when Vue mounts -->
      <div class="app-loading">
        <div class="app-loading-spinner"></div>
        <div class="app-loading-text">Loading MobyForm...</div>
      </div>
    </div>
    <script>
    (function() {
      // Performance monitoring
      if ('PerformanceObserver' in window) {
        // Monitor Largest Contentful Paint
        try {
          const lcpObserver = new PerformanceObserver((list) => {
            const entries = list.getEntries();
            const lastEntry = entries[entries.length - 1];
            console.log('LCP:', lastEntry.startTime);
          });
          lcpObserver.observe({ type: 'largest-contentful-paint', buffered: true });
        } catch (e) {}

        // Monitor First Input Delay
        try {
          const fidObserver = new PerformanceObserver((list) => {
            const entries = list.getEntries();
            entries.forEach(entry => {
              console.log('FID:', entry.processingStart - entry.startTime);
            });
          });
          fidObserver.observe({ type: 'first-input', buffered: true });
        } catch (e) {}

        // Monitor Cumulative Layout Shift
        try {
          let clsValue = 0;
          const clsObserver = new PerformanceObserver((list) => {
            for (const entry of list.getEntries()) {
              if (!entry.hadRecentInput) {
                clsValue += entry.value;
              }
            }
          });
          clsObserver.observe({ type: 'layout-shift', buffered: true });
        } catch (e) {}
      }

      // Report Core Web Vitals
      window.addEventListener('load', () => {
        setTimeout(() => {
          if (window.performance && window.performance.timing) {
            const timing = window.performance.timing;
            const metrics = {
              dns: timing.domainLookupEnd - timing.domainLookupStart,
              tcp: timing.connectEnd - timing.connectStart,
              ttfb: timing.responseStart - timing.navigationStart,
              download: timing.responseEnd - timing.responseStart,
              domInteractive: timing.domInteractive - timing.navigationStart,
              domComplete: timing.domComplete - timing.navigationStart,
              loadComplete: timing.loadEventEnd - timing.navigationStart
            };
            console.log('Performance Metrics:', metrics);
          }
        }, 0);
      });
    })();
  </script>
  </body>
</html>
