@wazir-dev/cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (629) hide show
  1. package/AGENTS.md +111 -0
  2. package/CHANGELOG.md +14 -0
  3. package/CONTRIBUTING.md +101 -0
  4. package/LICENSE +21 -0
  5. package/README.md +314 -0
  6. package/assets/composition-engine.mmd +34 -0
  7. package/assets/demo-script.sh +17 -0
  8. package/assets/logo-dark.svg +14 -0
  9. package/assets/logo.svg +14 -0
  10. package/assets/pipeline.mmd +39 -0
  11. package/assets/record-demo.sh +51 -0
  12. package/docs/README.md +51 -0
  13. package/docs/adapters/context-mode.md +60 -0
  14. package/docs/concepts/architecture.md +87 -0
  15. package/docs/concepts/artifact-model.md +60 -0
  16. package/docs/concepts/composition-engine.md +36 -0
  17. package/docs/concepts/indexing-and-recall.md +160 -0
  18. package/docs/concepts/observability.md +41 -0
  19. package/docs/concepts/roles-and-workflows.md +59 -0
  20. package/docs/concepts/terminology-policy.md +27 -0
  21. package/docs/getting-started/01-installation.md +78 -0
  22. package/docs/getting-started/02-first-run.md +102 -0
  23. package/docs/getting-started/03-adding-to-project.md +15 -0
  24. package/docs/getting-started/04-host-setup.md +15 -0
  25. package/docs/guides/ci-integration.md +15 -0
  26. package/docs/guides/creating-skills.md +15 -0
  27. package/docs/guides/expertise-module-authoring.md +15 -0
  28. package/docs/guides/hook-development.md +15 -0
  29. package/docs/guides/memory-and-learnings.md +34 -0
  30. package/docs/guides/multi-host-export.md +15 -0
  31. package/docs/guides/troubleshooting.md +101 -0
  32. package/docs/guides/writing-custom-roles.md +15 -0
  33. package/docs/plans/2026-03-15-cli-pipeline-integration-design.md +592 -0
  34. package/docs/plans/2026-03-15-cli-pipeline-integration-plan.md +598 -0
  35. package/docs/plans/2026-03-15-docs-enforcement-plan.md +238 -0
  36. package/docs/readmes/INDEX.md +99 -0
  37. package/docs/readmes/features/expertise/README.md +171 -0
  38. package/docs/readmes/features/exports/README.md +222 -0
  39. package/docs/readmes/features/hooks/README.md +103 -0
  40. package/docs/readmes/features/hooks/loop-cap-guard.md +133 -0
  41. package/docs/readmes/features/hooks/post-tool-capture.md +121 -0
  42. package/docs/readmes/features/hooks/post-tool-lint.md +130 -0
  43. package/docs/readmes/features/hooks/pre-compact-summary.md +122 -0
  44. package/docs/readmes/features/hooks/pre-tool-capture-route.md +100 -0
  45. package/docs/readmes/features/hooks/protected-path-write-guard.md +128 -0
  46. package/docs/readmes/features/hooks/session-start.md +119 -0
  47. package/docs/readmes/features/hooks/stop-handoff-harvest.md +125 -0
  48. package/docs/readmes/features/roles/README.md +157 -0
  49. package/docs/readmes/features/roles/clarifier.md +152 -0
  50. package/docs/readmes/features/roles/content-author.md +190 -0
  51. package/docs/readmes/features/roles/designer.md +193 -0
  52. package/docs/readmes/features/roles/executor.md +184 -0
  53. package/docs/readmes/features/roles/learner.md +210 -0
  54. package/docs/readmes/features/roles/planner.md +182 -0
  55. package/docs/readmes/features/roles/researcher.md +164 -0
  56. package/docs/readmes/features/roles/reviewer.md +184 -0
  57. package/docs/readmes/features/roles/specifier.md +162 -0
  58. package/docs/readmes/features/roles/verifier.md +215 -0
  59. package/docs/readmes/features/schemas/README.md +178 -0
  60. package/docs/readmes/features/skills/README.md +63 -0
  61. package/docs/readmes/features/skills/brainstorming.md +96 -0
  62. package/docs/readmes/features/skills/debugging.md +148 -0
  63. package/docs/readmes/features/skills/design.md +120 -0
  64. package/docs/readmes/features/skills/prepare-next.md +109 -0
  65. package/docs/readmes/features/skills/run-audit.md +159 -0
  66. package/docs/readmes/features/skills/scan-project.md +109 -0
  67. package/docs/readmes/features/skills/self-audit.md +176 -0
  68. package/docs/readmes/features/skills/tdd.md +137 -0
  69. package/docs/readmes/features/skills/using-skills.md +92 -0
  70. package/docs/readmes/features/skills/verification.md +120 -0
  71. package/docs/readmes/features/skills/writing-plans.md +104 -0
  72. package/docs/readmes/features/tooling/README.md +320 -0
  73. package/docs/readmes/features/workflows/README.md +186 -0
  74. package/docs/readmes/features/workflows/author.md +181 -0
  75. package/docs/readmes/features/workflows/clarify.md +154 -0
  76. package/docs/readmes/features/workflows/design-review.md +171 -0
  77. package/docs/readmes/features/workflows/design.md +169 -0
  78. package/docs/readmes/features/workflows/discover.md +162 -0
  79. package/docs/readmes/features/workflows/execute.md +173 -0
  80. package/docs/readmes/features/workflows/learn.md +167 -0
  81. package/docs/readmes/features/workflows/plan-review.md +165 -0
  82. package/docs/readmes/features/workflows/plan.md +170 -0
  83. package/docs/readmes/features/workflows/prepare-next.md +167 -0
  84. package/docs/readmes/features/workflows/review.md +169 -0
  85. package/docs/readmes/features/workflows/run-audit.md +191 -0
  86. package/docs/readmes/features/workflows/spec-challenge.md +159 -0
  87. package/docs/readmes/features/workflows/specify.md +160 -0
  88. package/docs/readmes/features/workflows/verify.md +177 -0
  89. package/docs/readmes/packages/README.md +50 -0
  90. package/docs/readmes/packages/ajv.md +117 -0
  91. package/docs/readmes/packages/context-mode.md +118 -0
  92. package/docs/readmes/packages/gray-matter.md +116 -0
  93. package/docs/readmes/packages/node-test.md +137 -0
  94. package/docs/readmes/packages/yaml.md +112 -0
  95. package/docs/reference/configuration-reference.md +159 -0
  96. package/docs/reference/expertise-index.md +52 -0
  97. package/docs/reference/git-flow.md +43 -0
  98. package/docs/reference/hooks.md +87 -0
  99. package/docs/reference/host-exports.md +50 -0
  100. package/docs/reference/launch-checklist.md +172 -0
  101. package/docs/reference/marketplace-listings.md +76 -0
  102. package/docs/reference/release-process.md +34 -0
  103. package/docs/reference/roles-reference.md +77 -0
  104. package/docs/reference/skills.md +33 -0
  105. package/docs/reference/templates.md +29 -0
  106. package/docs/reference/tooling-cli.md +94 -0
  107. package/docs/truth-claims.yaml +222 -0
  108. package/expertise/PROGRESS.md +63 -0
  109. package/expertise/README.md +18 -0
  110. package/expertise/antipatterns/PROGRESS.md +56 -0
  111. package/expertise/antipatterns/backend/api-design-antipatterns.md +1271 -0
  112. package/expertise/antipatterns/backend/auth-antipatterns.md +1195 -0
  113. package/expertise/antipatterns/backend/caching-antipatterns.md +622 -0
  114. package/expertise/antipatterns/backend/database-antipatterns.md +1038 -0
  115. package/expertise/antipatterns/backend/index.md +24 -0
  116. package/expertise/antipatterns/backend/microservices-antipatterns.md +850 -0
  117. package/expertise/antipatterns/code/architecture-antipatterns.md +919 -0
  118. package/expertise/antipatterns/code/async-antipatterns.md +622 -0
  119. package/expertise/antipatterns/code/code-smells.md +1186 -0
  120. package/expertise/antipatterns/code/dependency-antipatterns.md +1209 -0
  121. package/expertise/antipatterns/code/error-handling-antipatterns.md +1360 -0
  122. package/expertise/antipatterns/code/index.md +27 -0
  123. package/expertise/antipatterns/code/naming-and-abstraction.md +1118 -0
  124. package/expertise/antipatterns/code/state-management-antipatterns.md +1076 -0
  125. package/expertise/antipatterns/code/testing-antipatterns.md +1053 -0
  126. package/expertise/antipatterns/design/accessibility-antipatterns.md +1136 -0
  127. package/expertise/antipatterns/design/dark-patterns.md +1121 -0
  128. package/expertise/antipatterns/design/index.md +22 -0
  129. package/expertise/antipatterns/design/ui-antipatterns.md +1202 -0
  130. package/expertise/antipatterns/design/ux-antipatterns.md +680 -0
  131. package/expertise/antipatterns/frontend/css-layout-antipatterns.md +691 -0
  132. package/expertise/antipatterns/frontend/flutter-antipatterns.md +1827 -0
  133. package/expertise/antipatterns/frontend/index.md +23 -0
  134. package/expertise/antipatterns/frontend/mobile-antipatterns.md +573 -0
  135. package/expertise/antipatterns/frontend/react-antipatterns.md +1128 -0
  136. package/expertise/antipatterns/frontend/spa-antipatterns.md +1235 -0
  137. package/expertise/antipatterns/index.md +31 -0
  138. package/expertise/antipatterns/performance/index.md +20 -0
  139. package/expertise/antipatterns/performance/performance-antipatterns.md +1013 -0
  140. package/expertise/antipatterns/performance/premature-optimization.md +623 -0
  141. package/expertise/antipatterns/performance/scaling-antipatterns.md +785 -0
  142. package/expertise/antipatterns/process/ai-coding-antipatterns.md +853 -0
  143. package/expertise/antipatterns/process/code-review-antipatterns.md +656 -0
  144. package/expertise/antipatterns/process/deployment-antipatterns.md +920 -0
  145. package/expertise/antipatterns/process/index.md +23 -0
  146. package/expertise/antipatterns/process/technical-debt-antipatterns.md +647 -0
  147. package/expertise/antipatterns/security/index.md +20 -0
  148. package/expertise/antipatterns/security/secrets-antipatterns.md +849 -0
  149. package/expertise/antipatterns/security/security-theater.md +843 -0
  150. package/expertise/antipatterns/security/vulnerability-patterns.md +801 -0
  151. package/expertise/architecture/PROGRESS.md +70 -0
  152. package/expertise/architecture/data/caching-architecture.md +671 -0
  153. package/expertise/architecture/data/data-consistency.md +574 -0
  154. package/expertise/architecture/data/data-modeling.md +536 -0
  155. package/expertise/architecture/data/event-streams-and-queues.md +634 -0
  156. package/expertise/architecture/data/index.md +25 -0
  157. package/expertise/architecture/data/search-architecture.md +663 -0
  158. package/expertise/architecture/data/sql-vs-nosql.md +708 -0
  159. package/expertise/architecture/decisions/architecture-decision-records.md +640 -0
  160. package/expertise/architecture/decisions/build-vs-buy.md +616 -0
  161. package/expertise/architecture/decisions/index.md +23 -0
  162. package/expertise/architecture/decisions/monolith-to-microservices.md +790 -0
  163. package/expertise/architecture/decisions/technology-selection.md +616 -0
  164. package/expertise/architecture/distributed/cap-theorem-and-tradeoffs.md +800 -0
  165. package/expertise/architecture/distributed/circuit-breaker-bulkhead.md +741 -0
  166. package/expertise/architecture/distributed/consensus-and-coordination.md +796 -0
  167. package/expertise/architecture/distributed/distributed-systems-fundamentals.md +564 -0
  168. package/expertise/architecture/distributed/idempotency-and-retry.md +796 -0
  169. package/expertise/architecture/distributed/index.md +25 -0
  170. package/expertise/architecture/distributed/saga-pattern.md +797 -0
  171. package/expertise/architecture/foundations/architectural-thinking.md +460 -0
  172. package/expertise/architecture/foundations/coupling-and-cohesion.md +770 -0
  173. package/expertise/architecture/foundations/design-principles-solid.md +649 -0
  174. package/expertise/architecture/foundations/domain-driven-design.md +719 -0
  175. package/expertise/architecture/foundations/index.md +25 -0
  176. package/expertise/architecture/foundations/separation-of-concerns.md +472 -0
  177. package/expertise/architecture/foundations/twelve-factor-app.md +797 -0
  178. package/expertise/architecture/index.md +34 -0
  179. package/expertise/architecture/integration/api-design-graphql.md +638 -0
  180. package/expertise/architecture/integration/api-design-grpc.md +804 -0
  181. package/expertise/architecture/integration/api-design-rest.md +892 -0
  182. package/expertise/architecture/integration/index.md +25 -0
  183. package/expertise/architecture/integration/third-party-integration.md +795 -0
  184. package/expertise/architecture/integration/webhooks-and-callbacks.md +1152 -0
  185. package/expertise/architecture/integration/websockets-realtime.md +791 -0
  186. package/expertise/architecture/mobile-architecture/index.md +22 -0
  187. package/expertise/architecture/mobile-architecture/mobile-app-architecture.md +780 -0
  188. package/expertise/architecture/mobile-architecture/mobile-backend-for-frontend.md +670 -0
  189. package/expertise/architecture/mobile-architecture/offline-first.md +719 -0
  190. package/expertise/architecture/mobile-architecture/push-and-sync.md +782 -0
  191. package/expertise/architecture/patterns/cqrs-event-sourcing.md +717 -0
  192. package/expertise/architecture/patterns/event-driven.md +797 -0
  193. package/expertise/architecture/patterns/hexagonal-clean-architecture.md +870 -0
  194. package/expertise/architecture/patterns/index.md +27 -0
  195. package/expertise/architecture/patterns/layered-architecture.md +736 -0
  196. package/expertise/architecture/patterns/microservices.md +753 -0
  197. package/expertise/architecture/patterns/modular-monolith.md +692 -0
  198. package/expertise/architecture/patterns/monolith.md +626 -0
  199. package/expertise/architecture/patterns/plugin-architecture.md +735 -0
  200. package/expertise/architecture/patterns/serverless.md +780 -0
  201. package/expertise/architecture/scaling/database-scaling.md +615 -0
  202. package/expertise/architecture/scaling/feature-flags-and-rollouts.md +757 -0
  203. package/expertise/architecture/scaling/horizontal-vs-vertical.md +606 -0
  204. package/expertise/architecture/scaling/index.md +24 -0
  205. package/expertise/architecture/scaling/multi-tenancy.md +800 -0
  206. package/expertise/architecture/scaling/stateless-design.md +787 -0
  207. package/expertise/backend/embedded-firmware.md +625 -0
  208. package/expertise/backend/go.md +853 -0
  209. package/expertise/backend/index.md +24 -0
  210. package/expertise/backend/java-spring.md +448 -0
  211. package/expertise/backend/node-typescript.md +625 -0
  212. package/expertise/backend/python-fastapi.md +724 -0
  213. package/expertise/backend/rust.md +458 -0
  214. package/expertise/backend/solidity.md +711 -0
  215. package/expertise/composition-map.yaml +443 -0
  216. package/expertise/content/foundations/content-modeling.md +395 -0
  217. package/expertise/content/foundations/editorial-standards.md +449 -0
  218. package/expertise/content/foundations/index.md +24 -0
  219. package/expertise/content/foundations/microcopy.md +455 -0
  220. package/expertise/content/foundations/terminology-governance.md +509 -0
  221. package/expertise/content/index.md +34 -0
  222. package/expertise/content/patterns/accessibility-copy.md +518 -0
  223. package/expertise/content/patterns/index.md +24 -0
  224. package/expertise/content/patterns/notification-content.md +433 -0
  225. package/expertise/content/patterns/sample-content.md +486 -0
  226. package/expertise/content/patterns/state-copy.md +439 -0
  227. package/expertise/design/PROGRESS.md +58 -0
  228. package/expertise/design/disciplines/dark-mode-theming.md +577 -0
  229. package/expertise/design/disciplines/design-systems.md +595 -0
  230. package/expertise/design/disciplines/index.md +25 -0
  231. package/expertise/design/disciplines/information-architecture.md +800 -0
  232. package/expertise/design/disciplines/interaction-design.md +788 -0
  233. package/expertise/design/disciplines/responsive-design.md +552 -0
  234. package/expertise/design/disciplines/usability-testing.md +516 -0
  235. package/expertise/design/disciplines/user-research.md +792 -0
  236. package/expertise/design/foundations/accessibility-design.md +796 -0
  237. package/expertise/design/foundations/color-theory.md +797 -0
  238. package/expertise/design/foundations/iconography.md +795 -0
  239. package/expertise/design/foundations/index.md +26 -0
  240. package/expertise/design/foundations/motion-and-animation.md +653 -0
  241. package/expertise/design/foundations/rtl-design.md +585 -0
  242. package/expertise/design/foundations/spacing-and-layout.md +607 -0
  243. package/expertise/design/foundations/typography.md +800 -0
  244. package/expertise/design/foundations/visual-hierarchy.md +761 -0
  245. package/expertise/design/index.md +32 -0
  246. package/expertise/design/patterns/authentication-flows.md +474 -0
  247. package/expertise/design/patterns/content-consumption.md +789 -0
  248. package/expertise/design/patterns/data-display.md +618 -0
  249. package/expertise/design/patterns/e-commerce.md +1494 -0
  250. package/expertise/design/patterns/feedback-and-states.md +642 -0
  251. package/expertise/design/patterns/forms-and-input.md +819 -0
  252. package/expertise/design/patterns/gamification.md +801 -0
  253. package/expertise/design/patterns/index.md +31 -0
  254. package/expertise/design/patterns/microinteractions.md +449 -0
  255. package/expertise/design/patterns/navigation.md +800 -0
  256. package/expertise/design/patterns/notifications.md +705 -0
  257. package/expertise/design/patterns/onboarding.md +700 -0
  258. package/expertise/design/patterns/search-and-filter.md +601 -0
  259. package/expertise/design/patterns/settings-and-preferences.md +768 -0
  260. package/expertise/design/patterns/social-and-community.md +748 -0
  261. package/expertise/design/platforms/desktop-native.md +612 -0
  262. package/expertise/design/platforms/index.md +25 -0
  263. package/expertise/design/platforms/mobile-android.md +825 -0
  264. package/expertise/design/platforms/mobile-cross-platform.md +983 -0
  265. package/expertise/design/platforms/mobile-ios.md +699 -0
  266. package/expertise/design/platforms/tablet.md +794 -0
  267. package/expertise/design/platforms/web-dashboard.md +790 -0
  268. package/expertise/design/platforms/web-responsive.md +550 -0
  269. package/expertise/design/psychology/behavioral-nudges.md +449 -0
  270. package/expertise/design/psychology/cognitive-load.md +1191 -0
  271. package/expertise/design/psychology/error-psychology.md +778 -0
  272. package/expertise/design/psychology/index.md +22 -0
  273. package/expertise/design/psychology/persuasive-design.md +736 -0
  274. package/expertise/design/psychology/user-mental-models.md +623 -0
  275. package/expertise/design/tooling/open-pencil.md +266 -0
  276. package/expertise/frontend/angular.md +1073 -0
  277. package/expertise/frontend/desktop-electron.md +546 -0
  278. package/expertise/frontend/flutter.md +782 -0
  279. package/expertise/frontend/index.md +27 -0
  280. package/expertise/frontend/native-android.md +409 -0
  281. package/expertise/frontend/native-ios.md +490 -0
  282. package/expertise/frontend/react-native.md +1160 -0
  283. package/expertise/frontend/react.md +808 -0
  284. package/expertise/frontend/vue.md +1089 -0
  285. package/expertise/humanize/domain-rules-code.md +79 -0
  286. package/expertise/humanize/domain-rules-content.md +67 -0
  287. package/expertise/humanize/domain-rules-technical-docs.md +56 -0
  288. package/expertise/humanize/index.md +35 -0
  289. package/expertise/humanize/self-audit-checklist.md +87 -0
  290. package/expertise/humanize/sentence-patterns.md +218 -0
  291. package/expertise/humanize/vocabulary-blacklist.md +105 -0
  292. package/expertise/i18n/PROGRESS.md +65 -0
  293. package/expertise/i18n/advanced/accessibility-and-i18n.md +28 -0
  294. package/expertise/i18n/advanced/bidirectional-text-algorithm.md +38 -0
  295. package/expertise/i18n/advanced/complex-scripts.md +30 -0
  296. package/expertise/i18n/advanced/performance-and-i18n.md +27 -0
  297. package/expertise/i18n/advanced/testing-i18n.md +28 -0
  298. package/expertise/i18n/content/content-adaptation.md +23 -0
  299. package/expertise/i18n/content/locale-specific-formatting.md +23 -0
  300. package/expertise/i18n/content/machine-translation-integration.md +28 -0
  301. package/expertise/i18n/content/translation-management.md +29 -0
  302. package/expertise/i18n/foundations/date-time-calendars.md +67 -0
  303. package/expertise/i18n/foundations/i18n-architecture.md +272 -0
  304. package/expertise/i18n/foundations/locale-and-language-tags.md +79 -0
  305. package/expertise/i18n/foundations/numbers-currency-units.md +61 -0
  306. package/expertise/i18n/foundations/pluralization-and-gender.md +109 -0
  307. package/expertise/i18n/foundations/string-externalization.md +236 -0
  308. package/expertise/i18n/foundations/text-direction-bidi.md +241 -0
  309. package/expertise/i18n/foundations/unicode-and-encoding.md +86 -0
  310. package/expertise/i18n/index.md +38 -0
  311. package/expertise/i18n/platform/backend-i18n.md +31 -0
  312. package/expertise/i18n/platform/flutter-i18n.md +148 -0
  313. package/expertise/i18n/platform/native-android-i18n.md +36 -0
  314. package/expertise/i18n/platform/native-ios-i18n.md +36 -0
  315. package/expertise/i18n/platform/react-i18n.md +103 -0
  316. package/expertise/i18n/platform/web-css-i18n.md +81 -0
  317. package/expertise/i18n/rtl/arabic-specific.md +175 -0
  318. package/expertise/i18n/rtl/hebrew-specific.md +149 -0
  319. package/expertise/i18n/rtl/rtl-animations-and-transitions.md +111 -0
  320. package/expertise/i18n/rtl/rtl-forms-and-input.md +161 -0
  321. package/expertise/i18n/rtl/rtl-fundamentals.md +211 -0
  322. package/expertise/i18n/rtl/rtl-icons-and-images.md +181 -0
  323. package/expertise/i18n/rtl/rtl-layout-mirroring.md +252 -0
  324. package/expertise/i18n/rtl/rtl-navigation-and-gestures.md +107 -0
  325. package/expertise/i18n/rtl/rtl-testing-and-qa.md +147 -0
  326. package/expertise/i18n/rtl/rtl-typography.md +160 -0
  327. package/expertise/index.md +113 -0
  328. package/expertise/index.yaml +216 -0
  329. package/expertise/infrastructure/cloud-aws.md +597 -0
  330. package/expertise/infrastructure/cloud-gcp.md +599 -0
  331. package/expertise/infrastructure/cybersecurity.md +816 -0
  332. package/expertise/infrastructure/database-mongodb.md +447 -0
  333. package/expertise/infrastructure/database-postgres.md +400 -0
  334. package/expertise/infrastructure/devops-cicd.md +787 -0
  335. package/expertise/infrastructure/index.md +27 -0
  336. package/expertise/performance/PROGRESS.md +50 -0
  337. package/expertise/performance/backend/api-latency.md +1204 -0
  338. package/expertise/performance/backend/background-jobs.md +506 -0
  339. package/expertise/performance/backend/connection-pooling.md +1209 -0
  340. package/expertise/performance/backend/database-query-optimization.md +515 -0
  341. package/expertise/performance/backend/index.md +23 -0
  342. package/expertise/performance/backend/rate-limiting-and-throttling.md +971 -0
  343. package/expertise/performance/foundations/algorithmic-complexity.md +954 -0
  344. package/expertise/performance/foundations/caching-strategies.md +489 -0
  345. package/expertise/performance/foundations/concurrency-and-parallelism.md +847 -0
  346. package/expertise/performance/foundations/index.md +24 -0
  347. package/expertise/performance/foundations/measuring-and-profiling.md +440 -0
  348. package/expertise/performance/foundations/memory-management.md +964 -0
  349. package/expertise/performance/foundations/performance-budgets.md +1314 -0
  350. package/expertise/performance/index.md +31 -0
  351. package/expertise/performance/infrastructure/auto-scaling.md +1059 -0
  352. package/expertise/performance/infrastructure/cdn-and-edge.md +1081 -0
  353. package/expertise/performance/infrastructure/index.md +22 -0
  354. package/expertise/performance/infrastructure/load-balancing.md +1081 -0
  355. package/expertise/performance/infrastructure/observability.md +1079 -0
  356. package/expertise/performance/mobile/index.md +23 -0
  357. package/expertise/performance/mobile/mobile-animations.md +544 -0
  358. package/expertise/performance/mobile/mobile-memory-battery.md +416 -0
  359. package/expertise/performance/mobile/mobile-network.md +452 -0
  360. package/expertise/performance/mobile/mobile-rendering.md +599 -0
  361. package/expertise/performance/mobile/mobile-startup-time.md +505 -0
  362. package/expertise/performance/platform-specific/flutter-performance.md +647 -0
  363. package/expertise/performance/platform-specific/index.md +22 -0
  364. package/expertise/performance/platform-specific/node-performance.md +1307 -0
  365. package/expertise/performance/platform-specific/postgres-performance.md +1366 -0
  366. package/expertise/performance/platform-specific/react-performance.md +1403 -0
  367. package/expertise/performance/web/bundle-optimization.md +1239 -0
  368. package/expertise/performance/web/image-and-media.md +636 -0
  369. package/expertise/performance/web/index.md +24 -0
  370. package/expertise/performance/web/network-optimization.md +1133 -0
  371. package/expertise/performance/web/rendering-performance.md +1098 -0
  372. package/expertise/performance/web/ssr-and-hydration.md +918 -0
  373. package/expertise/performance/web/web-vitals.md +1374 -0
  374. package/expertise/quality/accessibility.md +985 -0
  375. package/expertise/quality/evidence-based-verification.md +499 -0
  376. package/expertise/quality/index.md +24 -0
  377. package/expertise/quality/ml-model-audit.md +614 -0
  378. package/expertise/quality/performance.md +600 -0
  379. package/expertise/quality/testing-api.md +891 -0
  380. package/expertise/quality/testing-mobile.md +496 -0
  381. package/expertise/quality/testing-web.md +849 -0
  382. package/expertise/security/PROGRESS.md +54 -0
  383. package/expertise/security/agentic-identity.md +540 -0
  384. package/expertise/security/compliance-frameworks.md +601 -0
  385. package/expertise/security/data/data-encryption.md +364 -0
  386. package/expertise/security/data/data-privacy-gdpr.md +692 -0
  387. package/expertise/security/data/database-security.md +1171 -0
  388. package/expertise/security/data/index.md +22 -0
  389. package/expertise/security/data/pii-handling.md +531 -0
  390. package/expertise/security/foundations/authentication.md +1041 -0
  391. package/expertise/security/foundations/authorization.md +603 -0
  392. package/expertise/security/foundations/cryptography.md +1001 -0
  393. package/expertise/security/foundations/index.md +25 -0
  394. package/expertise/security/foundations/owasp-top-10.md +1354 -0
  395. package/expertise/security/foundations/secrets-management.md +1217 -0
  396. package/expertise/security/foundations/secure-sdlc.md +700 -0
  397. package/expertise/security/foundations/supply-chain-security.md +698 -0
  398. package/expertise/security/index.md +31 -0
  399. package/expertise/security/infrastructure/cloud-security-aws.md +1296 -0
  400. package/expertise/security/infrastructure/cloud-security-gcp.md +1376 -0
  401. package/expertise/security/infrastructure/container-security.md +721 -0
  402. package/expertise/security/infrastructure/incident-response.md +1295 -0
  403. package/expertise/security/infrastructure/index.md +24 -0
  404. package/expertise/security/infrastructure/logging-and-monitoring.md +1618 -0
  405. package/expertise/security/infrastructure/network-security.md +1337 -0
  406. package/expertise/security/mobile/index.md +23 -0
  407. package/expertise/security/mobile/mobile-android-security.md +1218 -0
  408. package/expertise/security/mobile/mobile-binary-protection.md +1229 -0
  409. package/expertise/security/mobile/mobile-data-storage.md +1265 -0
  410. package/expertise/security/mobile/mobile-ios-security.md +1401 -0
  411. package/expertise/security/mobile/mobile-network-security.md +1520 -0
  412. package/expertise/security/smart-contract-security.md +594 -0
  413. package/expertise/security/testing/index.md +22 -0
  414. package/expertise/security/testing/penetration-testing.md +1258 -0
  415. package/expertise/security/testing/security-code-review.md +1765 -0
  416. package/expertise/security/testing/threat-modeling.md +1074 -0
  417. package/expertise/security/testing/vulnerability-scanning.md +1062 -0
  418. package/expertise/security/web/api-security.md +586 -0
  419. package/expertise/security/web/cors-and-headers.md +433 -0
  420. package/expertise/security/web/csrf.md +562 -0
  421. package/expertise/security/web/file-upload.md +1477 -0
  422. package/expertise/security/web/index.md +25 -0
  423. package/expertise/security/web/injection.md +1375 -0
  424. package/expertise/security/web/session-management.md +1101 -0
  425. package/expertise/security/web/xss.md +1158 -0
  426. package/exports/README.md +17 -0
  427. package/exports/hosts/claude/.claude/agents/clarifier.md +42 -0
  428. package/exports/hosts/claude/.claude/agents/content-author.md +63 -0
  429. package/exports/hosts/claude/.claude/agents/designer.md +55 -0
  430. package/exports/hosts/claude/.claude/agents/executor.md +55 -0
  431. package/exports/hosts/claude/.claude/agents/learner.md +51 -0
  432. package/exports/hosts/claude/.claude/agents/planner.md +53 -0
  433. package/exports/hosts/claude/.claude/agents/researcher.md +43 -0
  434. package/exports/hosts/claude/.claude/agents/reviewer.md +54 -0
  435. package/exports/hosts/claude/.claude/agents/specifier.md +47 -0
  436. package/exports/hosts/claude/.claude/agents/verifier.md +71 -0
  437. package/exports/hosts/claude/.claude/commands/author.md +42 -0
  438. package/exports/hosts/claude/.claude/commands/clarify.md +38 -0
  439. package/exports/hosts/claude/.claude/commands/design-review.md +46 -0
  440. package/exports/hosts/claude/.claude/commands/design.md +44 -0
  441. package/exports/hosts/claude/.claude/commands/discover.md +37 -0
  442. package/exports/hosts/claude/.claude/commands/execute.md +48 -0
  443. package/exports/hosts/claude/.claude/commands/learn.md +38 -0
  444. package/exports/hosts/claude/.claude/commands/plan-review.md +42 -0
  445. package/exports/hosts/claude/.claude/commands/plan.md +39 -0
  446. package/exports/hosts/claude/.claude/commands/prepare-next.md +37 -0
  447. package/exports/hosts/claude/.claude/commands/review.md +40 -0
  448. package/exports/hosts/claude/.claude/commands/run-audit.md +41 -0
  449. package/exports/hosts/claude/.claude/commands/spec-challenge.md +41 -0
  450. package/exports/hosts/claude/.claude/commands/specify.md +38 -0
  451. package/exports/hosts/claude/.claude/commands/verify.md +37 -0
  452. package/exports/hosts/claude/.claude/settings.json +34 -0
  453. package/exports/hosts/claude/CLAUDE.md +19 -0
  454. package/exports/hosts/claude/export.manifest.json +38 -0
  455. package/exports/hosts/claude/host-package.json +67 -0
  456. package/exports/hosts/codex/AGENTS.md +19 -0
  457. package/exports/hosts/codex/export.manifest.json +38 -0
  458. package/exports/hosts/codex/host-package.json +41 -0
  459. package/exports/hosts/cursor/.cursor/hooks.json +16 -0
  460. package/exports/hosts/cursor/.cursor/rules/wazir-core.mdc +19 -0
  461. package/exports/hosts/cursor/export.manifest.json +38 -0
  462. package/exports/hosts/cursor/host-package.json +42 -0
  463. package/exports/hosts/gemini/GEMINI.md +19 -0
  464. package/exports/hosts/gemini/export.manifest.json +38 -0
  465. package/exports/hosts/gemini/host-package.json +41 -0
  466. package/hooks/README.md +18 -0
  467. package/hooks/definitions/loop_cap_guard.yaml +21 -0
  468. package/hooks/definitions/post_tool_capture.yaml +24 -0
  469. package/hooks/definitions/pre_compact_summary.yaml +19 -0
  470. package/hooks/definitions/pre_tool_capture_route.yaml +19 -0
  471. package/hooks/definitions/protected_path_write_guard.yaml +19 -0
  472. package/hooks/definitions/session_start.yaml +19 -0
  473. package/hooks/definitions/stop_handoff_harvest.yaml +20 -0
  474. package/hooks/loop-cap-guard +17 -0
  475. package/hooks/post-tool-lint +36 -0
  476. package/hooks/protected-path-write-guard +17 -0
  477. package/hooks/session-start +41 -0
  478. package/llms-full.txt +2355 -0
  479. package/llms.txt +43 -0
  480. package/package.json +79 -0
  481. package/roles/README.md +20 -0
  482. package/roles/clarifier.md +42 -0
  483. package/roles/content-author.md +63 -0
  484. package/roles/designer.md +55 -0
  485. package/roles/executor.md +55 -0
  486. package/roles/learner.md +51 -0
  487. package/roles/planner.md +53 -0
  488. package/roles/researcher.md +43 -0
  489. package/roles/reviewer.md +54 -0
  490. package/roles/specifier.md +47 -0
  491. package/roles/verifier.md +71 -0
  492. package/schemas/README.md +24 -0
  493. package/schemas/accepted-learning.schema.json +20 -0
  494. package/schemas/author-artifact.schema.json +156 -0
  495. package/schemas/clarification.schema.json +19 -0
  496. package/schemas/design-artifact.schema.json +80 -0
  497. package/schemas/docs-claim.schema.json +18 -0
  498. package/schemas/export-manifest.schema.json +20 -0
  499. package/schemas/hook.schema.json +67 -0
  500. package/schemas/host-export-package.schema.json +18 -0
  501. package/schemas/implementation-plan.schema.json +19 -0
  502. package/schemas/proposed-learning.schema.json +19 -0
  503. package/schemas/research.schema.json +18 -0
  504. package/schemas/review.schema.json +29 -0
  505. package/schemas/run-manifest.schema.json +18 -0
  506. package/schemas/spec-challenge.schema.json +18 -0
  507. package/schemas/spec.schema.json +20 -0
  508. package/schemas/usage.schema.json +102 -0
  509. package/schemas/verification-proof.schema.json +29 -0
  510. package/schemas/wazir-manifest.schema.json +173 -0
  511. package/skills/README.md +40 -0
  512. package/skills/brainstorming/SKILL.md +77 -0
  513. package/skills/debugging/SKILL.md +50 -0
  514. package/skills/design/SKILL.md +61 -0
  515. package/skills/dispatching-parallel-agents/SKILL.md +128 -0
  516. package/skills/executing-plans/SKILL.md +70 -0
  517. package/skills/finishing-a-development-branch/SKILL.md +169 -0
  518. package/skills/humanize/SKILL.md +123 -0
  519. package/skills/init-pipeline/SKILL.md +124 -0
  520. package/skills/prepare-next/SKILL.md +20 -0
  521. package/skills/receiving-code-review/SKILL.md +123 -0
  522. package/skills/requesting-code-review/SKILL.md +105 -0
  523. package/skills/requesting-code-review/code-reviewer.md +108 -0
  524. package/skills/run-audit/SKILL.md +197 -0
  525. package/skills/scan-project/SKILL.md +41 -0
  526. package/skills/self-audit/SKILL.md +153 -0
  527. package/skills/subagent-driven-development/SKILL.md +154 -0
  528. package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -0
  529. package/skills/subagent-driven-development/implementer-prompt.md +102 -0
  530. package/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
  531. package/skills/tdd/SKILL.md +23 -0
  532. package/skills/using-git-worktrees/SKILL.md +163 -0
  533. package/skills/using-skills/SKILL.md +95 -0
  534. package/skills/verification/SKILL.md +22 -0
  535. package/skills/wazir/SKILL.md +463 -0
  536. package/skills/writing-plans/SKILL.md +30 -0
  537. package/skills/writing-skills/SKILL.md +157 -0
  538. package/skills/writing-skills/anthropic-best-practices.md +122 -0
  539. package/skills/writing-skills/persuasion-principles.md +50 -0
  540. package/templates/README.md +20 -0
  541. package/templates/artifacts/README.md +10 -0
  542. package/templates/artifacts/accepted-learning.md +19 -0
  543. package/templates/artifacts/accepted-learning.template.json +12 -0
  544. package/templates/artifacts/author.md +74 -0
  545. package/templates/artifacts/author.template.json +19 -0
  546. package/templates/artifacts/clarification.md +21 -0
  547. package/templates/artifacts/clarification.template.json +12 -0
  548. package/templates/artifacts/execute-notes.md +19 -0
  549. package/templates/artifacts/implementation-plan.md +21 -0
  550. package/templates/artifacts/implementation-plan.template.json +11 -0
  551. package/templates/artifacts/learning-proposal.md +19 -0
  552. package/templates/artifacts/next-run-handoff.md +21 -0
  553. package/templates/artifacts/plan-review.md +19 -0
  554. package/templates/artifacts/proposed-learning.template.json +12 -0
  555. package/templates/artifacts/research.md +21 -0
  556. package/templates/artifacts/research.template.json +12 -0
  557. package/templates/artifacts/review-findings.md +19 -0
  558. package/templates/artifacts/review.template.json +11 -0
  559. package/templates/artifacts/run-manifest.template.json +8 -0
  560. package/templates/artifacts/spec-challenge.md +19 -0
  561. package/templates/artifacts/spec-challenge.template.json +11 -0
  562. package/templates/artifacts/spec.md +21 -0
  563. package/templates/artifacts/spec.template.json +12 -0
  564. package/templates/artifacts/verification-proof.md +19 -0
  565. package/templates/artifacts/verification-proof.template.json +11 -0
  566. package/templates/examples/accepted-learning.example.json +14 -0
  567. package/templates/examples/author.example.json +152 -0
  568. package/templates/examples/clarification.example.json +15 -0
  569. package/templates/examples/docs-claim.example.json +8 -0
  570. package/templates/examples/export-manifest.example.json +7 -0
  571. package/templates/examples/host-export-package.example.json +11 -0
  572. package/templates/examples/implementation-plan.example.json +17 -0
  573. package/templates/examples/proposed-learning.example.json +13 -0
  574. package/templates/examples/research.example.json +15 -0
  575. package/templates/examples/research.example.md +6 -0
  576. package/templates/examples/review.example.json +17 -0
  577. package/templates/examples/run-manifest.example.json +9 -0
  578. package/templates/examples/spec-challenge.example.json +14 -0
  579. package/templates/examples/spec.example.json +21 -0
  580. package/templates/examples/verification-proof.example.json +21 -0
  581. package/templates/examples/wazir-manifest.example.yaml +65 -0
  582. package/templates/task-definition-schema.md +99 -0
  583. package/tooling/README.md +20 -0
  584. package/tooling/src/adapters/context-mode.js +50 -0
  585. package/tooling/src/capture/command.js +376 -0
  586. package/tooling/src/capture/store.js +99 -0
  587. package/tooling/src/capture/usage.js +270 -0
  588. package/tooling/src/checks/branches.js +50 -0
  589. package/tooling/src/checks/brand-truth.js +110 -0
  590. package/tooling/src/checks/changelog.js +231 -0
  591. package/tooling/src/checks/command-registry.js +36 -0
  592. package/tooling/src/checks/commits.js +102 -0
  593. package/tooling/src/checks/docs-drift.js +103 -0
  594. package/tooling/src/checks/docs-truth.js +201 -0
  595. package/tooling/src/checks/runtime-surface.js +156 -0
  596. package/tooling/src/cli.js +116 -0
  597. package/tooling/src/command-options.js +56 -0
  598. package/tooling/src/commands/validate.js +320 -0
  599. package/tooling/src/doctor/command.js +91 -0
  600. package/tooling/src/export/command.js +77 -0
  601. package/tooling/src/export/compiler.js +498 -0
  602. package/tooling/src/guards/loop-cap-guard.js +52 -0
  603. package/tooling/src/guards/protected-path-write-guard.js +67 -0
  604. package/tooling/src/index/command.js +152 -0
  605. package/tooling/src/index/storage.js +1061 -0
  606. package/tooling/src/index/summarizers.js +261 -0
  607. package/tooling/src/loaders.js +18 -0
  608. package/tooling/src/project-root.js +22 -0
  609. package/tooling/src/recall/command.js +225 -0
  610. package/tooling/src/schema-validator.js +30 -0
  611. package/tooling/src/state-root.js +40 -0
  612. package/tooling/src/status/command.js +71 -0
  613. package/wazir.manifest.yaml +135 -0
  614. package/workflows/README.md +19 -0
  615. package/workflows/author.md +42 -0
  616. package/workflows/clarify.md +38 -0
  617. package/workflows/design-review.md +46 -0
  618. package/workflows/design.md +44 -0
  619. package/workflows/discover.md +37 -0
  620. package/workflows/execute.md +48 -0
  621. package/workflows/learn.md +38 -0
  622. package/workflows/plan-review.md +42 -0
  623. package/workflows/plan.md +39 -0
  624. package/workflows/prepare-next.md +37 -0
  625. package/workflows/review.md +40 -0
  626. package/workflows/run-audit.md +41 -0
  627. package/workflows/spec-challenge.md +41 -0
  628. package/workflows/specify.md +38 -0
  629. package/workflows/verify.md +37 -0
