Skip to content

[codex] Improve site accessibility and mobile polish#15

Merged
Radical-Coder merged 3 commits into
mainfrom
codex/site-cleanup-improvements
Jun 22, 2026
Merged

[codex] Improve site accessibility and mobile polish#15
Radical-Coder merged 3 commits into
mainfrom
codex/site-cleanup-improvements

Conversation

@Radical-Coder

@Radical-Coder Radical-Coder commented Jun 22, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds keyboard skip navigation to the home and AI App Rescue pages.
  • Optimizes proof imagery with lazy/async loading hints and hardens external target links.
  • Reworks mobile package pricing from a fixed-width table into labeled stacked rows, with root overflow containment for shadow-heavy mobile styling.
  • Replaces repeated AI App Rescue inline borders with a shared section class and documents static test helpers.

Verification

  • npm test
  • npm run check
  • git diff --check
  • rg -nP "[^\x00-\x7F]" index.html ai-app-rescue/index.html styles.css tests
  • In-app Browser QA at http://127.0.0.1:4179/ and /ai-app-rescue/ for desktop 1440x900 and mobile 390x844: page identity, nonblank render, no framework overlay, no relevant page console errors, no broken images, no horizontal overflow, home workflow segment interaction, and mobile menu interaction.

Notes

Summary by CodeRabbit

Release Notes

  • New Features

    • Added a keyboard-accessible “skip to main content” link and improved focus navigation.
    • Improved mobile menu accessibility by updating the menu label based on expanded state.
  • Bug Fixes

    • Prevented horizontal page overflow.
  • Style

    • Unified section borders with a reusable style.
    • Hardened outbound links with noopener noreferrer.
    • Optimized images for performance and updated responsive pricing table layout.
  • Tests

    • Expanded HTML/CSS contract tests for accessibility markup, image attributes, external link safety, and responsive behavior.

@coderabbitai

coderabbitai Bot commented Jun 22, 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: e80f0436-e423-4b29-af9b-64ae746965bb

📥 Commits

Reviewing files that changed from the base of the PR and between 3507213 and f92abdb.

📒 Files selected for processing (1)
  • tests/html-metadata.test.js

📝 Walkthrough

Walkthrough

Accessibility, performance, and responsive layout improvements are applied to both the home page and AI app rescue page: a skip-to-main-content link is added with matching CSS; the mobile menu gains aria-expanded animations and dynamic label updates; proof images gain lazy loading and async decoding; a .bordered-section CSS class replaces inline border styles; the mobile pricing table gains data-label-driven stacking; and outbound links receive rel="noopener noreferrer". Tests are extended to cover all changes.

Changes

Accessibility, Performance, and Responsive Layout

Layer / File(s) Summary
Skip-link accessibility: CSS and HTML wiring
styles.css, ai-app-rescue/index.html, index.html
.skip-link CSS is added (hidden by default, revealed on :focus-visible with opacity/translate transition); html overflow-x is restricted; the skip anchor is inserted at the top of both page bodies; <main> is updated to id="main-content" with tabindex="-1"; the home page header brand link is changed to /.
Mobile menu: aria-expanded animation and dynamic label
index.html, styles.css
The mobile navigation toggle gains data-menu-label attribute; a setMenuOpen helper function updates aria-expanded, toggles menu visibility, and dynamically updates the screen-reader label text. .menu-button is repositioned with absolute-centered child lines; aria-expanded="true" transforms lines via nth-child selectors to render an "X" icon with the middle line faded.
Image lazy loading and async decoding
index.html, ai-app-rescue/index.html
loading="lazy" and decoding="async" are added to proof screenshot images in both pages; decoding="async" is added to the hero command-center image in index.html.
Mobile pricing table: data-label stacking layout
index.html, styles.css
Pricing table body cells in index.html gain data-label attributes per column (Package, Range, Best for, Included); styles.css mobile breakpoint collapses the table to a single-column grid, hides the header row, and uses span::before with data-label for inline column labels; hero button widths are separated into distinct responsive rules at 560px.
Bordered-section class and external link hardening
ai-app-rescue/index.html
.bordered-section is introduced in the inline style block; the Fit, Deliverables, Risk Scan, Proof Surface, Related Work, and Book sections switch from inline border-top styles to this class; outbound Upwork, consultation, and Catalog Intelligence MVP links gain rel="noopener noreferrer".
Test coverage for all changes
tests/html-metadata.test.js, tests/public-files.test.js
Test helpers are annotated with JSDoc. New assertions added for skip-link and focusability, dynamic mobile menu label state, lazy-loading/async-decoding counts, data-label counts per pricing column, bordered-section container counts, absence of inline border-top, and target/rel hardening counts. A "shared stylesheet contracts" suite checks mobile package header accessibility and menu icon rendering. JSDoc comment added to readPublicFile helper.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~18 minutes

Possibly related PRs

  • Radical-Coder/radical-codes-site#14: Introduced the /ai-app-rescue/ static page including the responsive ledger/table structure with data-label cell markup that this PR builds upon with .bordered-section, image optimizations, and skip-link wiring.

Poem

🐇 Hop, hop, skip to the main!
A tiny link eases the strain,
Lazy images load when in sight,
No inline borders — just classes done right.
The menu animates to an X with flair,
This rabbit refactored with such care! ✨

🚥 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 summarizes the main changes: improving site accessibility and mobile user experience polish, which directly aligns with the primary objectives of the PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 codex/site-cleanup-improvements

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: a35234bcbe

ℹ️ 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 thread styles.css Outdated
Comment on lines +1362 to +1363
.package-head {
display: none;

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 Keep mobile pricing headers accessible

On viewports up to 880px, this hides the only role="columnheader" row for the package table. The replacement labels are CSS-generated via content: attr(data-label), which is not a reliable programmatic label, so screen-reader users on mobile can encounter the package values without the Package/Range/Best for/Included context. Keep the headers in the accessibility tree, or add real hidden labels inside each cell.

Useful? React with 👍 / 👎.

@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

🧹 Nitpick comments (2)
tests/html-metadata.test.js (2)

93-94: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Avoid brittle exact-count assertions for additive optimizations.

loading="lazy"/hardened-link counts are currently exact. That makes tests fail when new compliant elements are added. Use lower-bound (>=) checks unless exact cardinality is a product invariant.

Suggested test-hardening diff
-    expect(html.match(/loading="lazy"/g)).toHaveLength(5);
+    expect(html.match(/loading="lazy"/g)?.length).toBeGreaterThanOrEqual(5);

-    expect(html.match(/loading="lazy"/g)).toHaveLength(2);
-    expect(html.match(/target="_blank" rel="noopener noreferrer"/g)).toHaveLength(5);
+    expect(html.match(/loading="lazy"/g)?.length).toBeGreaterThanOrEqual(2);
+    expect(html.match(/target="_blank"\s+rel="noopener noreferrer"/g)?.length).toBeGreaterThanOrEqual(5);

Also applies to: 138-139

🤖 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 `@tests/html-metadata.test.js` around lines 93 - 94, The test assertion for
`loading="lazy"` attribute matches uses an exact count check with
toHaveLength(5) which makes the test brittle and fails when new compliant
elements are added. Change this exact count assertion to use
toBeGreaterThanOrEqual with an appropriate lower-bound value instead, similar to
how the decoding="async" check is already written. Apply the same fix pattern to
the similar exact count assertions at lines 138-139 that are also mentioned in
the comment.

91-92: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Make structural HTML assertions order-insensitive.

These checks currently depend on exact attribute/class ordering (toContain(...) and class="section-container bordered-section"), which can fail on harmless markup reformatting. Prefer regex/token-based assertions that validate presence of required attributes/classes regardless of order.

Suggested test-hardening diff
-    expect(html).toContain('class="skip-link" href="`#main-content`"');
-    expect(html).toContain('<main id="main-content" tabindex="-1">');
+    expect(html).toMatch(/<a[^>]*class=["'][^"']*\bskip-link\b[^"']*["'][^>]*href=["']`#main-content`["'][^>]*>/i);
+    expect(html).toMatch(/<main[^>]*id=["']main-content["'][^>]*tabindex=["']-1["'][^>]*>/i);

-    expect(html).toContain('class="skip-link" href="`#main-content`"');
-    expect(html).toContain('<main id="main-content" tabindex="-1">');
+    expect(html).toMatch(/<a[^>]*class=["'][^"']*\bskip-link\b[^"']*["'][^>]*href=["']`#main-content`["'][^>]*>/i);
+    expect(html).toMatch(/<main[^>]*id=["']main-content["'][^>]*tabindex=["']-1["'][^>]*>/i);
-    expect(html.match(/class="section-container bordered-section/g)).toHaveLength(6);
+    expect(html.match(/class=["'][^"']*\bsection-container\b[^"']*\bbordered-section\b[^"']*["']/g)?.length).toBe(6);

Also applies to: 134-137

🤖 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 `@tests/html-metadata.test.js` around lines 91 - 92, The test assertions in the
expect statements on lines 91-92 use toContain with exact string matching,
making them fragile to harmless attribute reordering in the HTML output. Replace
these exact string match assertions with regex-based or token-based assertions
that validate the presence of required attributes and classes (such as
class="skip-link", href="`#main-content`", id="main-content", and tabindex="-1")
without depending on their specific order within the HTML elements. Apply the
same fix to the similar assertions mentioned at lines 134-137 to ensure all
structural HTML assertions are order-insensitive.
🤖 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 `@styles.css`:
- Around line 1362-1364: The .package-head class currently uses display: none
which removes the columnheader row from the accessibility tree, making it
inaccessible to assistive technologies. Replace display: none with a CSS
technique that visually hides the element while keeping it in the accessibility
tree, such as using position: absolute with off-screen positioning, clip-path:
inset(100%), or a standard screen-reader-only hiding pattern. This preserves the
structural header context for mobile table cells while maintaining visual
design.

---

Nitpick comments:
In `@tests/html-metadata.test.js`:
- Around line 93-94: The test assertion for `loading="lazy"` attribute matches
uses an exact count check with toHaveLength(5) which makes the test brittle and
fails when new compliant elements are added. Change this exact count assertion
to use toBeGreaterThanOrEqual with an appropriate lower-bound value instead,
similar to how the decoding="async" check is already written. Apply the same fix
pattern to the similar exact count assertions at lines 138-139 that are also
mentioned in the comment.
- Around line 91-92: The test assertions in the expect statements on lines 91-92
use toContain with exact string matching, making them fragile to harmless
attribute reordering in the HTML output. Replace these exact string match
assertions with regex-based or token-based assertions that validate the presence
of required attributes and classes (such as class="skip-link",
href="`#main-content`", id="main-content", and tabindex="-1") without depending on
their specific order within the HTML elements. Apply the same fix to the similar
assertions mentioned at lines 134-137 to ensure all structural HTML assertions
are order-insensitive.
🪄 Autofix (Beta)

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: 410eff62-d4fb-4814-ad34-c39da41bccac

📥 Commits

Reviewing files that changed from the base of the PR and between 83dadc2 and a35234b.

📒 Files selected for processing (5)
  • ai-app-rescue/index.html
  • index.html
  • styles.css
  • tests/html-metadata.test.js
  • tests/public-files.test.js

Comment thread styles.css

@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

🧹 Nitpick comments (1)
tests/html-metadata.test.js (1)

167-170: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Assert media-block extraction explicitly before content checks.

mobileBlock can be undefined; adding an explicit existence assertion makes failures clearer and avoids opaque matcher errors.

Suggested diff
-    const mobileBlock = css.match(/@media \(max-width: 880px\) \{[\s\S]*?`@media` \(max-width: 560px\)/)?.[0];
+    const mobileBlockMatch = css.match(/@media \(max-width: 880px\) \{[\s\S]*?`@media` \(max-width: 560px\)/);
+    expect(mobileBlockMatch).not.toBeNull();
+    const mobileBlock = mobileBlockMatch?.[0] ?? "";
🤖 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 `@tests/html-metadata.test.js` around lines 167 - 170, The variable mobileBlock
can be undefined if the regex match in the `@media` query fails, which causes
subsequent expect statements to fail with unclear error messages. Add an
explicit assertion immediately after the mobileBlock assignment to verify that
mobileBlock is defined before proceeding with the content checks (toContain,
toMatch calls). This will provide a clearer failure message if the media block
extraction fails, rather than letting the matcher errors mask the real problem.
🤖 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 `@tests/html-metadata.test.js`:
- Around line 155-159: The test assertions for bordered-section classes and
external-link attributes currently depend on specific attribute/class ordering.
Replace the regex pattern checking for both section-container and
bordered-section classes (which assumes section-container appears first) with
separate assertions that check for each class independently regardless of order.
Similarly, replace the regex pattern matching target="_blank" followed by
rel="noopener noreferrer" (which assumes target comes first) with a different
approach that verifies both attributes exist without depending on their relative
position, such as checking for each attribute separately or using a more
flexible pattern that allows any order.

---

Nitpick comments:
In `@tests/html-metadata.test.js`:
- Around line 167-170: The variable mobileBlock can be undefined if the regex
match in the `@media` query fails, which causes subsequent expect statements to
fail with unclear error messages. Add an explicit assertion immediately after
the mobileBlock assignment to verify that mobileBlock is defined before
proceeding with the content checks (toContain, toMatch calls). This will provide
a clearer failure message if the media block extraction fails, rather than
letting the matcher errors mask the real problem.
🪄 Autofix (Beta)

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: 94478172-a70e-45dc-98a8-a7e28f4c48b4

📥 Commits

Reviewing files that changed from the base of the PR and between a35234b and 3507213.

📒 Files selected for processing (3)
  • index.html
  • styles.css
  • tests/html-metadata.test.js

Comment thread tests/html-metadata.test.js Outdated
@Radical-Coder Radical-Coder merged commit 8958fc8 into main Jun 22, 2026
1 check passed
@Radical-Coder Radical-Coder deleted the codex/site-cleanup-improvements branch June 22, 2026 20:56
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