fix(ops): live checks assert the deployed footer tap-target rule (WCAG 2.2, PR #22 follow-up) - #110
Conversation
…ap-target rule The repo has carried the WCAG 2.2 24px footer tap-target fix since PR #22 (styles.css .footer-links a is an inline-block with min-height 24px and 4px vertical padding, regression-tested by test-public-link-targets.mjs), but neither live-verification script inspected the DEPLOYED stylesheet. A stale bundle therefore sails through both the nightly live-site net and the deploy acceptance proof with no signal - which is how the mobile footer tap-target audit finding kept coming back despite the fix being merged. Add the same assertions test-public-link-targets.mjs runs against the repo stylesheet, against /styles.css on the live site: - scripts/check-public-live-soft-404.mjs (nightly net): section E - scripts/check-public-live-deploy.mjs (deploy acceptance): proof #5 Against the current live site (June-20 era bundle, deploy lane dormant until a Cloudflare Pages token is provisioned) both now fail loudly with the exact cause: the deployed .footer-links a rule is a plain inline box without min-height or padding. Once the lane resumes, any publish that drops the rule fails the post-deploy proof instead of silently shipping a regression. verify: node --check scripts/check-public-live-soft-404.mjs && node --check scripts/check-public-live-deploy.mjs; SKIP_LIVE_CHECKS=1 npm run site:check-live (exit 0); SKIP_LIVE_CHECKS=1 node scripts/check-public-live-deploy.mjs (exit 0); node scripts/test-public-link-targets.mjs (77 checks, 0 failures); npm run site:check-live and node scripts/check-public-live-deploy.mjs against live fail section E with the expected stale-bundle cause; git diff --check
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Included review availability: 1 review is currently available. Your included PR review attempts over the past 7 days set your current allowance at 3 reviews per hour. 📝 WalkthroughWalkthroughThe live deployment and soft-404 checks now fetch ChangesFooter accessibility validation
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to This localized change adds checks that detect whether the deployed footer tap-target rule matches the repository requirement. No actionable merge-blocking risk remains beyond normal checks and review. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6df1690c5f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // stylesheet, so a stale bundle that loses the PR #22 rule fails loudly. | ||
| console.log("E. the deployed stylesheet keeps the WCAG 2.2 24px footer tap-target rule (PR #22)") | ||
| ok(cssRes.status === 200, `GET /styles.css returns HTTP ${cssRes.status}`) | ||
| const footerRule = cssBody.match(/\.footer-links\s*a\s*\{([^}]*)\}/) |
There was a problem hiding this comment.
Inspect all applicable footer rules
Both new live checks use match(), so they validate only the first .footer-links a declaration. If a later rule—especially a mobile @media override—sets display: inline, min-height: 0, or removes the padding, the CSS cascade makes the deployed mobile tap target undersized while every assertion here and in check-public-live-deploy.mjs still passes. Check the effective/final declarations or reject conflicting later rules.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a1cd94f7d4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ok(/min-height:\s*24px/.test(rule), ".footer-links a declares min-height: 24px") | ||
| const padding = rule.match(/padding:\s*([^;]+)/) | ||
| ok(padding !== null, ".footer-links a declares vertical padding") | ||
| if (padding) { | ||
| const vertical = parseFloat(padding[1].trim().split(/\s+/)[0]) |
There was a problem hiding this comment.
Require exact CSS units before passing the live check
If a deployed rule contains malformed values such as min-height: 24pxfoo; padding: 4, the browser discards both declarations, but the prefix regex and parseFloat still accept them. When the inherited line height is below 24px, both this live check and its duplicated deploy/static logic therefore report success while the effective tap target remains undersized; validate complete CSS tokens and require valid pixel units.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/check-public-live-deploy.mjs`:
- Around line 100-111: Replace the first-match footerRule checks in the live
validation flow of scripts/check-public-live-deploy.mjs (lines 100-111) with a
shared cascade-aware CSS validator that computes the effective .footer-links a
styles across later declarations and conditional rules. Update
scripts/check-public-live-soft-404.mjs (lines 113-124) to reuse this same
validator and evaluate the effective deployed rule, preserving all existing
display, min-height, and padding requirements.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 75a7ce89-e377-43f6-aedb-ff4f3ce2c870
📒 Files selected for processing (2)
scripts/check-public-live-deploy.mjsscripts/check-public-live-soft-404.mjs
| const footerRule = body.match(/\.footer-links\s*a\s*\{([^}]*)\}/) | ||
| ok(footerRule !== null, "deployed stylesheet has a .footer-links a rule") | ||
| if (footerRule) { | ||
| const rule = footerRule[1] | ||
| ok(/display:\s*(inline-block|inline-flex|block)/.test(rule), ".footer-links a is a block-level box (hit area covers the line box)") | ||
| ok(!/display:\s*inline\s*;/.test(rule), ".footer-links a is not a plain inline box") | ||
| ok(/min-height:\s*24px/.test(rule), ".footer-links a declares min-height: 24px") | ||
| const padding = rule.match(/padding:\s*([^;]+)/) | ||
| ok(padding !== null, ".footer-links a declares vertical padding") | ||
| if (padding) { | ||
| const vertical = parseFloat(padding[1].trim().split(/\s+/)[0]) | ||
| ok(vertical >= 4, `.footer-links a vertical padding is at least 4px (${vertical}px), so 16px text + padding >= 24px`) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
Use one cascade-aware validator for both live checks. Both implementations inspect only the first matching text block, so later declarations or conditional rules can invalidate the effective footer styles without failing the checks.
scripts/check-public-live-deploy.mjs#L100-L111: replace the first-match regex validation with cascade-aware CSS validation.scripts/check-public-live-soft-404.mjs#L113-L124: reuse the same validator and evaluate the effective deployed rule.
📍 Affects 2 files
scripts/check-public-live-deploy.mjs#L100-L111(this comment)scripts/check-public-live-soft-404.mjs#L113-L124
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/check-public-live-deploy.mjs` around lines 100 - 111, Replace the
first-match footerRule checks in the live validation flow of
scripts/check-public-live-deploy.mjs (lines 100-111) with a shared cascade-aware
CSS validator that computes the effective .footer-links a styles across later
declarations and conditional rules. Update
scripts/check-public-live-soft-404.mjs (lines 113-124) to reuse this same
validator and evaluate the effective deployed rule, preserving all existing
display, min-height, and padding requirements.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8366a998c1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const rule = footerRule[1] | ||
| ok(/display:\s*(inline-block|inline-flex|block)/.test(rule), ".footer-links a is a block-level box (hit area covers the line box)") | ||
| ok(!/display:\s*inline\s*;/.test(rule), ".footer-links a is not a plain inline box") | ||
| ok(/min-height:\s*24px/.test(rule), ".footer-links a declares min-height: 24px") |
There was a problem hiding this comment.
Strip CSS comments before validating declarations
If the footer declarations are commented out—for example, /* display: inline-block; min-height: 24px; padding: 4px 0; */—all of these positive checks still match the comment while the negative inline check also passes, even though the browser applies none of the declarations and the link remains inline. Strip comments or parse the declaration block as CSS before running these assertions; the duplicated deploy check has the same issue.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9bba2d3e04
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| { | ||
| const { status, body } = await get("/styles.css") | ||
| ok(status === 200, `GET /styles.css returns 200 (got ${status})`) | ||
| const footerRule = body.match(/\.footer-links\s*a\s*\{([^}]*)\}/) |
There was a problem hiding this comment.
Reject ancestor-scoped footer rules
If the deployed stylesheet scopes this declaration beneath another selector, such as .homepage .footer-links a { ... }, the unanchored regex starts matching at .footer-links and every assertion passes. Footer links on pages outside that ancestor remain undersized even though this acceptance proof claims coverage on every page; validate the complete selector list and require an unscoped .footer-links a selector.
Useful? React with 👍 / 👎.
…arget-detection # Conflicts: # scripts/check-public-live-deploy.mjs
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
PR #123 landed its own section E (Cloudflare email obfuscation) in check-public-live-deploy.mjs. Kept both checks and relabelled this branch footer tap-target section from E to F.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
|
Rebased during the backlog sweep, then knocked back into conflict again — this is a structural issue with the cluster, not a problem with this PR. What happened. Five PRs each append a new lettered proof section to the same function in Effort to land: small but strictly serial. The conflict is one hunk, always the same shape — keep Suggested order so each PR is rebased exactly once: #110, then #97, then #154, then #118. Landing them back to back is much cheaper than landing them days apart. Nothing here is stale — this branch's check is real, absent from |
Automated conflict resolution during the PR backlog sweep: kept main's side of every shared block, re-applied this branch's unique additions on top (package scripts re-inserted into main's chains; live-check sections relabelled to the next free letter). Repo check chain re-run green before push.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
check-public-live-deploy.mjs now carries sections A-G on main (E Cloudflare email #123, F JSON-LD #127, G footer tap-targets #110). Rather than resolve the overlapping hunks by hand, this takes main file verbatim and grafts this branch shared-footer copy proof onto it as section H. Repo check chain green.
What this item was
Queue item: "Mobile tap targets fall below the WCAG 2.2 24px minimum on every tinystudio.in page - footer" (unreviewed-by-grok, opened 2026-08-11/12).
Investigation result: the code fix already exists on main
public/styles.css.footer-links ais now an inline-block withmin-height: 24pxand4px 0vertical padding (~34px rendered hit area), and every footer link on all 13 public pages sits inside.footer-links.scripts/test-public-link-targets.mjs, wired intonpm testandnpm run ci.node scripts/test-public-link-targets.mjs→ 77 checks, 0 failures; section D proves every footer link on every public page is a.footer-linkslink; the repo stylesheet passes all four rule assertions (block-level box,min-height: 24px, vertical padding ≥ 4px).Why the audit kept flagging it: the live site is stale, and nothing detected that
/styles.css.footer-links ais a plain inline box with no min-height/padding (confirmed by fetching https://tinystudio.in/styles.css). The nightly live-site check is already red on that staleness (soft-404s), but neither live-verification script looked at the stylesheet, so the specific a11y regression produced no signal.deploy-public-site.yml) has failed every run since 2026-08-11 and is documented as dormant until a Cloudflare Pages API token with Pages:Edit is provisioned (one-time dashboard step, credentials outside repo scope; see workflow comment andfix/lane1-deploy-lane-dormant-until-pages-token).This PR
Adds the missing detector: the same assertions
test-public-link-targets.mjsruns against the repo stylesheet, run against the deployed/styles.css.scripts/check-public-live-soft-404.mjs(nightly net): new section E.scripts/check-public-live-deploy.mjs(deploy acceptance proof): new proof Add TinyStudio HSTS Pages header #5.Against the current live site both now fail loudly with the exact cause ("deployed .footer-links a rule is a plain inline box..."). When the deploy lane resumes with a Pages token, the post-deploy proof will verify the tap-target rule is actually live; a future bundle that drops the rule fails the deploy instead of shipping silently.
Verify
node --checkboth scripts — OKSKIP_LIVE_CHECKS=1gates exit 0 — OKnode scripts/test-public-link-targets.mjs— 77 checks, 0 failuresnpm run site:check-liveandnode scripts/check-public-live-deploy.mjsvs live — section E fails on the stale bundle exactly as intended (documented red state)git diff --check— cleanNote: full
npm testadditionally fails on an unrelated pre-existing environment check (check-retention-automationpoints at a local automation.toml path outside this repo); it is not touched by or related to this change.Summary by CodeRabbit
Accessibility
Quality Improvements