From 9580a78b78f8ac86c61e6ba8ebce2393b898a9da Mon Sep 17 00:00:00 2001
From: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
Date: Tue, 7 Jul 2026 19:23:53 +0000
Subject: [PATCH 1/3] =?UTF-8?q?feat:=20implement=20issue=20#429=20?=
 =?UTF-8?q?=E2=80=94=20SonarCloud:=20miscellaneous=20findings?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 deploy/index.html              |  2 +-
 deploy/tests/ui.spec.js        | 30 ++++++++++++++++++++++++++++++
 gas-installer/Index.html       |  2 +-
 gas-installer/tests/ui.spec.js | 30 ++++++++++++++++++++++++++++++
 4 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/deploy/index.html b/deploy/index.html
index 323453b8..1fac2f82 100644
--- a/deploy/index.html
+++ b/deploy/index.html
@@ -184,7 +184,7 @@
       }
       .status-info {
         background: #e8f0fe;
-        color: #1a73e8;
+        color: #1765cc;
       }
       .status-ok {
         background: #e6f4ea;
diff --git a/deploy/tests/ui.spec.js b/deploy/tests/ui.spec.js
index c627953a..ede7858f 100644
--- a/deploy/tests/ui.spec.js
+++ b/deploy/tests/ui.spec.js
@@ -1290,6 +1290,36 @@ test.describe('deploy index.html', () => {
     await expect(page.locator('#status-msg.status-error')).toBeVisible()
   })
 
+  test('status-info banner meets WCAG AA contrast (>= 4.5:1)', async ({
+    page,
+  }) => {
+    const contrast = await page.evaluate(() => {
+      const el = document.createElement('div')
+      el.className = 'status-msg status-info'
+      el.textContent = 'sample'
+      document.body.appendChild(el)
+      const cs = getComputedStyle(el)
+      const fg = cs.color
+      const bg = cs.backgroundColor
+      el.remove()
+
+      const channels = (s) => s.match(/\d+(\.\d+)?/g).map(Number)
+      const luminance = ([r, g, b]) => {
+        const lin = [r, g, b].map((v) => {
+          v /= 255
+          return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4)
+        })
+        return 0.2126 * lin[0] + 0.7152 * lin[1] + 0.0722 * lin[2]
+      }
+      const l1 = luminance(channels(fg))
+      const l2 = luminance(channels(bg))
+      const lighter = Math.max(l1, l2)
+      const darker = Math.min(l1, l2)
+      return (lighter + 0.05) / (darker + 0.05)
+    })
+    expect(contrast).toBeGreaterThanOrEqual(4.5)
+  })
+
   test('successful deploy shows status-ok class', async ({ page }) => {
     await mockSuccessfulDeploy(page)
     await signIn(page)
diff --git a/gas-installer/Index.html b/gas-installer/Index.html
index f660ace0..84f1b3b0 100644
--- a/gas-installer/Index.html
+++ b/gas-installer/Index.html
@@ -168,7 +168,7 @@
       }
       .status-info {
         background: #e8f0fe;
-        color: #1a73e8;
+        color: #1765cc;
       }
       .status-ok {
         background: #e6f4ea;
diff --git a/gas-installer/tests/ui.spec.js b/gas-installer/tests/ui.spec.js
index d1418e82..37f74e2a 100644
--- a/gas-installer/tests/ui.spec.js
+++ b/gas-installer/tests/ui.spec.js
@@ -205,6 +205,36 @@ test.describe('gas-installer Index.html', () => {
     await expect(page.locator('#status-msg.status-info')).toBeVisible()
   })
 
+  test('status-info banner meets WCAG AA contrast (>= 4.5:1)', async ({
+    page,
+  }) => {
+    const contrast = await page.evaluate(() => {
+      const el = document.createElement('div')
+      el.className = 'status-msg status-info'
+      el.textContent = 'sample'
+      document.body.appendChild(el)
+      const cs = getComputedStyle(el)
+      const fg = cs.color
+      const bg = cs.backgroundColor
+      el.remove()
+
+      const channels = (s) => s.match(/\d+(\.\d+)?/g).map(Number)
+      const luminance = ([r, g, b]) => {
+        const lin = [r, g, b].map((v) => {
+          v /= 255
+          return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4)
+        })
+        return 0.2126 * lin[0] + 0.7152 * lin[1] + 0.0722 * lin[2]
+      }
+      const l1 = luminance(channels(fg))
+      const l2 = luminance(channels(bg))
+      const lighter = Math.max(l1, l2)
+      const darker = Math.min(l1, l2)
+      return (lighter + 0.05) / (darker + 0.05)
+    })
+    expect(contrast).toBeGreaterThanOrEqual(4.5)
+  })
+
   test('showStatus ok applies status-ok class', async ({ page }) => {
     await page.locator('#script-gmail').click()
     await page.fill('#project-title', 'My Project')

From e25540cc0d64616896807a3a8a2ffd7a9850f8a2 Mon Sep 17 00:00:00 2001
From: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
Date: Tue, 7 Jul 2026 19:27:19 +0000
Subject: [PATCH 2/3] fix(reviews): address review comments [skip ci-relay]

---
 deploy/tests/ui.spec.js        | 2 +-
 gas-installer/tests/ui.spec.js | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/deploy/tests/ui.spec.js b/deploy/tests/ui.spec.js
index ede7858f..3a518644 100644
--- a/deploy/tests/ui.spec.js
+++ b/deploy/tests/ui.spec.js
@@ -1303,7 +1303,7 @@ test.describe('deploy index.html', () => {
       const bg = cs.backgroundColor
       el.remove()
 
-      const channels = (s) => s.match(/\d+(\.\d+)?/g).map(Number)
+      const channels = (s) => (s.match(/\d+(\.\d+)?/g) || []).map(Number)
       const luminance = ([r, g, b]) => {
         const lin = [r, g, b].map((v) => {
           v /= 255
diff --git a/gas-installer/tests/ui.spec.js b/gas-installer/tests/ui.spec.js
index 37f74e2a..899d5620 100644
--- a/gas-installer/tests/ui.spec.js
+++ b/gas-installer/tests/ui.spec.js
@@ -218,7 +218,7 @@ test.describe('gas-installer Index.html', () => {
       const bg = cs.backgroundColor
       el.remove()
 
-      const channels = (s) => s.match(/\d+(\.\d+)?/g).map(Number)
+      const channels = (s) => (s.match(/\d+(\.\d+)?/g) || []).map(Number)
       const luminance = ([r, g, b]) => {
         const lin = [r, g, b].map((v) => {
           v /= 255

From 7e4096ff1271c55133da5a6705970fe17c26a4bb Mon Sep 17 00:00:00 2001
From: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com>
Date: Tue, 7 Jul 2026 19:31:27 +0000
Subject: [PATCH 3/3] fix(bot): address bot feedback [skip ci-relay]

---
 deploy/tests/ui.spec.js        | 3 ++-
 gas-installer/tests/ui.spec.js | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/deploy/tests/ui.spec.js b/deploy/tests/ui.spec.js
index 3a518644..8001ba55 100644
--- a/deploy/tests/ui.spec.js
+++ b/deploy/tests/ui.spec.js
@@ -1303,7 +1303,8 @@ test.describe('deploy index.html', () => {
       const bg = cs.backgroundColor
       el.remove()
 
-      const channels = (s) => (s.match(/\d+(\.\d+)?/g) || []).map(Number)
+      const channels = (s) =>
+        ((s || '').match(/\d+(\.\d+)?/g) || []).map(Number)
       const luminance = ([r, g, b]) => {
         const lin = [r, g, b].map((v) => {
           v /= 255
diff --git a/gas-installer/tests/ui.spec.js b/gas-installer/tests/ui.spec.js
index 899d5620..5d63894f 100644
--- a/gas-installer/tests/ui.spec.js
+++ b/gas-installer/tests/ui.spec.js
@@ -218,7 +218,8 @@ test.describe('gas-installer Index.html', () => {
       const bg = cs.backgroundColor
       el.remove()
 
-      const channels = (s) => (s.match(/\d+(\.\d+)?/g) || []).map(Number)
+      const channels = (s) =>
+        ((s || '').match(/\d+(\.\d+)?/g) || []).map(Number)
       const luminance = ([r, g, b]) => {
         const lin = [r, g, b].map((v) => {
           v /= 255
