Skip to content

fix(ops): live checks assert the deployed footer tap-target rule (WCAG 2.2, PR #22 follow-up) - #110

Merged
nish3451 merged 12 commits into
mainfrom
fix/live-footer-tap-target-detection
Aug 19, 2026
Merged

fix(ops): live checks assert the deployed footer tap-target rule (WCAG 2.2, PR #22 follow-up)#110
nish3451 merged 12 commits into
mainfrom
fix/live-footer-tap-target-detection

Conversation

@nish3451

@nish3451 nish3451 commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

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

  • PR fix(public): bring footer links up to WCAG 2.2 24px tap targets #22 (2026-08-09) fixed exactly this: public/styles.css .footer-links a is now an inline-block with min-height: 24px and 4px 0 vertical padding (~34px rendered hit area), and every footer link on all 13 public pages sits inside .footer-links.
  • PR fix(public): bring in-content links up to WCAG 2.2 24px tap targets #25 renamed/expanded the regression test to scripts/test-public-link-targets.mjs, wired into npm test and npm run ci.
  • Verified in this worktree: node scripts/test-public-link-targets.mjs77 checks, 0 failures; section D proves every footer link on every public page is a .footer-links link; 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

  • The live tinystudio.in still serves the June-20-era bundle (pre-fix(public): bring footer links up to WCAG 2.2 24px tap targets #22): its /styles.css .footer-links a is 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.
  • The deploy lane (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 and fix/lane1-deploy-lane-dormant-until-pages-token).

This PR

Adds the missing detector: the same assertions test-public-link-targets.mjs runs 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 --check both scripts — OK
  • SKIP_LIVE_CHECKS=1 gates exit 0 — OK
  • node scripts/test-public-link-targets.mjs — 77 checks, 0 failures
  • npm run site:check-live and node scripts/check-public-live-deploy.mjs vs live — section E fails on the stale bundle exactly as intended (documented red state)
  • git diff --check — clean

Note: full npm test additionally fails on an unrelated pre-existing environment check (check-retention-automation points at a local automation.toml path outside this repo); it is not touched by or related to this change.

Summary by CodeRabbit

  • Accessibility

    • Footer-link styling is checked against WCAG 2.2 tap-target requirements, including minimum size, spacing, and block-level presentation.
  • Quality Improvements

    • Deployment checks now detect missing, outdated, or inaccessible footer-link styling before release.
    • Improved failure guidance makes live-site accessibility issues easier to identify and resolve.

…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

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4b8a9830-fd72-4d2d-b79f-42e5c9334937

📥 Commits

Reviewing files that changed from the base of the PR and between 3749993 and 06e28ab.

📒 Files selected for processing (1)
  • scripts/check-public-live-deploy.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/check-public-live-deploy.mjs

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.


📝 Walkthrough

Walkthrough

The live deployment and soft-404 checks now fetch /styles.css and validate the .footer-links a WCAG tap-target rule. They require a successful response, block-level display, min-height: 24px, and at least 4px vertical padding.

Changes

Footer accessibility validation

Layer / File(s) Summary
Deployment stylesheet check
scripts/check-public-live-deploy.mjs
The deployment check documents and validates the deployed .footer-links a rule in /styles.css.
Soft-404 stylesheet check
scripts/check-public-live-soft-404.mjs
The soft-404 check fetches /styles.css, validates the footer link tap-target declarations, and reports missing accessibility styling.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 06e28

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)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the live-check changes for the deployed footer tap-target rule.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/live-footer-tap-target-detection

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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*\{([^}]*)\}/)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +119 to +123
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])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4be12e3 and 691b775.

📒 Files selected for processing (2)
  • scripts/check-public-live-deploy.mjs
  • scripts/check-public-live-soft-404.mjs

Comment on lines +100 to +111
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`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +116 to +119
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")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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*\{([^}]*)\}/)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@nish3451

Copy link
Copy Markdown
Collaborator Author

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 scripts/check-public-live-deploy.mjs: #123 (Cloudflare email, merged), #127 (JSON-LD coverage, merged), plus #110, #97, #154 and this one. Because they all insert at the same place, each merge re-conflicts every PR still waiting. I resolved this branch once (kept main's sections, relabelled the footer tap-target stylesheet check to the next free letter, re-ran the check suite green), and it went conflicting again when #127 landed minutes later.

Effort to land: small but strictly serial. The conflict is one hunk, always the same shape — keep main's sections, bump this branch's section letter, done. It just has to be redone after each sibling merges. Expect one rebase per remaining sibling.

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 main, and passed the repo check chain when I last resolved it.

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.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your trial has ended. Reactivate Greptile to resume code reviews.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@nish3451
nish3451 merged commit 16840db into main Aug 19, 2026
3 of 4 checks passed
nish3451 added a commit that referenced this pull request Aug 19, 2026
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant