Accessibility
Workshopr targets WCAG AA compliance. Every interactive element must be keyboard-accessible, clearly focused, and properly labeled.
Requirements at a Glance
contrast
Color Contrast
WCAG AA: 4.5:1 for normal text, 3:1 for large text (18px+ bold or 24px+ regular).
center_focus_strong
Focus Visibility
box-shadow: 0 0 0 3px {app-light-color} on all interactive elements. Never use outline: none without a replacement.
touch_app
Touch Targets
Minimum 44x44px on mobile for all tap targets (buttons, links, form controls).
label
Form Labels
All inputs must have associated
image
Icon Semantics
Standalone icons get aria-label. Decorative icons get aria-hidden="true".
animation
Motion
All transitions under 300ms with ease curve. No bouncy/spring effects. Respect prefers-reduced-motion.
phone_iphone
iOS Safe Areas
Fixed elements use env(safe-area-inset-top) and env(safe-area-inset-bottom).
Color Contrast Checks
Key text/background pairs and their approximate contrast ratios.
| Pair | Text | Background | Ratio | Pass? |
|---|---|---|---|---|
| Ink on Page | #2C2416 |
#FEF7F1 |
~12.5:1 | AAA |
| Ink Secondary on Page | #5C5242 |
#FEF7F1 |
~6.8:1 | AA |
| Ink Muted on Page | #78716C |
#FEF7F1 |
~4.5:1 | AA |
| White on Primary Red | #FFFFFF |
#E54D4D |
~3.5:1 | AA Large |
| White on Navy | #FFFFFF |
#1A2744 |
~14.2:1 | AAA |
| Ink Faint on Page | #A8A29E |
#FEF7F1 |
~2.8:1 | Decorative only |
warning
--color-ink-faint (#A8A29E) does not meet AA contrast on cream backgrounds. Use only for decorative text, disabled states, or placeholders -- never for essential content.
Focus States
Every interactive element gets a visible focus ring using box-shadow.
/* Standard focus ring */
:focus-visible {
outline: none;
box-shadow: 0 0 0 3px var(--mainsite-light); /* #FEE2E2 */
}
/* Per-app variants */
.planner :focus-visible { box-shadow: 0 0 0 3px var(--planner-very-light); }
.coach :focus-visible { box-shadow: 0 0 0 3px var(--coach-very-light); }
Do: Use box-shadow for focus
box-shadow doesn't affect layout and works with border-radius.
Don't: Remove outline with nothing
outline: none without a replacement makes elements invisible to keyboard users.
Touch Targets
44px
Minimum Target
Required on mobile
48px
Recommended
Comfortable tap area
ARIA Patterns
Icons
<!-- Standalone icon (meaningful) -->
<button aria-label="Delete item">
<span class="material-symbols-outlined">delete</span>
</button>
<!-- Decorative icon (ignored by screen readers) -->
<span class="material-symbols-outlined" aria-hidden="true">schedule</span>
<span>30 min</span>
Modals
<div role="dialog" aria-modal="true" aria-labelledby="modal-title">
<h2 id="modal-title">Confirm Action</h2>
<!-- content -->
</div>
Reduced Motion
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}