From b34e3958f8648c1eef66e93f457cbee1b1d80198 Mon Sep 17 00:00:00 2001 From: nish3451 <257724087+nish3451@users.noreply.github.com> Date: Tue, 11 Aug 2026 22:41:16 +0530 Subject: [PATCH] fix(public): put a real Request-the-appraisal signup form in the /pricing closing callout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pricing page's closing band — "The appraisal costs you an email. The rest is a decision you can make later." — ended in a dead end: no intake form, no action, nothing to click, while every other served conversion surface (home, /audit) carried a real signup form. The band now embeds the same form.lead.two intake (website + email posting to /api/signups) with a "Request the appraisal" submit, matching the audit page's field shapes and persistent aria-labels, so the closing offer is actionable in place instead of bouncing the reader back to the nav. A static source guard in check-site.mjs pins the shape: the band must keep a form.lead posting to /api/signups, both intake inputs must carry a persistent programmatic aria-label, and the submit must read "Request the appraisal" — so the dead end cannot silently return. verify: npm run check and npm test (check, heading hierarchy, sitemap, worker, UI contracts) all green on this branch. Supersedes PR #68 (same fix, fresh branch from current origin/main so the governed review pipeline can land it). --- public/pricing.html | 5 +++++ scripts/check-site.mjs | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/public/pricing.html b/public/pricing.html index 38f21d64..5e513b12 100644 --- a/public/pricing.html +++ b/public/pricing.html @@ -129,6 +129,11 @@

Before you ask

The appraisal costs you an email. The rest is a decision you can make later.

Six a month, done by hand. When this month's sixth is taken the intake closes until the next one opens.

+
+ + + +
No revenue, ranking, ROAS, conversion, booked-call or sales-volume guarantees. The delivery guarantee above is the only promise we make about outcomes, and it is a promise about our work, not your market.
diff --git a/scripts/check-site.mjs b/scripts/check-site.mjs index 221cb2e8..8d707d36 100644 --- a/scripts/check-site.mjs +++ b/scripts/check-site.mjs @@ -274,6 +274,33 @@ if (!retiredDesk.includes("role=\"tabpanel\"") || !retiredDesk.includes("aria-la failures.push("Agent output must expose a proper tabpanel relationship."); } +// Pricing closing-callout regression (Grok finding: the /pricing closing band +// ended in a dead end — "The appraisal costs you an email" with no way to send +// one — while every other served conversion surface carried a real intake +// form). The band must keep the actual signup form: a form.lead inside the +// .band posting website + email to /api/signups, both fields with a +// persistent programmatic aria-label, and a submit button reading "Request +// the appraisal". STATIC SOURCE GUARD (regex over pricing.html), matching the +// repo's other source-string guards. +const sitePricing = read("public/pricing.html"); +const pricingBand = sitePricing.match(/
([\s\S]*?)<\/div>\s*
/)?.[1] ?? ""; +const pricingForm = pricingBand.match(/]*class="lead[^>]*"[^>]*>[\s\S]*?<\/form>/i)?.[0] ?? ""; + +if (!pricingForm || !pricingForm.includes('action="/api/signups"') || !pricingForm.includes('method="post"')) { + failures.push("Pricing closing callout must carry the real signup form (form.lead posting website + email to /api/signups) so the appraisal ask is actionable in place."); +} +for (const input of pricingForm.matchAll(/]*>/gi)) { + const tag = input[0]; + if (!/\bname="(?:website|email)"/.test(tag)) continue; + const aria = tag.match(/\baria-label="([^"]*)"/)?.[1] ?? ""; + if (!aria.trim()) { + failures.push(`Pricing intake input must carry a persistent programmatic aria-label (placeholder-only labels disappear as buyers type): ${tag}`); + } +} +if (!/Request the appraisal/i.test(pricingForm)) { + failures.push('Pricing closing callout submit button must read "Request the appraisal".'); +} + // Mobile layout regression: at 390x844 the /audit page previously overflowed // horizontally (navlinks measured to x=569, the 53-of-89 stat to x=451). // The mobile treatment must live in audit.css behind the shared 760px