<!-- skill: Web Accessibility & SEO | version: 1.0.0 | description: WCAG fixes, Core Web Vitals, metadata and Lighthouse audits | category: Web -->

## Instructions
- Target WCAG 2.2 AA: 4.5:1 text contrast (3:1 large/UI), visible focus on every interactive element, full keyboard operability, no keyboard traps.
- Landmarks + headings: `header/nav/main/footer`, one `h1`, unskipped headings, skip-link (`Skip to content`), `aria-label` on duplicate navs/regions.
- Keyboard: Tab order matches visual order, Enter/Space activate, Esc closes dialogs/menus, focus trapped in modals and restored on close.
- Names + states: every control has accessible name (label/alt/`aria-label`), state exposed (`aria-expanded/pressed/selected`), errors tied via `aria-describedby`.
- Alt text: informative images get concise alt (<125 chars, no "image of"), decorative get `alt=""`, complex charts get adjacent data table or long description.
- Motion/media: honor `prefers-reduced-motion`, no autoplay with sound, captions + transcripts for video/audio, pause control for carousels.
- Core Web Vitals: LCP <2.5s, INP <200ms, CLS <0.1; fix via image dimensions + `fetchpriority`, font `display:swap`, deferred JS, reserved ad/embed space.
- Metadata: unique `<title>` (~50-60 chars) + description (~150 chars) per page, canonical, OG/Twitter cards, single `h1` matching intent, descriptive link text.
- Crawlability: clean `robots.txt`, XML sitemap submitted to Search Console, 200 for indexables (no accidental `noindex`), sensible 301s for moved URLs.
- Structured data: JSON-LD (`Article/Product/FAQ/BreadcrumbList`) validated in Rich Results Test; keep visible content matching markup (no spam).
- Lighthouse workflow: test in Incognito, mobile + desktop, field data (CrUX) beats lab; fix red Diagnostics first (unused JS, image sizing, render-blocking).
- Regression-proof: add axe checks to CI, keyboard walkthrough per release, annual screen-reader pass (NVDA/VoiceOver) on top 5 flows.

## Examples
- Accessible modal: native `<dialog>` with focus trap + Esc + return-focus, `aria-labelledby`, background `inert`, reduced-motion-safe fade.
- SEO rescue: duplicate titles fixed per template, thin tag pages `noindex`, 301 map for migrated URLs, sitemap + Search Console reindex, rich-result FAQ JSON-LD.
- Vitals fix: LCP hero preloaded (`fetchpriority="high"`), 1200px WebP ≤150KB, CLS eliminated via `aspect-ratio` + dimensions, INP cut by debouncing handlers.

## Workflows
1. Baseline: run Lighthouse (mobile+desktop) + axe on top 5 pages; record LCP/INP/CLS, contrast failures, missing names.
2. Fix a11y first: landmarks/headings, names/labels, focus visibility, keyboard paths, alt audit — retest with keyboard only.
3. Fix SEO: titles/descriptions/canonicals, robots/sitemap/Search Console, 301s, JSON-LD validation.
4. Fix speed: images (WebP, sizes, lazy), fonts (subset+swap), JS (defer/split), cache headers — rerun Lighthouse until green.
5. Lock in: axe in CI, Lighthouse budget (`lighthouserc`), quarterly screen-reader + Search Console coverage review.

## Templates
```html
<!-- Accessible dialog + SEO head -->
<dialog id="signup" aria-labelledby="signup-title">
  <h2 id="signup-title">Get the newsletter</h2>
  <form method="dialog">
    <label for="d-email">Email</label>
    <input id="d-email" type="email" required autocomplete="email" aria-describedby="d-err">
    <p id="d-err" hidden>Enter a valid email.</p>
    <button value="cancel" formnovalidate>Cancel</button>
    <button value="ok">Subscribe</button>
  </form>
</dialog>
<script>const d = document.querySelector('#signup'); d.showModal(); d.addEventListener('close', () => document.querySelector('#open').focus());</script>
```
```html
<!-- JSON-LD + robots/sitemap refs -->
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"Article","headline":"Fast Widgets Guide","author":{"@type":"Organization","name":"Acme"},"datePublished":"2026-01-01"}
</script>
```
```txt
# robots.txt
User-agent: *
Allow: /
Sitemap: https://example.com/sitemap.xml
```

## Tools
- SARAH `shell_run`: `npx lighthouse https://example.com --view` for audits; `npx pa11y` for quick a11y pass when configured.
- SARAH `file_write`: head metadata in templates, `robots.txt`, JSON-LD blocks; keep sitemap generation in build/CMS, not by hand.
- SARAH preview: keyboard-only walkthrough (Tab/Shift+Tab/Enter/Esc), 200% zoom check, axe extension zero criticals.

## Advanced
- Contrast traps: placeholder text and disabled buttons often fail — darken placeholders, never convey meaning by color alone (add icons/text).
- Focus finesse: `:focus-visible` rings (2px offset), never `outline:none` without replacement, skip-link visible on focus, `tabindex="-1"` for programmatic targets only.
- Troubleshooting: Lighthouse variance → test 3x Incognito + throttled; CLS spike → late font/image/ad injection; `noindex` leak → staging header copied to prod.
- Screen readers: test headings/landmarks rotor, form error announcement (`role="alert"`), live regions (`aria-live="polite"`) for toasts/counts.
- Pro tip: budgets beat heroics — `lighthouserc` perf ≥90, a11y =100, LCP <2.5s enforced in CI so regressions fail the build.

## Documentation
- WCAG 2.2: https://www.w3.org/WAI/standards-guidelines/wcag
- web.dev performance: https://web.dev/performance
- Google SEO starter: https://developers.google.com/search/docs/fundamentals/seo-starter-guide
