From ca8081575cbb14323edb68724ab4623dfeea7da0 Mon Sep 17 00:00:00 2001 From: Pontoporeia Date: Mon, 6 Apr 2026 14:45:44 +0200 Subject: [PATCH] Add prefers-color-scheme dark mode for public pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- TODO.md | 3 +++ public/assets/css/search.css | 6 ++--- public/assets/css/variables.css | 39 +++++++++++++++++++++++++++++++++ todo/04-accessibility.md | 2 +- 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/TODO.md b/TODO.md index 98daa4e..7ad9686 100644 --- a/TODO.md +++ b/TODO.md @@ -11,6 +11,9 @@ Pending tasks have been split into topic files under [`todo/`](todo/README.md): ## Recently completed (this session) +- [x] `variables.css` + `search.css` — public dark-mode support via `@media (prefers-color-scheme: dark)` scoped to `body:not(.admin-body)`: all semantic tokens (`--bg-*`, `--text-*`, `--border-*`, `--accent-*`, status colours) overridden with dark equivalents; `--accent-primary` lightened to `#b87fd4` for WCAG contrast on dark backgrounds; `--search-error-*` variables added to replace hardcoded `#fff0f0`/`#c00` in `.search-error`; admin pages unaffected + + - [x] `src/ThesisCreateController.php` — extracted all validation, DB writes, and file-upload handling from `admin/actions/formulaire.php` into a dedicated controller; `make()` factory instantiates `Database`; `loadFormData()` returns all lookup tables for the add-form view; `submit(post, files)` runs the full creation flow: validates/sanitises all POST fields, calls `findOrCreateAuthor`, inserts thesis row via `createThesis`, links jury/languages/formats/tags inside a transaction, then processes cover image, banner, and multi-file uploads outside the transaction; `autofocusFieldForError()` maps exception messages to WCAG 3.3.1 autofocus field hints; `actions/formulaire.php` reduced 346→45 lines (CSRF guard + one `submit()` call); `admin/add.php` lookup-table block replaced with `ThesisCreateController::make()->loadFormData()`; `Database::setPublished()` and `Database::bulkSetPublished()` added, eliminating raw SQL from `actions/publish.php` (100→65 lines); no raw PDO calls remain in any action handler file - [x] `src/HomeController.php` — extracted all data-fetching logic from `public/index.php` into a dedicated controller class; `create()` returns a ready instance with `Database` singleton injected; `handle()` parses `page`/`year` GET params, determines display mode (default-random-latest / year-filtered / paginated-all), runs the appropriate DB queries (`getLatestPublishedYear`, `getLatestYearTheses`, `searchTheses`+`countSearchResults`, `getPublishedTheses`+`countPublishedTheses`), batch-loads cover images via `getCoverPathsForTheses`, assembles OG/meta tags, and returns a flat view-variable array; `public/index.php` reduced 100→71 lines (6-line dispatcher + pure view template); `todo/02-php-components.md` “Extract remaining controllers” task marked done diff --git a/public/assets/css/search.css b/public/assets/css/search.css index fc51cc0..df6d437 100644 --- a/public/assets/css/search.css +++ b/public/assets/css/search.css @@ -306,9 +306,9 @@ /* Error message */ .search-error { - background: #fff0f0; - border-left: 3px solid #c00; - color: #c00; + background: var(--search-error-bg); + border-left: 3px solid var(--search-error-border); + color: var(--search-error-color); padding: 0.5rem 1rem; font-size: 0.88rem; margin: 0.5rem 1.5rem; diff --git a/public/assets/css/variables.css b/public/assets/css/variables.css index c8efa35..73a9d59 100644 --- a/public/assets/css/variables.css +++ b/public/assets/css/variables.css @@ -2,6 +2,7 @@ CSS VARIABLES (CUSTOM PROPERTIES) ============================================================ */ +/* ── Light mode (default) ─────────────────────────────────────────────── */ :root { --bg-primary: #ffffff; --bg-secondary: #f5f5f5; @@ -27,4 +28,42 @@ --gradient-2: #60ECB4; --gradient-3: #E390FF; --gradient-4: #9557B5; + + /* Search error block (public only, overridden in dark mode) */ + --search-error-bg: #fff0f0; + --search-error-border: #c00; + --search-error-color: #c00; +} + +/* ── Dark mode — public pages only (.admin-body keeps light vars) ─────── */ +@media (prefers-color-scheme: dark) { + body:not(.admin-body) { + --bg-primary: #111111; + --bg-secondary: #1a1a1a; + --bg-tertiary: #252525; + --bg-active: #333333; + + --text-primary: #eeeeee; + --text-secondary: #aaaaaa; + --text-tertiary: #777777; + + --border-primary: #333333; + --border-secondary: #444444; + + /* Accent hue lightened for contrast on dark bg (4.5:1 against #111) */ + --accent-primary: #b87fd4; + --accent-secondary: #9557b5; + --accent-foreground: #111111; + --accent-muted: rgba(184, 127, 212, 0.15); + + /* Status colours — slightly muted on dark */ + --success: #4db886; + --error: #e05555; + --warning: #d4a830; + + /* Search error block */ + --search-error-bg: #2a1515; + --search-error-border: #e05555; + --search-error-color: #e05555; + } } diff --git a/todo/04-accessibility.md b/todo/04-accessibility.md index d1063e7..f9d4d08 100644 --- a/todo/04-accessibility.md +++ b/todo/04-accessibility.md @@ -76,4 +76,4 @@ ## 5 - Motion & user preferences -- [ ] **`prefers-color-scheme` not respected** — site has fixed white public / fixed dark admin themes; consider a dark-mode variant for public pages (not a WCAG failure, but quality-of-life) +- [x] **`prefers-color-scheme` not respected** — `variables.css` now includes a `@media (prefers-color-scheme: dark)` block scoped to `body:not(.admin-body)`; overrides all semantic tokens (`--bg-*`, `--text-*`, `--border-*`, `--accent-*`, status colours) with dark equivalents; `--accent-primary` lightened to `#b87fd4` for 4.5:1 contrast on dark backgrounds; `search.css` `.search-error` hardcoded `#fff0f0`/`#c00` replaced with `--search-error-bg`/`--search-error-border`/`--search-error-color` variables also overridden in dark mode; admin pages unaffected (`.admin-body` preserves light-mode values)