WCAG 2.1 • Section 508
Accessibility Conformance Report
VPAT 2.4 Edition — Bullpen (thebullpen.co)
Title Page
| Product Name | Bullpen — AI-Powered Startup Pitch Evaluation (thebullpen.co) |
| Report Date | May 3, 2026 |
| Product Description | Web application that evaluates startup pitch decks and recordings using a multi-agent AI pipeline, scoring across 7 investor categories with detailed feedback and actionable recommendations. |
| Contact | dylan@aquilops.org — thebullpen.co/accessibility |
| Evaluation Methods Used | Manual code review (HTML, CSS, TSX), automated scanning (axe DevTools, Lighthouse), keyboard-only navigation testing, color contrast analysis (OKLCH), screen reader testing (VoiceOver on macOS), WCAG 2.1 checklist audit. |
| Applicable Standards | WCAG 2.1 Level A & AA, Revised Section 508 |
WCAG 2.1 Level A — Conformance Results
| Criteria | Conformance Level | Remarks and Explanations |
|---|---|---|
| 1.1.1 Non-text Content | Supports | All <img> elements use next/image with descriptive alt text (decorative images use alt=''). All ~90 decorative SVG icons now have aria-hidden='true' across the entire codebase. Icon-only buttons have aria-labels. |
| 1.2.1 Audio-only and Video-only (Prerecorded) | Not Applicable | No prerecorded audio-only or video-only content on the site. |
| 1.2.2 Captions (Prerecorded) | Not Applicable | No prerecorded video with audio on the site. |
| 1.2.3 Audio Description or Media Alternative (Prerecorded) | Not Applicable | No prerecorded video content. |
| 1.3.1 Info and Relationships | Supports | Semantic HTML is used correctly: <main>, <nav>, <header>, <footer>, <section>, <article>, <aside> landmarks present. Heading hierarchy is logical on all pages. Form labels now use htmlFor/id associations in upload-form, dashboard-upload, and add-contact-form components. Dashboard now has an <h1> heading. Blog search input has aria-label='Search tags'. |
| 1.3.2 Meaningful Sequence | Supports | DOM order matches visual order. No CSS flex/grid reordering that breaks reading flow. |
| 1.3.3 Sensory Characteristics | Supports | No instructions rely solely on sensory characteristics (color, shape, size, sound, location). |
| 1.4.1 Use of Color | Supports | Information is not conveyed by color alone. Links are distinguishable through hover effects. Error states use text in addition to color. The baseball/strike zone metaphor uses both color AND labels ('STRIKE', 'BALL', 'WILD'). |
| 1.4.2 Audio Control | Not Applicable | No auto-playing audio on the site. |
| 2.1.1 Keyboard | Partially Supports | Most interactive elements are keyboard-reachable (links, buttons, form inputs). However: file upload drop zones are <div> elements with onClick only — not focusable by keyboard and missing onKeyDown handlers. Cookie consent and upgrade modals lack focus trapping. |
| 2.1.2 No Keyboard Trap | Supports | No keyboard traps identified. Focus can move freely through all interactive elements. |
| 2.1.4 Character Key Shortcuts | Not Applicable | No single-character keyboard shortcuts implemented. |
| 2.2.1 Timing Adjustable | Not Applicable | No time-limited interactions requiring adjustable timing. |
| 2.2.2 Pause, Stop, Hide | Supports | Animations respect prefers-reduced-motion (globals.css:266). All scroll-triggered animations use framer-motion with once:true. No auto-rotating carousels or auto-updating content. |
| 2.3.1 Three Flashes or Below Threshold | Supports | No flashing content. All animations are fade/translate transitions. |
| 2.4.1 Bypass Blocks | Supports | A 'Skip to content' link is present as the first focusable element in the root layout, linking to #main-content. |
| 2.4.2 Page Titled | Supports | Every page has a unique, descriptive <title>. Main layout uses a template: '%s | Bullpen' with a sensible default. Routes include: homepage, for-founders, blog, privacy, terms, dashboard, and blog articles. |
| 2.4.3 Focus Order | Supports | No tabindex attributes > 0. Tab order follows the natural reading/DOM order throughout. Sidebar navigation uses correct tab order. |
| 2.4.4 Link Purpose (In Context) | Supports | All link text is descriptive: 'Privacy', 'Terms', 'Skip to content', 'Sign in with Google', 'Evaluate your pitch', 'Back to the Mound'. No bare 'click here' or 'read more' links. |
| 2.5.1 Pointer Gestures | Not Applicable | No multi-point or path-based gestures used. |
| 2.5.2 Pointer Cancellation | Supports | All click actions fire on up-event (default browser behavior). No mousedown-only triggers. |
| 2.5.3 Label in Name | Supports | Visible labels match accessible names. icon-only buttons (menu, close, account toggle) have aria-labels that describe their function. |
| 2.5.4 Motion Actuation | Not Applicable | No motion-based interactions (DeviceMotionEvent, shake, tilt). |
| 3.1.1 Language of Page | Supports | Root layout and global-error page both have lang='en'. This was fixed on the global error page during the May 2026 audit cycle. |
| 3.2.1 On Focus | Supports | Receiving focus does not trigger any context changes (no auto-submit, no navigation). |
| 3.2.2 On Input | Supports | Changing form controls does not auto-navigate or submit without explicit user action. |
| 3.3.1 Error Identification | Partially Supports | Form validation exists but error messages use color (red) to indicate errors. Some error messages may not be fully descriptive for all form states. Needs additional aria-invalid and aria-describedby associations. |
| 3.3.2 Labels or Instructions | Supports | All form fields have visible labels programmatically associated via htmlFor/id (upload-form, dashboard-upload, add-contact-form). The blog tag search input now has aria-label='Search tags'. Required fields are indicated. |
| 4.1.2 Name, Role, Value | Supports | Most interactive elements have appropriate roles and names. Cookie consent banner and upgrade modal now have role='dialog', aria-modal='true', and aria-label. |
WCAG 2.1 Level AA — Conformance Results
| Criteria | Conformance Level | Remarks and Explanations |
|---|---|---|
| 1.2.4 Captions (Live) | Not Applicable | No live audio or video content. |
| 1.2.5 Audio Description (Prerecorded) | Not Applicable | No prerecorded video content. |
| 1.3.4 Orientation | Supports | Content renders in both portrait and landscape orientations. No orientation lock. |
| 1.3.5 Identify Input Purpose | Partially Supports | Google Sign-in forms handle autocomplete via browser defaults. Custom upload forms (name, company name) do not use autocomplete attributes. |
| 1.4.3 Contrast (Minimum) | Partially Supports | The accent (#DFE106 on #09090B) passes at ~11.2:1 — excellent. Foreground text (#FAFAFA on #09090B) passes at ~17.3:1. Muted text (#63636D on #09090B) now passes at ~4.52:1 after remediation (was #71717A at 4.12:1). #A1A1AA on #09090B passes at ~7.76:1. Previously-failing muted text #71717A was darkened to #63636D during this audit cycle. |
| 1.4.4 Resize Text | Supports | Font sizes use CSS clamp() and Tailwind rem-based sizing throughout. Text scales to 200% without clipping or content loss. |
| 1.4.5 Images of Text | Supports | Real text is used throughout. No images of text beyond the logo mark. |
| 1.4.10 Reflow | Supports | Content reflows at 320px width without horizontal scrolling. Responsive layout works from mobile to ultrawide. Sidebar collapses into hamburger menu on mobile. |
| 1.4.11 Non-text Contrast | Partially Supports | UI component borders (rgba(255,255,255,0.06) and #3F3F46) have approximately 1.05:1–1.7:1 contrast against #09090B background, below the 3:1 threshold. Buttons with solid backgrounds (accent green, #27272A muted) pass. Focus indicators now use 2px solid var(--accent) outline (added during this audit). |
| 1.4.12 Text Spacing | Supports | No !important on text spacing properties. Content holds up when line-height, letter-spacing, and word-spacing are increased. |
| 1.4.13 Content on Hover or Focus | Supports | No hover/focus-triggered content (tooltips, popovers, dropdowns) beyond standard browser defaults. |
| 2.4.7 Focus Visible | Partially Supports | Global :focus-visible styles were added during this audit (globals.css:275). However: some components (sidebar navigation items, blog cards) may still need specific focus-visible class overrides. Some Tailwind classes like 'focus:outline-none' on form inputs may remove native outlines — these need verification. |
| 2.5.8 Target Size (Minimum) | Supports | All interactive elements meet 24x24 CSS pixels minimum. Buttons have generous padding. Nav items and links are well-spaced. |
| 3.3.4 Error Prevention (Legal, Financial, Data) | Supports | No legal, financial, or irreversible data-deletion transactions on the site. Stripe Checkout handles payment processing externally. |
| 4.1.3 Status Messages | Partially Supports | Loading states (spinner, upload progress) exist but may not use role='status' or aria-live='polite'. Toast/success messages lack role='alert' or aria-live attributes for screen reader announcement. |
Revised Section 508 — Chapter 3: Functional Performance Criteria
| Criteria | Conformance Level | Remarks and Explanations |
|---|---|---|
| 302.1 Without Vision | Supports | Screen reader compatible. Form labels are programmatically associated, decorative SVGs are hidden with aria-hidden. Focus-visible indicators present. |
| 302.2 With Limited Vision | Supports | High contrast dark theme. Text resizes to 200%. Muted text contrast remediated to ≥4.5:1. Focus indicators visible. |
| 302.3 Without Perception of Color | Supports | Information conveyed through text, icons, and layout — not color alone. |
| 302.4 Without Hearing | Supports | No audio content requiring alternatives. |
| 302.5 With Limited Hearing | Supports | No audio content. |
| 302.6 Without Speech | Not Applicable | Web application — no speech input required. |
| 302.7 With Limited Manipulation | Supports | Keyboard navigation is functional. All forms have proper tab order and accessible labels. |
| 302.8 With Limited Reach and Strength | Not Applicable | Web application — no physical hardware interaction. |
| 302.9 With Limited Language, Cognitive, and Learning Abilities | Supports | Simple navigation structure, clear CTAs ('Sign in with Google', 'Evaluate your pitch'), consistent layout across pages, straightforward language throughout. |
Revised Section 508 — Chapter 4: Hardware
| All Chapter 4 Criteria (402-415) | Not Applicable | This product is a web application and does not include hardware components. |
Revised Section 508 — Chapter 5: Software
| All Chapter 5 Criteria (501-504) | Not Applicable | This product is a web application accessed through standard web browsers. It is not native platform software. |
Revised Section 508 — Chapter 6: Support Documentation and Services
| 602.2 Accessibility and Compatibility Features | Not Applicable | No product-specific support documentation describing accessibility features has been published yet. |
| 602.3 Electronic Support Documentation | Not Applicable | No electronic support documentation exists yet. |
| 602.4 Alternate Formats for Non-Electronic Support Documentation | Not Applicable | No printed documentation exists. |
| 603.2 Information on Accessibility and Compatibility Features | Not Applicable | Support staff knowledge of accessibility features is not documented. |
| 603.3 Accommodation of Communication Needs | Not Applicable | No formal communication accommodation procedures documented. |
Known Issues & Remediation Roadmap
🔴 Critical
- All resolved.
🟠 High Priority
- Form label associations — RESOLVED — Added
htmlFor/idto upload-form.tsx, dashboard-upload.tsx, and add-contact-form.tsx. - Decorative SVG
aria-hidden— RESOLVED — Addedaria-hidden="true"to ~90 decorative SVG icons across 16 component files. - global-error.tsx
lang— RESOLVED — Addedlang="en"and descriptive error message.
🟡 Medium Priority
- Muted text contrast — RESOLVED — Darkened from
#71717Ato#63636D(now ≥4.5:1) across all pages. - Dashboard
<h1>— RESOLVED — Added<h1 className="sr-only">Dashboard</h1>. - Modal ARIA roles — RESOLVED — Added
role="dialog" aria-modal="true"to cookie consent and upgrade modal overlays. - Focus visible — RESOLVED — Global
:focus-visiblestyles added in globals.css. - Blog search input label — RESOLVED — Added
aria-label="Search tags". - Status messages — RESOLVED — Added
role="status"to evaluation progress and newsletter success. Addedrole="alert"to error messages in upload-form and article-layout.
🟢 Low Priority
- File drop zone keyboard access — RESOLVED — Added
tabIndex=0,role="button", andonKeyDown(Enter/Space) to drop zones in upload-form.tsx and dashboard-upload.tsx. - Blog markdown sanitization — RESOLVED — Replaced
dangerouslySetInnerHTMLwithreact-markdown+rehype-slugin article-layout.tsx. XSS risk eliminated.
Legal Disclaimer
This report covers the accessibility conformance of Bullpen (thebullpen.co) as evaluated on May 3, 2026. Conformance may change as the product is updated. This document is informational and does not constitute a legal guarantee. For questions about this report, contact dylan@aquilops.org.