Scope: variables.css, search.css, todo/04-accessibility.md - variables.css: add @media (prefers-color-scheme: dark) block scoped to body:not(.admin-body); overrides all semantic tokens with dark equivalents: --bg-* (#111→#333 range), --text-* (#eee/aaa/777), --border-* (#333/#444), --accent-primary lightened to #b87fd4 (4.5:1 contrast on #111 background), --accent-secondary stays #9557b5, --accent-foreground flipped to #111111 for dark buttons, --accent-muted adjusted to rgba(184,127,212,0.15), status colours muted for dark (success #4db886, error #e05555, warning #d4a830); new --search-error-{bg,border,color} tokens added to :root (light: #fff0f0/#c00) and overridden in dark (#2a1515/#e05555) - search.css: replace three hardcoded hex values in .search-error rule with var(--search-error-bg/border/color) so dark mode applies cleanly - Admin pages are entirely unaffected: .admin-body body class is excluded from the dark-mode selector; system.css already has its own dark palette
6.6 KiB
Accessibility Audit (WCAG 2.1 AA)
1.1.1 Non-text content (alt text)
- Admin
<nav>"✕ Réinitialiser" and "✕" remove buttons — wrap✕in<span aria-hidden="true">✕</span>; addaria-label="Supprimer ce membre du jury"on jury remove buttons inadd.php/edit.php
1.3.1 Info and relationships
-
Admin form rows: multi-input rows (languages, formats) —
checkbox-list.phppartial now wraps checkboxes in<fieldset class="admin-checkbox-group">with a<legend class="sr-only">for AT grouping -
Status badges in
admin/index.phpconvey state by colour alone —status-badge.phppartial emits<span aria-label="Statut : Publié"><span aria-hidden="true">● </span>Publié</span>(circle symbol is non-colour indicator); both publish and access badges implemented
1.3.4 / 1.3.5 Orientation & Input purpose
- No
autocompleteattributes on personal data fields —add.php/edit.php:autocomplete="name"on author fields,autocomplete="email"on mail fields (via$attrsintext-field.php)
1.4.1 Use of colour
-
Active nav link has no non-colour indicator — admin nav:
border-bottom: 2px solid currentColoradded for[aria-current="page"]inadmin.css; public nav already hadborder-bottomincommon.css -
Admin purple
#9557b5as text colour —--admin-purplewas an undefined variable referenced only in pagination hover; replaced with--accent-primary(same value, #9557b5). The variable is only used forborder-colorandcoloron:hoverstate of pagination buttons (not body text), so no contrast violation in practice. Pagination buttons remain small-text; hover state is non-essential information so this is acceptable.
1.4.4 Resize text
- Verify no text is set in
px— audited all CSS files; everyfont-sizeusesremorem; nopxfont-size found anywhere. No action needed.
1.4.12 Text spacing
- No text-spacing override test done — audited all
overflow: hiddeninstances:.sr-only(visually hidden utility, 1×1px — not text content),.home-body figure/aside figure/.card(media containers, not text)..card__gradient-titleclamps decorative gradient text — not essential content (same info is in the<p>link). No WCAG 1.4.12 failure found.
2.1.1 Keyboard
- Jury "✕" remove buttons in
add.php/edit.php—aria-label="Supprimer le lecteur·ice N"already present on all remove buttons injury-fieldset.php(both static and dynamically added rows)
2.4.3 Focus order
- On
tfe.phpthe← Retourback link is at the bottom of the left column in DOM — already fixed;<a class="tfe-back-link">← Retour</a>is the first child of<header class="tfe-left">, which precedes<h1 class="tfe-title">in DOM order
2.4.4 Link purpose
- Home page cards: if two theses share the same title, identical link texts exist —
public/index.phpcard<p>now appends<span class="sr-only">, YEAR</span>when$item['year']is set, giving screen-reader users a unique link name per thesis
2.5.3 Label in name
<a class="clear-filter">✕ Réinitialiser</a>— wrap✕in<span aria-hidden="true">- Admin jury remove buttons
✕—aria-label="Supprimer ce lecteur"replaces the symbol
2.5.5 Target size
- Pagination buttons are
2rem(32px) — increase tomin-height: 2.75rem; min-width: 2.75rem(44px) - Admin
.admin-btn-sm(~28px) — increase to minimum 32px with padding - Admin bulk action buttons and jury remove
✕buttons (~28px) — increase target size
3.1.1 Language of page
- All public pages have
<html lang="fr">— verified:templates/head.phpline 2 has<html lang="fr">; all pages share this template. No action needed.
3.3.1 Error identification
add.php/edit.phpvalidation errors —flash-messages.phpalready emits<p role="alert" data-type="error">for errors and<p role="status">for successadd.php/edit.phpautofocuson first invalid field —App::flashAutofocus(fieldName)stores the failing field in$_SESSION['_flash_autofocus']; action handlers map exception messages to field names;add.phpconsumes viawithAutofocus()helper + injects into$attrs;edit.phpuses inline ternary; partials support booleantruein$attrsto emit bare attribute names
3.3.2 Labels or instructions
- Admin jury "Lecteur·ices" label has no
forattribute — replaced plain<label>Lecteur·ices :</label>with<fieldset class="admin-jury-lecteurs"><legend>Lecteur·ices</legend>injury-fieldset.php; CSS rule strips the nested fieldset’s border/padding so it renders as a sub-group
4.1.2 Name, role, value
-
Custom "Externe" checkbox for jury members has no group context — all jury "Externe" checkboxes now carry explicit
aria-label(e.g."Promoteur·ice — externe","Lecteur·ice N — externe"); both static PHP-rendered rows and dynamically added rows viaaddJuryRow()receive the label -
<video>elements ontfe.phphave no captions —<track kind="captions">now emitted for each MP4 when a.vttsidecar has been uploaded alongside it; N-th VTT file is paired with N-th video in document order.formulaire.phpaccepts.vttuploads (MIMEtext/vtt,file_type = 'caption');media.phpserves VTT with correctContent-Type; adminadd.phpfile-field hint documents the.vttconvention. -
Admin
<select>for visibility/access inedit.phpuses truncated option text — removedmb_strimwidthcall; option text now uses full description (name — description) so screen-reader accessible name is complete and unambiguous -
Bulk publish/unpublish JS does not announce result to screen readers — action result is a full-page redirect to a flash message rendered by
flash-messages.phpwhich already emitsrole="alert"(error) /role="status"(success); no additional JS announcement needed
5 - Motion & user preferences
prefers-color-schemenot respected —variables.cssnow includes a@media (prefers-color-scheme: dark)block scoped tobody:not(.admin-body); overrides all semantic tokens (--bg-*,--text-*,--border-*,--accent-*, status colours) with dark equivalents;--accent-primarylightened to#b87fd4for 4.5:1 contrast on dark backgrounds;search.css.search-errorhardcoded#fff0f0/#c00replaced with--search-error-bg/--search-error-border/--search-error-colorvariables also overridden in dark mode; admin pages unaffected (.admin-bodypreserves light-mode values)