Pairing screen shows garbled text

I’m pretty new to Homey app development and ran into a weird issue. I’m building a driver for a WiFi smart bulb, and in the pairing flow I’m only using fields — no custom template. The pairing screen does show up in the Homey mobile app, but the text looks totally garbled or unreadable. I double-checked my JSON structure and everything seems fine. Anyone know what might be causing this? Could it be encoding or something else? Appreciate any tips!

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>Enter WiFi Bulb Info</title>
  <script src="/homey.js" data-origin="settings"></script>
</head>

<body>
  <h1>Enter WiFi Bulb Information</h1>

  <homey-text id="bulb_ip" label="Bulb IP" placeholder="192.168.1.100"></homey-text>
  <homey-number id="bulb_port" label="Port" value="80"></homey-number>

  <button id="save">Save</button>

  <script>
    document.getElementById('save').addEventListener('click', () => {
      Homey.emit('save', {
        bulb_ip: Homey.getValue('bulb_ip'),
        bulb_port: Homey.getValue('bulb_port')
      }).then(() => Homey.done());
    });
  </script>
</body>

</html>
{
  "id": "wifi-light-v2",
  "name": {
    "en": "WiFi Smart Bulb v2"
  },
  "class": "light",
  "capabilities": [
    "dim",
    "onoff"
  ],
  "platforms": [
    "local"
  ],
  "connectivity": [
    "lan"
  ],
  "pair": [
    {
      "id": "enter-credentials",
      "name": {
        "en": "Enter Info"
      },
      "description": {
        "en": "Please enter IP and Port"
      },
      "fields": [
        {
          "id": "bulb_ip",
          "type": "text",
          "required": true
        },
        {
          "id": "bulb_port",
          "type": "number",
          "required": true,
          "default": 80
        }
      ]
    }
  ]
}

Does this happen on an actual mobile device, or are you running it inside an emulator? Seems like a local issue to me.

I’ve tested it both on a real mobile device and inside an emulator — the issue appears in both environments.

Are you using something like AdGuard or PiHole in your network?

I’m not using AdGuard or Pi-hole in my network, at least not intentionally.
However, I noticed that some files appear with a lock icon, which makes me suspect there might be encryption or access control involved.
Could this be affecting the pairing process?

It could, but I have no idea how that could happen.

Thanks for the help! I figured out the issue — it was related to Windows file encryption.
Some files had a lock icon and were likely being encrypted or restricted by the system.
I solved it by pushing the code to Git and pulling it into Ubuntu via WSL, which bypassed the encryption.
Still learning, but this was a good lesson!