@@ -0,0 +1,1136 @@
1
+ # Accessibility Anti-Patterns -- Design Domain
2
+
3
+ > 95.9% of the top one million homepages fail WCAG 2.2 Level A/AA conformance, averaging 51 accessibility errors per page. Over 4,000 ADA web accessibility lawsuits were filed in 2024 alone, with a 37% increase in the first half of 2025. These anti-patterns are not theoretical -- they are the direct cause of litigation, user exclusion, and reputational damage.
4
+
5
+ ---
6
+
7
+ ## Anti-Pattern Index
8
+
9
+ | # | Anti-Pattern | Severity | WCAG SC | Prevalence |
10
+ |----|-------------------------------------------|------------|------------------|------------|
11
+ | 1 | Missing Alt Text on Images | Critical | 1.1.1 | 55.5% |
12
+ | 2 | Div/Span Soup Instead of Semantic HTML | Critical | 1.3.1, 4.1.2 | Very High |
13
+ | 3 | Keyboard Traps | Critical | 2.1.2 | 12% |
14
+ | 4 | Missing Focus Indicators | High | 2.4.7, 2.4.13 | Very High |
15
+ | 5 | Color-Only Information | High | 1.4.1 | High |
16
+ | 6 | ARIA Misuse | Critical | 4.1.2 | Very High |
17
+ | 7 | Auto-Playing Media Without Controls | High | 1.4.2 | Moderate |
18
+ | 8 | Time Limits Without Extension | High | 2.2.1 | Moderate |
19
+ | 9 | Missing Skip Navigation Links | Moderate | 2.4.1 | 83% |
20
+ | 10 | Inaccessible Forms | Critical | 1.3.1, 3.3.2 | 45% |
21
+ | 11 | Custom Controls Without Keyboard Support | Critical | 2.1.1 | High |
22
+ | 12 | Low Contrast Text | High | 1.4.3 | 79.1% |
23
+ | 13 | Non-Resizable / Tiny Text | High | 1.4.4 | Moderate |
24
+ | 14 | Mouse-Only Interactions | Critical | 2.1.1, 2.5.1 | High |
25
+ | 15 | PDF-Only Content Without HTML Alternative | Moderate | 1.1.1, 4.1.2 | High |
26
+ | 16 | CAPTCHAs Without Accessible Alternatives | Critical | 1.1.1, 3.3.8 | High |
27
+ | 17 | Dynamic Content Without Live Regions | High | 4.1.3 | High |
28
+ | 18 | Inaccessible Modals and Dialogs | Critical | 2.1.2, 4.1.2 | Very High |
29
+ | 19 | Tables Without Proper Headers | Moderate | 1.3.1 | High |
30
+ | 20 | Focus Order Mismatching Visual Order | High | 2.4.3, 1.3.2 | High |
31
+
32
+ ---
33
+
34
+ ## 1. Missing Alt Text on Images
35
+
36
+ **Also known as:** Decorative-by-default, silent images, empty information.
37
+
38
+ **Description:** Images are rendered without `alt` attributes or with meaningless values like `alt="image"`, `alt="photo"`, or `alt="IMG_20240301.jpg"`. Screen readers either skip the image entirely or announce the filename, leaving blind and low-vision users without critical information.
39
+
40
+ **Why it happens:**
41
+ - Developers treat alt text as optional or low-priority
42
+ - CMS systems allow image uploads without requiring alt text
43
+ - Stock photo integrations auto-populate filenames as alt values
44
+ - Teams lack content authoring guidelines for image descriptions
45
+
46
+ **Real-world impact:**
47
+ - NFB v. Target Corp. (2006-2008): Target.com lacked alt text on images, preventing blind users from navigating or purchasing products. Settlement: $6 million in class damages plus mandatory remediation.
48
+ - Conner v. Parkwood Entertainment (2019): Beyonce.com sued for missing alt text on graphics, inaccessible drop-down menus, and lack of keyboard access.
49
+ - WebAIM Million 2025: 55.5% of homepages have images missing alt text, averaging 11 images per page without alternatives.
50
+
51
+ **What to do instead:**
52
+ ```html
53
+ <!-- WRONG: Missing alt -->
54
+ <img src="sale-banner.jpg">
55
+
56
+ <!-- WRONG: Meaningless alt -->
57
+ <img src="sale-banner.jpg" alt="image">
58
+ <img src="sale-banner.jpg" alt="banner">
59
+
60
+ <!-- RIGHT: Descriptive alt -->
61
+ <img src="sale-banner.jpg" alt="Summer sale: 40% off all outdoor furniture through July 31">
62
+
63
+ <!-- RIGHT: Decorative image explicitly marked -->
64
+ <img src="decorative-border.png" alt="" role="presentation">
65
+ ```
66
+
67
+ **Detection:**
68
+ - Automated: axe-core rule `image-alt`, Lighthouse audit, htmlhint
69
+ - Manual: Screen reader walkthrough (NVDA: press `G` to jump between images)
70
+ - CI gate: eslint-plugin-jsx-a11y `alt-text` rule
71
+
72
+ **WCAG:** 1.1.1 Non-text Content (Level A)
73
+
74
+ ---
75
+
76
+ ## 2. Div/Span Soup Instead of Semantic HTML
77
+
78
+ **Also known as:** Div-itis, unsemantic markup, reinventing native elements.
79
+
80
+ **Description:** Developers build interactive controls entirely from `<div>` and `<span>` elements, manually adding click handlers, rather than using native HTML elements like `<button>`, `<a>`, `<nav>`, `<main>`, `<header>`, or `<select>`. The result is elements that look correct visually but are invisible or broken for assistive technology.
81
+
82
+ **Why it happens:**
83
+ - CSS styling of native elements is perceived as difficult
84
+ - Component libraries abstract away HTML, producing `<div>` wrappers
85
+ - Developers lack understanding of implicit ARIA roles and native keyboard behavior
86
+ - "It works for me" testing only with a mouse in a visual browser
87
+
88
+ **Real-world impact:**
89
+ - Screen readers cannot identify interactive elements -- a `<div onclick="...">` is announced as "text" not "button"
90
+ - Keyboard users cannot Tab to `<div>` elements (they are not focusable by default)
91
+ - WebAIM 2025: Pages using excessive ARIA to compensate for non-semantic HTML averaged 57 errors, more than double pages without ARIA (implying semantic HTML)
92
+ - 67.5% of screen reader users navigate by headings; missing `<h1>`-`<h6>` hierarchy destroys their primary navigation strategy
93
+
94
+ **What to do instead:**
95
+ ```html
96
+ <!-- WRONG: Fake button -->
97
+ <div class="btn" onclick="submit()">Submit</div>
98
+
99
+ <!-- RIGHT: Native button -->
100
+ <button type="submit">Submit</button>
101
+
102
+ <!-- WRONG: Fake navigation -->
103
+ <div class="nav">
104
+ <div class="nav-item" onclick="goto('/home')">Home</div>
105
+ </div>
106
+
107
+ <!-- RIGHT: Semantic navigation -->
108
+ <nav aria-label="Main">
109
+ <ul>
110
+ <li><a href="/home">Home</a></li>
111
+ </ul>
112
+ </nav>
113
+
114
+ <!-- RIGHT: Landmark regions -->
115
+ <header>...</header>
116
+ <main>...</main>
117
+ <footer>...</footer>
118
+ ```
119
+
120
+ **Detection:**
121
+ - Automated: axe-core rules `button-name`, `landmark-*`, eslint `click-events-have-key-events`
122
+ - Manual: Tab through page -- can you reach and activate every control by keyboard alone?
123
+ - Audit: Run Accessibility Tree inspector in Chrome DevTools and compare against visual layout
124
+
125
+ **WCAG:** 1.3.1 Info and Relationships (Level A), 4.1.2 Name, Role, Value (Level A)
126
+
127
+ ---
128
+
129
+ ## 3. Keyboard Traps
130
+
131
+ **Also known as:** Focus jail, inescapable widgets, Tab black holes.
132
+
133
+ **Description:** Keyboard focus enters a component -- such as a modal, embedded video player, rich text editor, or third-party widget -- and the user cannot navigate away using standard keyboard commands (Tab, Shift+Tab, Escape). The user is effectively trapped.
134
+
135
+ **Why it happens:**
136
+ - Third-party embeds (video players, maps, iframes, CAPTCHA widgets) do not implement keyboard exit
137
+ - JavaScript `onBlur` / `onChange` handlers force focus back to the same element on validation failure
138
+ - Modal dialogs trap focus intentionally but fail to release it when closed
139
+ - Rich text editors and code editors capture all key events including Tab and Escape
140
+
141
+ **Real-world impact:**
142
+ - WCAG SC 2.1.2 is Level A -- the most fundamental requirement. Failure means the site cannot be considered accessible at any level.
143
+ - WebAIM analysis found keyboard traps on 12% of websites
144
+ - For keyboard-only users (motor disabilities, RSI, blindness), a trap means total inability to complete the task -- they must close and reopen the browser
145
+
146
+ **What to do instead:**
147
+ ```javascript
148
+ // WRONG: Focus forced back on blur
149
+ input.addEventListener('blur', () => {
150
+ if (!input.value) input.focus(); // TRAP!
151
+ });
152
+
153
+ // RIGHT: Show error but allow navigation
154
+ input.addEventListener('blur', () => {
155
+ if (!input.value) showError(input, 'Required field');
156
+ // User can still Tab away
157
+ });
158
+
159
+ // RIGHT: Modal focus trap with Escape release
160
+ dialog.addEventListener('keydown', (e) => {
161
+ if (e.key === 'Escape') {
162
+ closeDialog();
163
+ triggerButton.focus(); // Return focus to trigger
164
+ }
165
+ // Trap Tab within modal (but Escape always exits)
166
+ if (e.key === 'Tab') trapFocusWithinDialog(e);
167
+ });
168
+ ```
169
+
170
+ **Detection:**
171
+ - Manual: Tab through every interactive element; can you always Tab/Shift+Tab/Escape away?
172
+ - Automated: Lighthouse "User focus is not accidentally trapped in a region"
173
+ - Test: Navigate into embedded iframes, video players, and third-party widgets
174
+
175
+ **WCAG:** 2.1.2 No Keyboard Trap (Level A)
176
+
177
+ ---
178
+
179
+ ## 4. Missing Focus Indicators
180
+
181
+ **Also known as:** Invisible focus, outline:none, ghost navigation.
182
+
183
+ **Description:** The visible focus indicator (typically a browser-default outline) is removed via CSS (`outline: none` or `outline: 0`) without providing a custom replacement. Keyboard users cannot see which element is currently focused.
184
+
185
+ **Why it happens:**
186
+ - Designers find the browser default focus ring "ugly" and remove it globally
187
+ - CSS resets (normalize.css, reset.css) zero out outlines
188
+ - Teams add `:focus { outline: none }` to satisfy visual QA without understanding the accessibility consequence
189
+ - Focus styles are tested only with a mouse (where they are irrelevant)
190
+
191
+ **Real-world impact:**
192
+ - WCAG 2.2 added SC 2.4.13 Focus Appearance, requiring minimum area and contrast for focus indicators
193
+ - Keyboard-only users (estimated 7-10% of web users) cannot navigate pages where focus is invisible
194
+ - Low-contrast focus rings cause the same disorientation as missing ones
195
+
196
+ **What to do instead:**
197
+ ```css
198
+ /* WRONG: Removing focus without replacement */
199
+ *:focus {
200
+ outline: none;
201
+ }
202
+
203
+ /* RIGHT: Custom visible focus indicator */
204
+ *:focus-visible {
205
+ outline: 3px solid #1a73e8;
206
+ outline-offset: 2px;
207
+ border-radius: 2px;
208
+ }
209
+
210
+ /* RIGHT: High-contrast focus for dark backgrounds */
211
+ .dark-theme *:focus-visible {
212
+ outline: 3px solid #ffffff;
213
+ box-shadow: 0 0 0 5px rgba(0, 0, 0, 0.5);
214
+ }
215
+
216
+ /* RIGHT: Remove only for mouse, keep for keyboard */
217
+ *:focus:not(:focus-visible) {
218
+ outline: none;
219
+ }
220
+ ```
221
+
222
+ **Detection:**
223
+ - Automated: axe-core rule `focus-visible` (partial), CSS grep for `outline: none` or `outline: 0`
224
+ - Manual: Unplug mouse, navigate entire page with Tab key -- can you always see where you are?
225
+ - WCAG 2.2 SC 2.4.13 requires focus indicator with minimum 2px perimeter and 3:1 contrast
226
+
227
+ **WCAG:** 2.4.7 Focus Visible (Level AA), 2.4.13 Focus Appearance (Level AA, WCAG 2.2)
228
+
229
+ ---
230
+
231
+ ## 5. Color-Only Information
232
+
233
+ **Also known as:** Red means error, green means go, color-coded status.
234
+
235
+ **Description:** Information is conveyed solely through color -- red text for errors, green for success, color-coded charts without patterns, required fields indicated only by a red asterisk with no label. Users who are colorblind, use monochrome displays, or have low vision cannot distinguish the states.
236
+
237
+ **Why it happens:**
238
+ - Designers assume universal color perception
239
+ - "Red = error" feels culturally obvious
240
+ - Data visualization libraries default to color-only legends
241
+ - Form validation shows only red/green borders with no text
242
+
243
+ **Real-world impact:**
244
+ - 8% of males and 0.5% of females have some form of color vision deficiency (roughly 300 million people worldwide)
245
+ - Red-green colorblindness (deuteranopia/protanopia) makes error/success states indistinguishable
246
+ - Color-coded dashboards become unreadable for affected users
247
+
248
+ **What to do instead:**
249
+ ```html
250
+ <!-- WRONG: Color-only error -->
251
+ <input style="border-color: red;" />
252
+
253
+ <!-- RIGHT: Color + icon + text -->
254
+ <div class="field-error">
255
+ <input aria-invalid="true" aria-describedby="email-error" />
256
+ <span id="email-error" role="alert">
257
+ <svg aria-hidden="true"><!-- error icon --></svg>
258
+ Please enter a valid email address.
259
+ </span>
260
+ </div>
261
+
262
+ <!-- WRONG: Color-only chart legend -->
263
+ <div style="color: green;">Revenue</div>
264
+ <div style="color: blue;">Costs</div>
265
+
266
+ <!-- RIGHT: Color + pattern + label -->
267
+ <!-- Use distinct line patterns (solid, dashed, dotted) in addition to colors -->
268
+ <!-- Include direct labels on chart lines, not just a separate legend -->
269
+ ```
270
+
271
+ **Detection:**
272
+ - Manual: View page in grayscale (DevTools > Rendering > Emulate vision deficiencies)
273
+ - Automated: axe-core `color-contrast` (partial -- does not catch semantic color-only issues)
274
+ - Review: Search codebase for validation that sets only `border-color` or `color` without companion text
275
+
276
+ **WCAG:** 1.4.1 Use of Color (Level A)
277
+
278
+ ---
279
+
280
+ ## 6. ARIA Misuse
281
+
282
+ **Also known as:** Bad ARIA, cargo-cult accessibility, role soup, "No ARIA is better than bad ARIA."
283
+
284
+ **Description:** ARIA attributes are applied incorrectly -- wrong roles, missing required children/parent roles, conflicting attributes, `aria-role` instead of `role`, or ARIA used where native HTML semantics suffice. Misused ARIA actively harms assistive technology users by announcing incorrect information.
285
+
286
+ **Why it happens:**
287
+ - Developers copy-paste ARIA from Stack Overflow without understanding the specification
288
+ - ARIA is added as an afterthought to patch non-semantic HTML rather than fixing the HTML
289
+ - Role hierarchy requirements (e.g., `tab` must be inside `tablist`) are not understood
290
+ - Testing is done visually, never with a screen reader
291
+
292
+ **Real-world impact:**
293
+ - WebAIM Million 2025: Pages with ARIA averaged 57 errors -- more than double pages without ARIA. Over 105 million ARIA attributes detected across 1 million pages (106 per page), an 18.5% increase year-over-year.
294
+ - The accessibility community maxim: "No ARIA is better than bad ARIA" -- incorrect roles cause screen readers to announce wrong element types, breaking user mental models.
295
+ - Using `role="menu"` on a navigation bar causes screen readers to expect arrow-key navigation like an OS menu, confusing users when standard Tab behavior is needed.
296
+
297
+ **What to do instead:**
298
+ ```html
299
+ <!-- WRONG: ARIA on a native element that already has the role -->
300
+ <button role="button">Submit</button>
301
+
302
+ <!-- RIGHT: Native element, no ARIA needed -->
303
+ <button>Submit</button>
304
+
305
+ <!-- WRONG: Broken role hierarchy -->
306
+ <div role="tab">Settings</div> <!-- Missing tablist parent -->
307
+
308
+ <!-- RIGHT: Correct hierarchy -->
309
+ <div role="tablist" aria-label="Settings">
310
+ <button role="tab" aria-selected="true" aria-controls="panel-1">General</button>
311
+ <button role="tab" aria-selected="false" aria-controls="panel-2">Privacy</button>
312
+ </div>
313
+ <div role="tabpanel" id="panel-1">...</div>
314
+
315
+ <!-- WRONG: Invalid attribute name -->
316
+ <div aria-role="alert">Error!</div>
317
+
318
+ <!-- RIGHT: Correct attribute -->
319
+ <div role="alert">Error!</div>
320
+
321
+ <!-- WRONG: Redundant ARIA overriding native semantics -->
322
+ <a href="/home" role="button">Home</a>
323
+
324
+ <!-- RIGHT: Use the correct element -->
325
+ <a href="/home">Home</a>
326
+ ```
327
+
328
+ **Detection:**
329
+ - Automated: axe-core rules `aria-*`, Lighthouse ARIA audits, `eslint-plugin-jsx-a11y`
330
+ - Manual: Screen reader testing (NVDA + Firefox, VoiceOver + Safari, JAWS + Chrome)
331
+ - Linting: `aria-query` and `axe-core` rule sets catch invalid roles, missing required attributes
332
+
333
+ **WCAG:** 4.1.2 Name, Role, Value (Level A)
334
+
335
+ ---
336
+
337
+ ## 7. Auto-Playing Media Without Controls
338
+
339
+ **Also known as:** Surprise audio, autoplay assault, sensory ambush.
340
+
341
+ **Description:** Audio or video content plays automatically when a page loads, without visible pause/stop controls, volume adjustment, or the ability to mute. This disorients screen reader users (whose audio output is overridden), triggers vestibular disorders, and overwhelms users with cognitive disabilities.
342
+
343
+ **Why it happens:**
344
+ - Marketing teams want "engaging" hero videos on landing pages
345
+ - Developers add `autoplay` attribute without considering assistive technology
346
+ - Background ambient audio is deemed "subtle enough" to not need controls
347
+ - Third-party ad embeds autoplay without site control
348
+
349
+ **Real-world impact:**
350
+ - Screen reader users cannot hear their assistive technology output over auto-playing audio
351
+ - Users with PTSD, anxiety disorders, or sensory processing conditions are startled or overwhelmed
352
+ - WCAG SC 1.4.2 requires any audio playing for more than 3 seconds to have pause/stop/mute controls
353
+
354
+ **What to do instead:**
355
+ ```html
356
+ <!-- WRONG: Autoplay with sound, no controls -->
357
+ <video autoplay src="promo.mp4"></video>
358
+
359
+ <!-- RIGHT: Autoplay muted with controls visible -->
360
+ <video autoplay muted loop playsinline controls>
361
+ <source src="promo.mp4" type="video/mp4">
362
+ <track kind="captions" src="promo-captions.vtt" srclang="en" label="English">
363
+ </video>
364
+
365
+ <!-- RIGHT: No autoplay, user initiates -->
366
+ <video controls preload="metadata">
367
+ <source src="promo.mp4" type="video/mp4">
368
+ <track kind="captions" src="promo-captions.vtt" srclang="en" label="English">
369
+ </video>
370
+ ```
371
+
372
+ **Detection:**
373
+ - Automated: Search codebase for `autoplay` attribute without `muted`
374
+ - Manual: Load page -- does anything play without user action?
375
+ - Audit: Check that all media players have visible, keyboard-accessible controls
376
+
377
+ **WCAG:** 1.4.2 Audio Control (Level A)
378
+
379
+ ---
380
+
381
+ ## 8. Time Limits Without Extension
382
+
383
+ **Also known as:** Session timeout ambush, countdown wall, timed-out mid-task.
384
+
385
+ **Description:** Users are given a fixed time to complete a task (form submission, checkout, exam) with no warning, no extension option, and no ability to save progress. When time expires, work is lost silently.
386
+
387
+ **Why it happens:**
388
+ - Security teams impose aggressive session timeouts (e.g., 2 minutes) without accessibility review
389
+ - Shopping cart / booking systems use countdown timers without extension
390
+ - Developers do not consider users who need more time (cognitive disabilities, screen reader users, motor impairments)
391
+
392
+ **Real-world impact:**
393
+ - Screen reader users take 3-10x longer to complete forms than sighted mouse users
394
+ - Users with cognitive disabilities need more time to process and respond
395
+ - Motor-impaired users using switch devices or eye tracking are significantly slower
396
+ - WCAG requires that for each time limit, users must be able to turn it off, adjust it, or extend it
397
+
398
+ **What to do instead:**
399
+ ```javascript
400
+ // WRONG: Silent timeout
401
+ setTimeout(() => { window.location = '/session-expired'; }, 120000);
402
+
403
+ // RIGHT: Warning with extension option
404
+ function warnBeforeTimeout() {
405
+ const warning = document.getElementById('timeout-warning');
406
+ warning.removeAttribute('hidden');
407
+ warning.focus();
408
+ // "Your session will expire in 2 minutes.
409
+ // Press 'Continue' to extend by 20 minutes."
410
+ }
411
+ // Warn at least 20 seconds before expiry (WCAG SC 2.2.1)
412
+ setTimeout(warnBeforeTimeout, timeoutMs - 20000);
413
+ ```
414
+
415
+ **Detection:**
416
+ - Manual: Complete all timed workflows at slow speed; does anything expire without warning?
417
+ - Code review: Search for `setTimeout`, `setInterval` paired with redirect or form clearing
418
+ - Audit: Check session timeout configuration and whether extension is available
419
+
420
+ **WCAG:** 2.2.1 Timing Adjustable (Level A)
421
+
422
+ ---
423
+
424
+ ## 9. Missing Skip Navigation Links
425
+
426
+ **Also known as:** Header gauntlet, navigation treadmill, 50-tabs-to-content.
427
+
428
+ **Description:** Pages lack a "Skip to main content" link, forcing keyboard and screen reader users to Tab through the entire header, navigation bar, and sidebar on every page load before reaching the primary content.
429
+
430
+ **Why it happens:**
431
+ - Developers and designers are unaware skip links exist as a pattern
432
+ - Skip links are visually hidden by default and forgotten during QA
433
+ - SPAs re-render headers on route changes without providing skip links
434
+ - Broken implementations: skip link target lacks `tabindex="-1"`, so focus does not actually move
435
+
436
+ **Real-world impact:**
437
+ - WebAIM 2025: Only 17% of the top one million homepages have skip links. Of those, one in six are broken.
438
+ - A site with 30 navigation links forces 30+ Tab presses before reaching content on every page
439
+ - Conner v. Parkwood Entertainment (2019): "Lack of navigation links" was among the cited violations
440
+
441
+ **What to do instead:**
442
+ ```html
443
+ <!-- RIGHT: Skip link as first focusable element -->
444
+ <body>
445
+ <a href="#main-content" class="skip-link">Skip to main content</a>
446
+ <header><!-- navigation --></header>
447
+ <main id="main-content" tabindex="-1">
448
+ <!-- page content -->
449
+ </main>
450
+ </body>
451
+
452
+ <style>
453
+ /* Visually hidden until focused */
454
+ .skip-link {
455
+ position: absolute;
456
+ left: -9999px;
457
+ top: auto;
458
+ width: 1px;
459
+ height: 1px;
460
+ overflow: hidden;
461
+ }
462
+ .skip-link:focus {
463
+ position: fixed;
464
+ top: 10px;
465
+ left: 10px;
466
+ width: auto;
467
+ height: auto;
468
+ padding: 8px 16px;
469
+ background: #000;
470
+ color: #fff;
471
+ z-index: 10000;
472
+ font-size: 1rem;
473
+ }
474
+ </style>
475
+ ```
476
+
477
+ **Detection:**
478
+ - Manual: Press Tab on page load -- does a "Skip" link appear?
479
+ - Automated: axe-core rule `skip-link`, Lighthouse bypass audit
480
+ - Verify: After activating skip link, does focus actually land on the main content?
481
+
482
+ **WCAG:** 2.4.1 Bypass Blocks (Level A)
483
+
484
+ ---
485
+
486
+ ## 10. Inaccessible Forms
487
+
488
+ **Also known as:** Label-less inputs, placeholder-as-label, orphan errors.
489
+
490
+ **Description:** Form fields lack programmatically associated labels, rely on placeholder text as the only label, or display error messages that are not connected to their respective fields. Screen readers cannot tell users what a field is for or what went wrong.
491
+
492
+ **Why it happens:**
493
+ - Designers prefer "clean" UIs with placeholder-only inputs (no visible labels)
494
+ - Developers use `<label>` visually but forget the `for` attribute to create programmatic association
495
+ - Error messages are generic ("Please fix errors above") rather than field-specific
496
+ - CMS/form builders generate inaccessible markup by default
497
+
498
+ **Real-world impact:**
499
+ - WebAIM Million 2025: Missing form labels appear on 45% of homepages -- the third most common error
500
+ - Placeholder text disappears on input, leaving users with cognitive disabilities unable to remember what to enter
501
+ - Generic errors force screen reader users to search the entire form for problems
502
+ - Courts have consistently ruled inaccessible forms violate the ADA (WCAG 3.3.1, 3.3.2)
503
+
504
+ **What to do instead:**
505
+ ```html
506
+ <!-- WRONG: Placeholder as label -->
507
+ <input type="email" placeholder="Email address">
508
+
509
+ <!-- RIGHT: Visible label with association -->
510
+ <label for="email">Email address</label>
511
+ <input type="email" id="email" name="email"
512
+ aria-describedby="email-hint email-error"
513
+ aria-invalid="false">
514
+ <span id="email-hint" class="hint">We will never share your email.</span>
515
+
516
+ <!-- RIGHT: Error associated with field -->
517
+ <label for="password">Password</label>
518
+ <input type="password" id="password" aria-invalid="true"
519
+ aria-describedby="password-error">
520
+ <span id="password-error" role="alert">
521
+ Password must be at least 8 characters.
522
+ </span>
523
+ ```
524
+
525
+ **Detection:**
526
+ - Automated: axe-core rules `label`, `form-field-multiple-labels`, eslint `label-has-associated-control`
527
+ - Manual: Click on each label text -- does it focus the corresponding input?
528
+ - Screen reader: Navigate form in JAWS/NVDA forms mode -- are all fields announced with labels?
529
+
530
+ **WCAG:** 1.3.1 Info and Relationships (Level A), 3.3.2 Labels or Instructions (Level A), 3.3.1 Error Identification (Level A)
531
+
532
+ ---
533
+
534
+ ## 11. Custom Controls Without Keyboard Support
535
+
536
+ **Also known as:** Mouse-only widgets, Tab-immune components, click-only interactives.
537
+
538
+ **Description:** Custom UI components (carousels, accordions, tree views, drag-and-drop interfaces, star ratings, sliders) are built without implementing keyboard event handlers. They respond only to mouse clicks and hover events.
539
+
540
+ **Why it happens:**
541
+ - Developers implement `onClick` but not `onKeyDown`
542
+ - Custom components do not use native interactive elements as their base
543
+ - "Accessible later" is deferred indefinitely
544
+ - Testing never includes keyboard-only users
545
+
546
+ **Real-world impact:**
547
+ - Robles v. Domino's Pizza (2016-2022): Blind user Guillermo Robles could not order pizza via keyboard and screen reader. The Supreme Court declined to hear Domino's appeal, establishing that the ADA applies to websites. After six years of litigation, Domino's settled.
548
+ - Any control that is mouse-only excludes keyboard users, screen reader users, switch device users, and voice control users
549
+ - WCAG SC 2.1.1 is Level A: all functionality must be operable via keyboard
550
+
551
+ **What to do instead:**
552
+ ```javascript
553
+ // WRONG: Click-only accordion
554
+ div.addEventListener('click', togglePanel);
555
+
556
+ // RIGHT: Keyboard-accessible accordion
557
+ button.addEventListener('click', togglePanel);
558
+ button.addEventListener('keydown', (e) => {
559
+ if (e.key === 'Enter' || e.key === ' ') {
560
+ e.preventDefault();
561
+ togglePanel();
562
+ }
563
+ });
564
+ // Better yet: use <button> which handles Enter/Space natively
565
+ // <button aria-expanded="false" aria-controls="panel-1">Section 1</button>
566
+
567
+ // WRONG: Drag-only reordering
568
+ item.addEventListener('dragstart', onDrag);
569
+
570
+ // RIGHT: Drag AND keyboard alternative
571
+ // Provide up/down buttons or use aria-grabbed + arrow keys
572
+ ```
573
+
574
+ **Detection:**
575
+ - Manual: Disconnect mouse, complete every workflow using only keyboard
576
+ - Automated: eslint `click-events-have-key-events`, `interactive-supports-focus`
577
+ - Review: Search for `addEventListener('click'` without corresponding keyboard handlers
578
+
579
+ **WCAG:** 2.1.1 Keyboard (Level A)
580
+
581
+ ---
582
+
583
+ ## 12. Low Contrast Text
584
+
585
+ **Also known as:** Gray-on-white, whisper text, aesthetic-over-readable.
586
+
587
+ **Description:** Text color does not meet the minimum contrast ratio against its background: 4.5:1 for normal text or 3:1 for large text (18pt+ or 14pt+ bold). Users with low vision, cataracts, or those in bright ambient light cannot read the content.
588
+
589
+ **Why it happens:**
590
+ - Designers prioritize "soft" or "modern" aesthetics (light gray on white)
591
+ - Brand color palettes are chosen without contrast checking
592
+ - Placeholder text, disabled states, and footer text are left at very low contrast
593
+ - Dark mode implementations invert poorly, creating low-contrast combinations
594
+
595
+ **Real-world impact:**
596
+ - WebAIM Million 2025: Low contrast text found on 79.1% of homepages -- the single most common accessibility error for the fifth consecutive year. Average of 29.6 low-contrast instances per page.
597
+ - 253 million people worldwide have vision impairment (WHO). Low contrast text is the most widespread barrier they face online.
598
+ - Low contrast issues are cited in virtually every ADA web accessibility lawsuit
599
+
600
+ **What to do instead:**
601
+ ```css
602
+ /* WRONG: 2.5:1 contrast ratio */
603
+ body { color: #999999; background: #ffffff; }
604
+
605
+ /* RIGHT: 7.4:1 contrast ratio */
606
+ body { color: #333333; background: #ffffff; }
607
+
608
+ /* WRONG: Placeholder too faint */
609
+ ::placeholder { color: #cccccc; }
610
+
611
+ /* RIGHT: Placeholder meeting 4.5:1 */
612
+ ::placeholder { color: #767676; }
613
+
614
+ /* Tools: Use WebAIM Contrast Checker, Chrome DevTools
615
+ color picker, or Polypane built-in contrast overlay */
616
+ ```
617
+
618
+ **Detection:**
619
+ - Automated: axe-core `color-contrast`, Lighthouse contrast audit, Polypane
620
+ - Manual: Chrome DevTools > Elements > color picker shows contrast ratio
621
+ - Design: Check all color pairs in the design system against WCAG thresholds before coding
622
+
623
+ **WCAG:** 1.4.3 Contrast Minimum (Level AA), 1.4.6 Contrast Enhanced (Level AAA)
624
+
625
+ ---
626
+
627
+ ## 13. Non-Resizable / Tiny Text
628
+
629
+ **Also known as:** Fixed font size, pixel-locked typography, zoom-breaking layout.
630
+
631
+ **Description:** Text is set in fixed pixel sizes (`font-size: 12px`) or the page layout breaks when text is resized to 200%. Content overflows, gets clipped by `overflow: hidden`, or overlaps other elements. Some sites use `maximum-scale=1` in the viewport meta tag, preventing pinch-to-zoom on mobile.
632
+
633
+ **Why it happens:**
634
+ - Pixel-perfect designs use fixed `px` units throughout
635
+ - `overflow: hidden` is used to "clean up" layout without testing at larger text sizes
636
+ - Viewport meta includes `user-scalable=no` or `maximum-scale=1`
637
+ - Component heights are fixed, causing text to overflow containers when resized
638
+
639
+ **What to do instead:**
640
+ ```css
641
+ /* WRONG: Fixed pixel sizes */
642
+ body { font-size: 12px; }
643
+ .card { height: 200px; overflow: hidden; }
644
+
645
+ /* RIGHT: Relative units */
646
+ body { font-size: 1rem; } /* 16px default, scales with user preference */
647
+ .card { min-height: 12rem; } /* Grows with text size */
648
+
649
+ /* WRONG: Preventing zoom */
650
+ <meta name="viewport" content="width=device-width, maximum-scale=1, user-scalable=no">
651
+
652
+ /* RIGHT: Allowing zoom */
653
+ <meta name="viewport" content="width=device-width, initial-scale=1">
654
+ ```
655
+
656
+ **Detection:**
657
+ - Manual: Set browser zoom to 200% -- does all content remain visible and functional?
658
+ - Automated: axe-core `meta-viewport`, grep for `user-scalable=no` or `maximum-scale=1`
659
+ - Design review: Ensure all containers use `min-height` not `height` with `overflow: hidden`
660
+
661
+ **WCAG:** 1.4.4 Resize Text (Level AA)
662
+
663
+ ---
664
+
665
+ ## 14. Mouse-Only Interactions
666
+
667
+ **Also known as:** Hover-dependent UI, click-to-reveal, tooltip-only information.
668
+
669
+ **Description:** Critical functionality or content is available only through mouse-specific events: hover-triggered menus, tooltips with essential information that appear only on `mouseover`, right-click context menus, drag-and-drop as the only reordering mechanism. Keyboard, touch, and assistive technology users are excluded.
670
+
671
+ **Why it happens:**
672
+ - CSS `:hover` is used without corresponding `:focus` styles
673
+ - Dropdown menus appear on hover with no keyboard or touch equivalent
674
+ - Drag-and-drop is the sole method for reordering (no button alternative)
675
+ - Tooltips with critical info lack `focus` triggers and `aria-describedby` association
676
+
677
+ **Real-world impact:**
678
+ - Touch device users (mobile, tablet) have no hover capability
679
+ - Voice control users (Dragon NaturallySpeaking) cannot trigger hover events
680
+ - Conner v. Parkwood Entertainment (2019): "Denial of keyboard access" and "inaccessible drop-down menus" among cited violations
681
+
682
+ **What to do instead:**
683
+ ```css
684
+ /* WRONG: Hover-only dropdown */
685
+ .menu-item:hover > .submenu { display: block; }
686
+
687
+ /* RIGHT: Hover AND focus */
688
+ .menu-item:hover > .submenu,
689
+ .menu-item:focus-within > .submenu {
690
+ display: block;
691
+ }
692
+ ```
693
+ ```html
694
+ <!-- WRONG: Tooltip only on hover, with critical info -->
695
+ <span title="Required: must be 8+ characters">Password</span>
696
+
697
+ <!-- RIGHT: Always-visible hint + accessible tooltip -->
698
+ <label for="pw">Password</label>
699
+ <input id="pw" aria-describedby="pw-hint">
700
+ <span id="pw-hint">Must be at least 8 characters.</span>
701
+ ```
702
+
703
+ **Detection:**
704
+ - Manual: Complete all workflows without a mouse; are any features missing?
705
+ - Automated: CSS grep for `:hover` without corresponding `:focus` or `:focus-within`
706
+ - Testing: Use iOS VoiceOver or Android TalkBack on mobile -- can you reach all content?
707
+
708
+ **WCAG:** 2.1.1 Keyboard (Level A), 2.5.1 Pointer Gestures (Level A), 1.4.13 Content on Hover or Focus (Level AA)
709
+
710
+ ---
711
+
712
+ ## 15. PDF-Only Content Without HTML Alternative
713
+
714
+ **Also known as:** PDF wall, document-format gatekeeping, scan-and-post.
715
+
716
+ **Description:** Important content (policies, forms, reports, menus, course materials) is published exclusively as PDF, often scanned images of paper documents. These PDFs lack tagged structure, reading order, alt text, and form field labels, making them partially or fully inaccessible to screen readers.
717
+
718
+ **Why it happens:**
719
+ - Organizations scan paper documents and post them as image-PDFs
720
+ - PDF is seen as the "official" format for legal/compliance documents
721
+ - PDF accessibility tagging (heading structure, reading order, form fields) requires specialized tools and knowledge
722
+ - "Just upload the PDF" is faster than creating an accessible HTML page
723
+
724
+ **Real-world impact:**
725
+ - Government agencies have been sued repeatedly over inaccessible PDF-only content (Section 508)
726
+ - Scanned-image PDFs are entirely invisible to screen readers -- they contain zero text to read
727
+ - Even tagged PDFs frequently have incorrect reading order, missing alt text, and broken form fields
728
+
729
+ **What to do instead:**
730
+ - Provide an HTML version of all PDF content as the primary format
731
+ - If PDF is required, ensure it is tagged (Adobe Acrobat Pro > Accessibility Checker)
732
+ - Never publish scanned-image PDFs without OCR and manual verification
733
+ - Include a text-based summary or equivalent HTML page alongside any PDF
734
+
735
+ **Detection:**
736
+ - Manual: Open PDFs in a screen reader -- can the full content be read in logical order?
737
+ - Automated: Adobe Acrobat Accessibility Checker, PAC 2024 (PDF Accessibility Checker)
738
+ - Policy: Require HTML alternative for every PDF published on the site
739
+
740
+ **WCAG:** 1.1.1 Non-text Content (Level A), 1.3.1 Info and Relationships (Level A), 4.1.2 Name, Role, Value (Level A)
741
+
742
+ ---
743
+
744
+ ## 16. CAPTCHAs Without Accessible Alternatives
745
+
746
+ **Also known as:** Bot gate that blocks humans, prove-you-can-see challenge, ability test masquerading as security.
747
+
748
+ **Description:** Visual CAPTCHAs (distorted text, image selection grids) are presented without accessible alternatives. Audio CAPTCHAs, when provided, are heavily distorted and often fail. Users with visual, auditory, cognitive, or motor disabilities are locked out of registration, login, or form submission.
749
+
750
+ **Why it happens:**
751
+ - CAPTCHA vendors prioritize bot detection over accessibility
752
+ - Developers integrate CAPTCHA without evaluating the accessible fallback
753
+ - Audio CAPTCHAs are added as a "checkbox" compliance measure but are unusable
754
+ - reCAPTCHA v2 image challenges are impossible for blind users without sighted assistance
755
+
756
+ **Real-world impact:**
757
+ - WebAIM survey (2023-2024): Screen reader users ranked CAPTCHA as the single most problematic element on the web -- worse than missing alt text, ambiguous links, or lack of keyboard access.
758
+ - W3C published "Inaccessibility of CAPTCHA" (TR/turingtest) acknowledging no fully accessible CAPTCHA exists
759
+ - FTC v. accessiBe (2025): $1 million settlement after FTC found accessiBe's overlay widget failed to make CAPTCHAs accessible despite marketing claims
760
+
761
+ **What to do instead:**
762
+ - Use invisible CAPTCHA / risk-based analysis (reCAPTCHA v3, Cloudflare Turnstile) that requires no user interaction
763
+ - Implement honeypot fields (hidden fields that bots fill out but humans do not)
764
+ - Use time-based analysis (bots submit forms faster than humans)
765
+ - If visual CAPTCHA is required, provide a genuinely usable audio alternative AND a contact/support bypass
766
+ - WCAG 2.2 SC 3.3.8 (Accessible Authentication) prohibits cognitive function tests for login
767
+
768
+ **Detection:**
769
+ - Manual: Attempt to complete all CAPTCHA-protected flows using a screen reader
770
+ - Audit: Test audio CAPTCHA alternatives -- can a real user with hearing understand them?
771
+ - Review: Check if any pathway exists for users who cannot complete the CAPTCHA
772
+
773
+ **WCAG:** 1.1.1 Non-text Content (Level A), 3.3.8 Accessible Authentication (Level AA, WCAG 2.2)
774
+
775
+ ---
776
+
777
+ ## 17. Dynamic Content Without Live Regions
778
+
779
+ **Also known as:** Silent updates, ghost notifications, invisible status changes.
780
+
781
+ **Description:** Content on the page updates dynamically (AJAX responses, form validation messages, chat messages, notifications, progress indicators, shopping cart counts) without using ARIA live regions. Screen reader users are unaware that anything has changed.
782
+
783
+ **Why it happens:**
784
+ - Developers update the DOM visually but do not consider screen reader announcements
785
+ - SPA frameworks (React, Angular, Vue) update components without native page reload announcements
786
+ - Teams are unaware of `aria-live`, `role="alert"`, `role="status"`, or `role="log"`
787
+ - Live regions are added dynamically after page load, which some screen readers do not detect
788
+
789
+ **What to do instead:**
790
+ ```html
791
+ <!-- RIGHT: Status message with polite live region -->
792
+ <!-- IMPORTANT: The live region container must exist in the DOM at page load -->
793
+ <div aria-live="polite" id="status-message"></div>
794
+
795
+ <script>
796
+ // Inject message into the existing container
797
+ document.getElementById('status-message').textContent =
798
+ 'Your item has been added to the cart.';
799
+ </script>
800
+
801
+ <!-- RIGHT: Urgent error alert -->
802
+ <div role="alert">
803
+ Payment failed. Please check your card details.
804
+ </div>
805
+
806
+ <!-- RIGHT: Progress indicator -->
807
+ <div role="progressbar" aria-valuenow="65" aria-valuemin="0"
808
+ aria-valuemax="100" aria-label="Upload progress">
809
+ 65%
810
+ </div>
811
+
812
+ <!-- WRONG: Dynamically injected live region (may not be detected) -->
813
+ <script>
814
+ const div = document.createElement('div');
815
+ div.setAttribute('aria-live', 'polite');
816
+ div.textContent = 'Updated!';
817
+ document.body.appendChild(div); // Screen reader may ignore this
818
+ </script>
819
+ ```
820
+
821
+ **Detection:**
822
+ - Manual: Use NVDA/JAWS while triggering dynamic updates -- are changes announced?
823
+ - Code review: Search for DOM manipulation that updates text without an `aria-live` container
824
+ - SPA audit: Verify route changes announce the new page title via a live region
825
+
826
+ **WCAG:** 4.1.3 Status Messages (Level AA)
827
+
828
+ ---
829
+
830
+ ## 18. Inaccessible Modals and Dialogs
831
+
832
+ **Also known as:** Ghost dialogs, focus-leaking modals, background-interactive overlays.
833
+
834
+ **Description:** Modal dialogs fail one or more of the following: focus does not move into the dialog on open; focus is not trapped within the dialog while open; background content remains interactive via keyboard; pressing Escape does not close the dialog; focus does not return to the trigger element on close; the dialog lacks `role="dialog"` and `aria-modal="true"`.
835
+
836
+ **Why it happens:**
837
+ - Developers use `<div>` with `display:block` instead of `<dialog>` or proper ARIA markup
838
+ - Focus management requires explicit JavaScript (not built into CSS show/hide)
839
+ - Third-party modal libraries have incomplete accessibility support
840
+ - Background scroll is prevented visually but not from keyboard/screen reader interaction
841
+
842
+ **Real-world impact:**
843
+ - Modals are one of the most common UI patterns and one of the most frequently broken for accessibility
844
+ - Screen readers may not announce that a dialog has appeared at all if `role="dialog"` is missing
845
+ - VoiceOver + Safari has known issues with `aria-modal="true"` making static dialog content inaccessible
846
+ - Keyboard users who can interact with background content while a modal is open lose their place entirely
847
+
848
+ **What to do instead:**
849
+ ```html
850
+ <!-- RIGHT: Native dialog element (modern browsers) -->
851
+ <dialog id="confirm-dialog" aria-labelledby="dialog-title">
852
+ <h2 id="dialog-title">Confirm deletion</h2>
853
+ <p>Are you sure you want to delete this item?</p>
854
+ <button id="cancel-btn">Cancel</button>
855
+ <button id="confirm-btn">Delete</button>
856
+ </dialog>
857
+
858
+ <script>
859
+ const dialog = document.getElementById('confirm-dialog');
860
+ const triggerBtn = document.getElementById('delete-trigger');
861
+
862
+ triggerBtn.addEventListener('click', () => {
863
+ dialog.showModal(); // Native: traps focus, adds backdrop, handles Escape
864
+ });
865
+
866
+ dialog.addEventListener('close', () => {
867
+ triggerBtn.focus(); // Return focus to trigger
868
+ });
869
+ </script>
870
+ ```
871
+
872
+ **Detection:**
873
+ - Manual: Open modal with keyboard, Tab through all elements -- does focus stay inside?
874
+ - Test: Press Escape -- does the modal close? Does focus return to the trigger?
875
+ - Screen reader: Does the dialog announce its title and role on open?
876
+ - Check: Can you interact with background content while the modal is open?
877
+
878
+ **WCAG:** 2.1.2 No Keyboard Trap (Level A), 4.1.2 Name, Role, Value (Level A), 2.4.3 Focus Order (Level A)
879
+
880
+ ---
881
+
882
+ ## 19. Tables Without Proper Headers
883
+
884
+ **Also known as:** Layout tables, header-free data, unlabeled grids.
885
+
886
+ **Description:** Data tables lack `<th>` elements, `scope` attributes, `<caption>`, or use `<table>` for visual layout instead of data. Screen readers cannot associate data cells with their headers, making the table content incomprehensible.
887
+
888
+ **Why it happens:**
889
+ - Tables are used for layout (a practice from the 1990s that persists in email templates and legacy codebases)
890
+ - Developers use `<td>` for all cells including headers, styling them bold via CSS
891
+ - Complex tables with merged cells (`colspan`, `rowspan`) lack `headers` attribute associations
892
+ - Data grids rendered by JavaScript frameworks output flat `<div>` structures instead of proper `<table>` markup
893
+
894
+ **What to do instead:**
895
+ ```html
896
+ <!-- WRONG: No headers, no caption -->
897
+ <table>
898
+ <tr><td>Name</td><td>Role</td><td>Start Date</td></tr>
899
+ <tr><td>Alice</td><td>Engineer</td><td>2024-01-15</td></tr>
900
+ </table>
901
+
902
+ <!-- RIGHT: Proper headers and caption -->
903
+ <table>
904
+ <caption>Engineering team roster</caption>
905
+ <thead>
906
+ <tr>
907
+ <th scope="col">Name</th>
908
+ <th scope="col">Role</th>
909
+ <th scope="col">Start Date</th>
910
+ </tr>
911
+ </thead>
912
+ <tbody>
913
+ <tr>
914
+ <th scope="row">Alice</th>
915
+ <td>Engineer</td>
916
+ <td>2024-01-15</td>
917
+ </tr>
918
+ </tbody>
919
+ </table>
920
+
921
+ <!-- RIGHT: Complex table with headers attribute -->
922
+ <table>
923
+ <caption>Quarterly revenue by region</caption>
924
+ <thead>
925
+ <tr>
926
+ <td></td>
927
+ <th id="q1" scope="col">Q1</th>
928
+ <th id="q2" scope="col">Q2</th>
929
+ </tr>
930
+ </thead>
931
+ <tbody>
932
+ <tr>
933
+ <th id="na" scope="row">North America</th>
934
+ <td headers="q1 na">$1.2M</td>
935
+ <td headers="q2 na">$1.5M</td>
936
+ </tr>
937
+ </tbody>
938
+ </table>
939
+ ```
940
+
941
+ **Detection:**
942
+ - Automated: axe-core rules `td-headers-attr`, `th-has-data-cells`, `table-fake-caption`
943
+ - Manual: Screen reader table navigation (JAWS: `Ctrl+Alt+Arrow` keys) -- are headers announced?
944
+ - Review: Search for `<table>` without `<th>` or `<caption>` elements
945
+
946
+ **WCAG:** 1.3.1 Info and Relationships (Level A)
947
+
948
+ ---
949
+
950
+ ## 20. Focus Order Mismatching Visual Order
951
+
952
+ **Also known as:** Tab chaos, positive tabindex abuse, CSS-reordered-but-DOM-unchanged.
953
+
954
+ **Description:** The keyboard Tab order does not match the visual layout of the page. This occurs when CSS (`order`, `flex-direction: row-reverse`, `position: absolute`, `float`) rearranges elements visually while the DOM order remains unchanged, or when positive `tabindex` values (1, 2, 3...) override the natural Tab sequence.
955
+
956
+ **Why it happens:**
957
+ - CSS Flexbox/Grid `order` property rearranges visual layout without changing DOM order
958
+ - Developers assign `tabindex="1"`, `tabindex="5"`, etc. to force a Tab sequence
959
+ - Absolutely positioned elements appear in one place visually but are in a different DOM location
960
+ - Mobile-first CSS moves elements to different visual positions on desktop breakpoints
961
+
962
+ **Real-world impact:**
963
+ - Keyboard users Tab to elements in an unexpected sequence, losing their place
964
+ - Screen reader users hear content in DOM order, which may contradict the visual story
965
+ - Using positive tabindex values across a page creates an unpredictable, unmaintainable Tab order
966
+
967
+ **What to do instead:**
968
+ ```html
969
+ <!-- WRONG: Positive tabindex -->
970
+ <input tabindex="3" placeholder="Last name">
971
+ <input tabindex="1" placeholder="First name">
972
+ <input tabindex="2" placeholder="Email">
973
+
974
+ <!-- RIGHT: Match DOM order to visual order -->
975
+ <input placeholder="First name">
976
+ <input placeholder="Email">
977
+ <input placeholder="Last name">
978
+
979
+ <!-- WRONG: CSS order mismatches DOM -->
980
+ <div style="display:flex;">
981
+ <div style="order:2;">Second visually, first in DOM</div>
982
+ <div style="order:1;">First visually, second in DOM</div>
983
+ </div>
984
+
985
+ <!-- RIGHT: DOM order matches intended visual order -->
986
+ <div style="display:flex;">
987
+ <div>First visually, first in DOM</div>
988
+ <div>Second visually, second in DOM</div>
989
+ </div>
990
+ ```
991
+
992
+ **Detection:**
993
+ - Manual: Tab through page and compare focus sequence against visual reading order
994
+ - Automated: axe-core `tabindex` rule (flags positive tabindex values)
995
+ - CSS review: Search for `order:`, `flex-direction: row-reverse`, `flex-direction: column-reverse`
996
+ - Test at multiple breakpoints: Mobile and desktop may have different visual orders
997
+
998
+ **WCAG:** 2.4.3 Focus Order (Level A), 1.3.2 Meaningful Sequence (Level A)
999
+
1000
+ ---
1001
+
1002
+ ## Root Cause Analysis
1003
+
1004
+ The 20 anti-patterns above share a small number of systemic root causes:
1005
+
1006
+ ### 1. Lack of Assistive Technology Testing
1007
+ Teams test only with mouse and visual browser. If no one on the team uses a screen reader, keyboard-only navigation, or voice control, accessibility failures are invisible during development and QA.
1008
+
1009
+ ### 2. "Accessibility Later" Mentality
1010
+ Accessibility is treated as a post-launch polish step rather than a core requirement. By the time it is addressed, the architecture (non-semantic HTML, custom controls, inaccessible third-party dependencies) makes remediation expensive.
1011
+
1012
+ ### 3. Aesthetic Over Function
1013
+ Design decisions prioritize visual minimalism (low contrast, hidden focus indicators, placeholder-only inputs, hover-only interactions) over readability and operability for all users.
1014
+
1015
+ ### 4. Native HTML Ignorance
1016
+ Developers reach for `<div>` + JavaScript + ARIA instead of using native HTML elements (`<button>`, `<dialog>`, `<nav>`, `<label>`, `<table>`) that provide keyboard support, screen reader semantics, and focus management for free.
1017
+
1018
+ ### 5. Third-Party Dependency Trust
1019
+ Teams embed third-party widgets (video players, maps, CAPTCHAs, chat widgets, analytics overlays) without verifying their accessibility. The FTC v. accessiBe settlement ($1 million, 2025) proved that accessibility overlay widgets can create more barriers than they remove.
1020
+
1021
+ ### 6. No Automated Enforcement
1022
+ Without accessibility linting in CI/CD (axe-core, eslint-plugin-jsx-a11y, Lighthouse CI), regressions are introduced silently with every deployment.
1023
+
1024
+ ---
1025
+
1026
+ ## Self-Check Questions
1027
+
1028
+ Before shipping any feature, the team should be able to answer "yes" to every question below:
1029
+
1030
+ 1. **Keyboard:** Can every interactive element be reached and operated with Tab, Shift+Tab, Enter, Space, Escape, and Arrow keys alone?
1031
+ 2. **Focus:** Is a visible focus indicator present on every focusable element, meeting WCAG 2.4.13 minimum area and contrast?
1032
+ 3. **Screen reader:** Have you tested with at least one screen reader (NVDA + Firefox, VoiceOver + Safari, or JAWS + Chrome)? Are all elements announced with correct names, roles, and states?
1033
+ 4. **Alt text:** Does every non-decorative image have a descriptive `alt` attribute? Are decorative images marked with `alt=""`?
1034
+ 5. **Labels:** Is every form field programmatically associated with a visible `<label>`? Are error messages associated via `aria-describedby`?
1035
+ 6. **Contrast:** Do all text/background color pairs meet 4.5:1 (normal text) or 3:1 (large text) contrast ratios?
1036
+ 7. **Zoom:** Does the page remain functional and readable at 200% browser zoom?
1037
+ 8. **Color independence:** Is every piece of information conveyed by color also conveyed by text, icon, or pattern?
1038
+ 9. **Semantic HTML:** Are you using native elements (`<button>`, `<a>`, `<nav>`, `<main>`, `<dialog>`, `<table>`) instead of ARIA-patched `<div>` elements?
1039
+ 10. **Dynamic content:** Are AJAX updates, notifications, and status changes announced via ARIA live regions?
1040
+ 11. **Time limits:** Can users extend, adjust, or disable any time-limited feature?
1041
+ 12. **Skip link:** Does a "Skip to main content" link appear as the first focusable element?
1042
+ 13. **Modals:** Do dialogs trap focus, release on Escape, and return focus to the trigger on close?
1043
+ 14. **Third-party widgets:** Have all embedded components (video players, maps, CAPTCHAs) been tested for keyboard and screen reader accessibility?
1044
+
1045
+ ---
1046
+
1047
+ ## Code Smell Quick Reference
1048
+
1049
+ | Smell | Likely Anti-Pattern | Fix |
1050
+ |-------|---------------------|-----|
1051
+ | `<div onclick="...">` | #2 Div soup, #11 No keyboard | Use `<button>` |
1052
+ | `outline: none` without replacement | #4 Missing focus indicator | Use `:focus-visible` with custom outline |
1053
+ | `tabindex="5"` (positive values) | #20 Focus order mismatch | Use `tabindex="0"` or restructure DOM |
1054
+ | `<img>` without `alt` | #1 Missing alt text | Add descriptive `alt` or `alt=""` for decorative |
1055
+ | `<input>` without `<label for="">` | #10 Inaccessible forms | Add associated `<label>` element |
1056
+ | `placeholder` as only label | #10 Inaccessible forms | Add visible `<label>`, keep placeholder as hint |
1057
+ | `color: #999` on `#fff` background | #12 Low contrast | Check contrast ratio, use 4.5:1 minimum |
1058
+ | `user-scalable=no` in viewport | #13 Non-resizable text | Remove, allow user zoom |
1059
+ | `:hover` without `:focus` | #14 Mouse-only interaction | Add `:focus` and `:focus-within` |
1060
+ | `role="menu"` on site nav | #6 ARIA misuse | Remove role or use `<nav>` with `<ul>` |
1061
+ | `aria-role="..."` | #6 ARIA misuse (wrong syntax) | Use `role="..."` |
1062
+ | `autoplay` without `muted` | #7 Auto-playing media | Add `muted` and visible controls |
1063
+ | `setTimeout` + redirect | #8 Time limits | Add warning and extension mechanism |
1064
+ | `<table>` without `<th>` | #19 Headerless tables | Add `<th scope="col/row">` and `<caption>` |
1065
+ | `<div class="modal">` | #18 Inaccessible modal | Use `<dialog>` or add `role="dialog"` + focus management |
1066
+ | DOM update without `aria-live` | #17 Silent dynamic content | Use `aria-live="polite"` or `role="alert"` |
1067
+ | No skip link in `<body>` | #9 Missing skip navigation | Add `<a href="#main">` as first child |
1068
+ | `border-color: red` as only error signal | #5 Color-only information | Add text message + icon + `aria-invalid` |
1069
+ | reCAPTCHA v2 without alternative | #16 Inaccessible CAPTCHA | Use reCAPTCHA v3 or Turnstile |
1070
+ | Scanned PDF without OCR | #15 PDF-only content | Provide HTML alternative or tagged PDF |
1071
+
1072
+ ---
1073
+
1074
+ ## Key Legal Cases and Regulatory Actions
1075
+
1076
+ | Case / Action | Year | Outcome | Key Lesson |
1077
+ |---|---|---|---|
1078
+ | **NFB v. Target Corp.** | 2006-2008 | $6 million settlement; Target required to make website accessible | First precedent: commercial websites must comply with ADA |
1079
+ | **Robles v. Domino's Pizza** | 2016-2022 | Supreme Court declined Domino's appeal; settled after 6 years | ADA applies to websites; screen reader access is required |
1080
+ | **Conner v. Parkwood Entertainment** (Beyonce.com) | 2019 | Class action for missing alt text, no keyboard access, broken navigation | Celebrity and entertainment sites are not exempt |
1081
+ | **Gil v. Winn-Dixie** | 2016-2022 | Initially won at trial; reversed on appeal; vacated as moot | Legal landscape is evolving but risk remains |
1082
+ | **FTC v. accessiBe** | 2025 | $1 million FTC settlement | Accessibility overlay widgets are not a compliance solution |
1083
+ | **4,000+ ADA lawsuits** | 2024 | 69% targeted eCommerce; 22.6% targeted sites with overlay widgets | Volume is accelerating; no industry is safe |
1084
+ | **2,014 ADA lawsuits (H1)** | 2025 | 37% increase over 2024; fines up to $115,231 first offense | Enforcement is intensifying year over year |
1085
+
1086
+ ---
1087
+
1088
+ ## Testing Toolkit
1089
+
1090
+ **Automated (catches ~30% of WCAG issues):**
1091
+ - axe-core / axe DevTools (browser extension)
1092
+ - Lighthouse accessibility audit (Chrome DevTools)
1093
+ - eslint-plugin-jsx-a11y (React/JSX linting)
1094
+ - Pa11y CI (CI/CD integration)
1095
+ - WAVE (WebAIM browser extension)
1096
+
1097
+ **Screen Readers (essential for the other ~70%):**
1098
+ - NVDA + Firefox (Windows, free)
1099
+ - JAWS + Chrome (Windows, commercial)
1100
+ - VoiceOver + Safari (macOS/iOS, built-in)
1101
+ - TalkBack + Chrome (Android, built-in)
1102
+
1103
+ **Contrast and Color:**
1104
+ - WebAIM Contrast Checker
1105
+ - Chrome DevTools color picker (shows ratio inline)
1106
+ - Stark (Figma/Sketch plugin)
1107
+
1108
+ **Keyboard Testing:**
1109
+ - Unplug mouse; navigate entire site with Tab, Shift+Tab, Enter, Space, Escape, Arrow keys
1110
+ - Check focus visibility at every step
1111
+
1112
+ ---
1113
+
1114
+ ## Sources
1115
+
1116
+ - [WebAIM Million 2025 Report](https://webaim.org/projects/million/)
1117
+ - [WebAIM: To ARIA! The Cause of, and Solution to, All Our Accessibility Problems](https://webaim.org/blog/aria-cause-solution/)
1118
+ - [Deque: WAI-ARIA Top 6 Mistakes to Avoid](https://www.deque.com/blog/wai-aria-top-6-mistakes-to-avoid/)
1119
+ - [W3C: Understanding WCAG 2.1 SC 2.1.2 No Keyboard Trap](https://www.w3.org/WAI/WCAG21/Understanding/no-keyboard-trap.html)
1120
+ - [W3C: Inaccessibility of CAPTCHA](https://www.w3.org/TR/turingtest/)
1121
+ - [BOIA: Missing Input Labels](https://www.boia.org/blog/missing-input-labels-how-to-fix-a-common-accessibility-issue)
1122
+ - [BOIA: Low Contrast Text Most Common Issue](https://www.boia.org/blog/low-contrast-text-remains-the-most-common-accessibility-issue-in-2023)
1123
+ - [BOIA: Skip Navigation Links](https://www.boia.org/blog/skip-navigation-links-avoiding-common-accessibility-mistakes)
1124
+ - [NFB v. Target Corp. Settlement](https://nfb.org/images/nfb/publications/bm/bm08/bm0809/bm080915.htm)
1125
+ - [Robles v. Domino's Pizza Settlement](https://www.boia.org/blog/the-robles-v.-dominos-settlement-and-why-it-matters)
1126
+ - [Conner v. Parkwood Entertainment (Beyonce.com)](https://www.billboard.com/music/music-news/beyonce-parkwood-entertainment-sued-website-accessibility-8492195/)
1127
+ - [Gil v. Winn-Dixie (11th Circuit)](https://adasoutheast.org/legal/court/gil-v-winn-dixie-2021/)
1128
+ - [FTC v. accessiBe ($1M Settlement)](https://www.ftc.gov/news-events/news/press-releases/2025/01/ftc-order-requires-online-marketer-pay-1-million-deceptive-claims-its-ai-product-could-make-websites)
1129
+ - [Accessibility.Works: ADA Lawsuit Trends 2024](https://www.accessibility.works/blog/ada-lawsuit-trends-statistics-2024-summary/)
1130
+ - [AudioEye: Website Accessibility in 2025](https://www.audioeye.com/post/website-accessibility-in-2025/)
1131
+ - [TPGi: The Current State of Modal Dialog Accessibility](https://www.tpgi.com/the-current-state-of-modal-dialog-accessibility/)
1132
+ - [Smashing Magazine: Accessibility Problem with CAPTCHA](https://www.smashingmagazine.com/2025/11/accessibility-problem-authentication-methods-captcha/)
1133
+ - [A11Y Collective: Keyboard Trap](https://www.a11y-collective.com/blog/keyboard-trap/)
1134
+ - [MDN: ARIA Live Regions](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Guides/Live_regions)
1135
+ - [WebAIM: Contrast and Color Accessibility](https://webaim.org/articles/contrast/)
1136
+ - [FT Product & Technology: An Outbreak of Accessibility Anti-Patterns](https://medium.com/ft-product-technology/an-outbreak-of-accessibility-anti-patterns-e73577242ee8)