perf+a11y: WAL mode for SQLite, skip links, :focus-visible, .sr-only

SQLite performance (Database::__construct):
- PRAGMA journal_mode = WAL: eliminates full-DB read locks on write, safe
  for concurrent PHP-FPM workers
- PRAGMA synchronous = NORMAL: durable on commit without full fsync per write
- PRAGMA cache_size = -8000: ~8 MB page cache per connection

Accessibility foundation (WCAG 2.1 AA):
- common.css: add .sr-only utility, .skip-link (hidden until focused),
  global :focus-visible (2px purple outline, 2px offset),
  prefers-reduced-motion guard; remove bare outline:none from
  .site-search__input
- admin.css: same :focus-visible, skip-link, and motion guard scoped to
  admin purple; remove outline:none from .admin-input/.admin-select/
  .admin-textarea and .admin-filters select (both had :focus border rules
  already, so focus is still visually communicated)
- search.css: remove outline:none from .search-filter-select (already has
  :focus border-color rule)
- All 5 public pages (index, search, tfe, apropos, licence): add
  <a href="#main-content" class="skip-link"> as first child of <body>;
  add id="main-content" to <main>
- templates/admin/head.php: same skip link; aria-label="Navigation admin"
  on <nav>; id="main-content" on all 10 admin <main> elements

All 4 test suites pass (unit, integration, security, rate-limit).
This commit is contained in:
Pontoporeia
2026-03-27 13:45:01 +01:00
parent a9877b1d1d
commit 42af4644c5
23 changed files with 128 additions and 45 deletions

31
TODO.md
View File

@@ -347,7 +347,7 @@ Goal: rename the tables and column to the canonical M2M pattern (`tags`, `thesis
### A — SQLite / Query performance
- [ ] **WAL mode** — set `PRAGMA journal_mode = WAL` and `PRAGMA synchronous = NORMAL` in `Database::__construct()` after `foreign_keys = ON`.
- [x] **WAL mode** — set `PRAGMA journal_mode = WAL` and `PRAGMA synchronous = NORMAL` in `Database::__construct()` after `foreign_keys = ON`.
Eliminates full-database read-locks on every write; makes concurrent PHP-FPM workers safe.
Also add `PRAGMA cache_size = -8000` (≈8 MB page cache) while there.
@@ -1308,27 +1308,14 @@ Current state: **zero ARIA attributes, zero skip links, zero focus-visible style
These are things that must be added once and apply everywhere:
- [ ] **Add `.sr-only` utility class to `common.css`** — needed for skip links, visually-hidden
labels, and screen-reader-only context text referenced throughout this audit:
```css
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0,0,0,0);
white-space: nowrap;
border: 0;
}
```
- [x] **Add `.sr-only` utility class to `common.css`** — needed for skip links, visually-hidden
labels, and screen-reader-only context text referenced throughout this audit.
- [ ] **Add skip-to-content link in all page templates** — as described in 2.4.1 above. This
one change has the highest impact-per-line-of-code ratio of any item in this audit.
- [x] **Add skip-to-content link in all page templates** — added to all 5 public pages and
admin head template; `id="main-content"` added to every `<main>` in the codebase.
- [ ] **Add global `:focus-visible` rule in `common.css` and `admin.css`** — as described in
2.4.7. Second highest impact item.
- [x] **Add global `:focus-visible` rule in `common.css` and `admin.css`** — consistent
2px purple outline with 2px offset; `prefers-reduced-motion` guard also added.
- [ ] **Remove all `outline: none` declarations that have no replacement focus style** —
`common.css:125`, `admin.css:121`, `admin.css:323`, `search.css:241`.
- [x] **Remove all `outline: none` declarations that have no replacement focus style** —
removed from `common.css`, `admin.css` (×2), and `search.css`.