This page is the project baseline. The thirteen rules below are the Accessibility Specialist peer-review requirements.
Baseline
1. Skip link to main content (visible on focus)
Every page starts with Skip to main content, injected as the first child of <body>. It is clipped until focused, then shown as a fixed control above other chrome. The target is <main id="quarto-document-content" tabindex="-1"> so keyboard focus actually moves.
Blocker if missing, not first, or not visible on focus.
2. One h1 per page; heading outline only
The Quarto page title is the only h1 and the first heading in the document. Body headings start at ##. Do not fake headings with bold, font-size, or colour. Callout titles are labels, not outline headings. The right-hand TOC label (“On this page”) is a styled paragraph, not an h2, so it cannot steal the outline ahead of the page title.
Blocker if a page has no h1, more than one h1, a heading before the page h1, or a skipped heading level.
3. Landmark structure
Required landmarks: header, nav, main, footer. There is one banner: the site chrome (#quarto-header, named “Site”). The page title block is a div, not a second <header>. Multiple nav elements are named:
The navbar collapse control is a native button with aria-expanded / aria-controls. It must not have role="menu" (that role is for menu widgets, not a disclosure).
The current page is indicated by aria-current="page" plus underline/weight plus visually hidden “(current page)” — not colour alone. Home uses aria-current on the site title. 404 is exempt.
Blocker if a landmark is missing, a nav is unnamed, or the current page is colour-only.
4. Visible :focus-visible rings
Do not remove outlines. styles.scss sets a 3px ember (#C8653A) outline plus a white/ember double box-shadow. Ember on cream is about 3.5:1 and ember on forge purple is about 4.5:1, so the ring stays ≥3:1 on both the light page and the dark navbar. Ember is not used for body text.
Blocker if a control we added has outline: none without a visible replacement.
5. prefers-reduced-motion
scroll-behavior is auto. Quarto’s sticky/headroom header is unstuck and de-animated in CSS — hide-on-scroll is not essential. Any future timeline or animation must honour prefers-reduced-motion. There is no JavaScript timeline.
High if essential information is conveyed only by motion.
6. Reflow at 200% zoom / ~320px width
The header is static, not sticky, so chrome cannot cover wrapped text. Body text uses overflow-wrap. Wide tables may scroll inside a .table-scroll region (role="region", tabindex="0", named as a horizontally scrollable table); the page’s prose must not require horizontal scrolling. The Timeline page also has a short note that the grid scrolls sideways on small screens. Navbar items collapse to a hamburger below large breakpoints. Toggle controls are at least 44×44 px.
Blocker if text requires horizontal scrolling or sticky chrome eats content at ~320px or 200% zoom.
7. Descriptive link names
Forbidden sole labels: “click here”, “here”, “read more”, “more”, “link”, “this”. External destinations get visually hidden “(external site)”. PDFs get “(PDF)”. Do not use a bare URL as the only link name.
Blocker if a generic or empty link name ships.
8. Contrast and status
Source and timeline statuses are visible text inside a bordered .status-label. Do not encode status by colour alone.
Blocker if status is colour-only or body text fails 4.5:1.
9. Tables
Timeline and catalogue views are real <table> elements with <caption>, <thead>, and scope="col" headers. Do not invent role="grid". A CSS-only card layout is not a substitute for these data tables.
Blocker if a data table lacks a caption/headers or uses grid roles.
11. Images and diagrams
Meaningful images need descriptive alt. Decorative images use alt="". Do not put critical history only in an image. The navbar carries a decorative jordanforge corner mark (alt=""). The maker relationship is the footer link “A jordanforge.ca project”, not the image.
Blocker if an <img> is missing an alt attribute.
12. Quarto theme and in-repo CSS
- Theme: Quarto
default (Bootstrap) + styles.scss.
styles.scss is grouped by baseline rule number. Treat it as the a11y override file.
scripts/post_render.py patches landmark names, skip target, current page, table captions, external-link text, TOC title demotion, navbar role="menu" removal, single banner landmark, and contained table overflow after each render.
High if a theme or custom widget removes focus styles or adds inaccessible chrome.
13. Comfortable default body text
Do not ship tiny theme defaults. Root/body text is 18px / 1rem with line-height 1.6 ($font-size-root: 18px in styles.scss). Never drop body text below ~16px. There is no in-page text-size widget — simplicity over novelty. Browser zoom to 200% must remain usable (see rule 6).
High if default body text is under ~16px or 200% zoom breaks reading.