[PR #1894] [MERGED] feat(website): follow the system dark mode and fix small-screen text #4888

Closed
opened 2026-10-31 00:56:27 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/1894
Author: @CassieFox23
Created: 10/11/2026
Status: ✅ Merged
Merged: 10/11/2026
Merged by: @morluto

Base: main ← Head: feat/website-dark-mode-upstream


📝 Commits (9)

  • 2122cdd fix(website): keep text inside small screens and tidy small type and spacing
  • 4a840d6 feat(website): follow the system dark mode
  • 6f0c4de feat(website): give the five SVG figures a dark scheme
  • 754f3ec chore(website): refresh translation source references
  • fb59ba8 fix(website): keep inline step highlights inline
  • 4f25251 test(website): check every page offers light and dark theme colors
  • b9ef65d fix(website): draw the dinosaur game in the page colors
  • 5f907ed fix(website): recolor the Touhou flywheel arrows in dark mode
  • 9e0e445 fix(website): redraw the dinosaur game when the system theme changes

📊 Changes

46 files changed (+32440 additions, -32063 deletions)

View changed files

📝 scripts/test-website.py (+16 -0)
📝 website/locales/ar/messages.po (+1687 -1687)
📝 website/locales/de/messages.po (+1687 -1687)
📝 website/locales/es/messages.po (+1687 -1687)
📝 website/locales/fa/messages.po (+1687 -1687)
📝 website/locales/fr/messages.po (+1687 -1687)
📝 website/locales/id/messages.po (+1687 -1687)
📝 website/locales/it/messages.po (+1687 -1687)
📝 website/locales/ja/messages.po (+1687 -1687)
📝 website/locales/ko/messages.po (+1687 -1687)
📝 website/locales/messages.pot (+1633 -1633)
📝 website/locales/pl/messages.po (+1687 -1687)
📝 website/locales/pt-BR/messages.po (+1687 -1687)
📝 website/locales/ru/messages.po (+1687 -1687)
📝 website/locales/th/messages.po (+1687 -1687)
📝 website/locales/tr/messages.po (+1687 -1687)
📝 website/locales/uk/messages.po (+1687 -1687)
📝 website/locales/vi/messages.po (+1687 -1687)
📝 website/locales/zh-CN/messages.po (+1687 -1687)
📝 website/locales/zh-TW/messages.po (+1687 -1687)

...and 26 more files

📄 Description

TL;DR: The website now turns dark when the reader's system is set to dark. The same PR fixes small text and spacing problems that show in both modes. Light colors do not change.

Summary

The plan is in discussion #1727. Thanks, morluto, for the go-ahead. The site only had a light theme. With a dark system, readers got a white page. This PR adds a dark theme. It also fixes small layout problems that I found while measuring the pages.

Scope grew in review. This PR is bigger than the plan in #1727. The automated review found four places where dark mode made things worse. I fixed them here. They are the step highlight, the dinosaur game colors and its redraw, and the Touhou flywheel arrows. A new site test came too. If smaller pieces are easier to review, I can split it.

Problem and expected behavior

  • With the system set to dark, the site should be dark. With it set to light, the colors should stay as they are.
  • Some layout details fall short of WCAG 2.2. At 320 px, long terminal prompts and Copy buttons were cut off. Some labels were 9.6 px. Some header and footer links were 23.09 px tall.

Change and scope

The first four commits are the change, and each can be read alone. Five more came after review. They hold the four review fixes and a new site test.

  1. Layout fixes. These change the light theme on purpose:
    • Long terminal prompts and code-header buttons wrap at 320 px.
    • Headings and table cells break long words.
    • Header and footer links are at least 24 px tall.
    • Labels under 12 px now render at 12 px or more. Inline code never drops under 0.75rem.
    • On the home page, the two column rows share one gap and line up on the first baseline.
    • Terminals, step tabs and the assembly title bar use the 5 px corner and matching padding.
    • Highlight chips get room around the text. The active run in a step listing is one band, not a box per line.
  2. Dark mode. One @media (prefers-color-scheme: dark) block sits in styles.css, before the right-to-left rules. It swaps the six color variables to Catppuccin Mocha (MIT). It also sets color-scheme: dark. Fixed colors that would break on a dark page get dark values. The terminals get a border. The page template and the 17 pages get a second theme-color tag for dark. The style guide's color table gets a Dark column.
  3. Dark figures. Pages load the five SVG figures with an img tag, so page CSS cannot reach them. Each SVG carries its own dark block. All five share one color map. Markup, labels and shapes do not change.
  4. Catalog references. Commit 2 adds lines to every page head. That moves the line numbers that the translation catalogs cite. The command python3 scripts/website.py translations extract rewrites them. This commit is that run, unedited. It changes 19 files and about 31,600 lines. The changes are #: reference comments and one moved entry ("Main navigation"). No msgstr text changes. Without it, the site check fails. The error is "Translation sources changed". You can skip it when reviewing. You can also re-run the command yourself.

The translated pages need no extra CSS. The build makes them from the English pages. They load the same stylesheet. The language picker and the translation notice use the color variables. The right-to-left rules set no colors.

Not in this PR: the sharing image. It stays light. Link previews ignore the system setting.

Screenshots

These are placeholder previews from my fork build, made before the port to today's main. They show the look, not this exact branch.

Home page in dark mode, desktop
Home page in light mode, desktop
Home page in dark mode, phone width
The bullet-ring figure in dark mode

Contract and boundary impact

  • Semantic owner and earliest changed stage: website only.
  • CLI and MCP/tool-catalog contract: none.
  • Provider, bridge, target-format, or platform compatibility: none.
  • Evidence, artifact, provenance, or reconstruction contract: none.
  • Process execution, authorization, cleanup, or containment impact: none.
  • Generated metadata (docs/public/product-catalog.json), package, or installation impact: none.

Evidence and regression coverage

All numbers below were measured on the built site. I read computed styles in headless Chromium. I judged no looks from screenshots.

  • Tests added: one, in scripts/test-website.py. Every reading page, and its built copy in each language, must have a light and a dark theme-color tag. The stylesheet must keep its dark block. On fa9a7e5e, before this PR, the test fails on every page. On this branch it passes. The other site tests still cover the pages, links and metadata.
  • Dark text contrast: 323 reading pages. At 1280 px that is 50,973 text elements. At 320 px it is 50,270. The lowest ratio is 5.97:1 at both widths. That is blue link text on a tinted highlight, on the home page. Nothing is below 4.5:1.
  • Dark on translated pages: the 34 Arabic and Persian pages (right to left) have the dark page color. So do the 17 Chinese pages. Every reading page has both theme-color tags.
  • Left out of every count here: the two example pages notes-electron and notes-web. They are sample apps, and this PR does not touch them. The 323 reading pages are 17 pages in each of 19 languages.
  • Light colors: I compared 82,992 elements on 323 pages, before and after. The colors I compared were text, background, border, outline, fill, stroke and shadow. There were 0 differences.
  • Light figures: a screenshot of each of the five SVGs is byte-for-byte identical before and after. The dark screenshots differ from the old ones, so the test can fail.
  • Figure text in dark: the five figures hold 94 text elements. For 81 of them, the script found the background behind the text. The lowest ratio is 5.97:1. For the other 13, the script found no background shape. Those 13 are not measured.
  • Light geometry at 320 px, on 323 pages: the smallest text went from 9.6 px to 12 px. The smallest header or footer link went from 23.09 px to 24 px. No page scrolled sideways, before or after.
  • !important: none added.
  • Dinosaur game: after review, the canvas reads its colors from CSS variables on .dino-stage. In light, its pixels match the old ones byte for byte on both pages that host it. In dark, the dinosaur is 8.3:1, cacti and text 7.9:1, and the crash color 7.6:1. The game redraws when the system theme changes, even while idle.
  • Touhou flywheel: in dark, two rules map its five hard-coded strokes to the accent and muted colors. They read 7.8:1 and 7.4:1, up from 2.0:1 and 2.8:1. Light keeps the old strokes.
  • Remaining proof gaps: see "Not run" below.

Not run

  • I looked at this branch's English pages by eye in dark mode, in LibreWolf 157 (a Firefox fork, MPL-2.0). I did not look at the translated pages by eye.
  • No measurement of hover, focus or pressed states.
  • The 320 px cut-off of prompts and buttons. I measured it in an earlier pass on my fork. I did not re-measure it here.
  • Firefox's engine was checked by eye only, in LibreWolf 157. No measurements ran there, and nothing ran in Safari.
  • A Pages preview deploy.

Validation performed

All ran on this branch.

The copy was clean, under /tmp. The Node version was 24.18.0.

  • python3 scripts/website.py check: exit 0.
  • python3 scripts/test-website.py: exit 0, 12 tests, with the new one.
  • npm ci: exit 0.
  • npm run check:fast: exit 0. This needed a git repository in the copy, because the lint step lists files with git.
  • npx oxfmt --check website scripts: exit 0.
  • The measuring scripts all ran to the end. They are not in the repo.

Compatibility, safety, and release

  • Breaking changes or migration steps: none. Readers with a light system see the same colors.
  • Real Hopper/Ghidra, browser, or OS coverage: not applicable. I measured in Chromium 154 only.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: not needed. Only CSS, HTML, SVG and catalog comments change. Nothing adds scripts or storage. The palette is Catppuccin Mocha (MIT).

Review checklist

  • This PR addresses a concrete problem or an agreed enhancement.
  • The PR has one focused outcome and the title follows type(scope): outcome. Two parts by choice, agreed in #1727.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output. Not applicable: website only.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.
Test setup
  • Box: Nobara 44 (Fedora 44 base), Linux 7.2.9
  • CPU: AMD Ryzen 9 5900X, 12 cores / 24 threads
  • RAM: 32 GB DDR4-3600
  • Node: 24.18.0
  • Head / base: 9e0e4454 / fa9a7e5e (#1873)
  • Python: 3.14.7, with polib 1.2.0
  • Browser: Chromium 154.0.8037.57 (BSD-3-Clause)

🤖 Generated with Claude Code (Sonnet 5.5, verified by Opus 5.5) 🦊


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/1894 **Author:** [@CassieFox23](https://github.com/CassieFox23) **Created:** 10/11/2026 **Status:** ✅ Merged **Merged:** 10/11/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `feat/website-dark-mode-upstream` --- ### 📝 Commits (9) - [`2122cdd`](https://github.com/morluto/rea/commit/2122cdd8cae306909101af5e6be4ab1deb7f0e3f) fix(website): keep text inside small screens and tidy small type and spacing - [`4a840d6`](https://github.com/morluto/rea/commit/4a840d605507adb8b71b7591c5338479bb3d59a6) feat(website): follow the system dark mode - [`6f0c4de`](https://github.com/morluto/rea/commit/6f0c4de4eebd4f6f561ee1df05f04c0c36a3e5c3) feat(website): give the five SVG figures a dark scheme - [`754f3ec`](https://github.com/morluto/rea/commit/754f3ec52c58006f2bf84357017e4bb63905f612) chore(website): refresh translation source references - [`fb59ba8`](https://github.com/morluto/rea/commit/fb59ba853e4a3bf35101277ade6b294a85bf26f8) fix(website): keep inline step highlights inline - [`4f25251`](https://github.com/morluto/rea/commit/4f252518cef184cb0f6ee5ff842039d3ec3d61b0) test(website): check every page offers light and dark theme colors - [`b9ef65d`](https://github.com/morluto/rea/commit/b9ef65ddedd318e05e722684b01c457ec737ebda) fix(website): draw the dinosaur game in the page colors - [`5f907ed`](https://github.com/morluto/rea/commit/5f907ed762276f43ef42c77efea1c1be9b88b820) fix(website): recolor the Touhou flywheel arrows in dark mode - [`9e0e445`](https://github.com/morluto/rea/commit/9e0e4454302f95853e265641a3ee9febeab40fc5) fix(website): redraw the dinosaur game when the system theme changes ### 📊 Changes **46 files changed** (+32440 additions, -32063 deletions) <details> <summary>View changed files</summary> 📝 `scripts/test-website.py` (+16 -0) 📝 `website/locales/ar/messages.po` (+1687 -1687) 📝 `website/locales/de/messages.po` (+1687 -1687) 📝 `website/locales/es/messages.po` (+1687 -1687) 📝 `website/locales/fa/messages.po` (+1687 -1687) 📝 `website/locales/fr/messages.po` (+1687 -1687) 📝 `website/locales/id/messages.po` (+1687 -1687) 📝 `website/locales/it/messages.po` (+1687 -1687) 📝 `website/locales/ja/messages.po` (+1687 -1687) 📝 `website/locales/ko/messages.po` (+1687 -1687) 📝 `website/locales/messages.pot` (+1633 -1633) 📝 `website/locales/pl/messages.po` (+1687 -1687) 📝 `website/locales/pt-BR/messages.po` (+1687 -1687) 📝 `website/locales/ru/messages.po` (+1687 -1687) 📝 `website/locales/th/messages.po` (+1687 -1687) 📝 `website/locales/tr/messages.po` (+1687 -1687) 📝 `website/locales/uk/messages.po` (+1687 -1687) 📝 `website/locales/vi/messages.po` (+1687 -1687) 📝 `website/locales/zh-CN/messages.po` (+1687 -1687) 📝 `website/locales/zh-TW/messages.po` (+1687 -1687) _...and 26 more files_ </details> ### 📄 Description **TL;DR:** The website now turns dark when the reader's system is set to dark. The same PR fixes small text and spacing problems that show in both modes. Light colors do not change. ## Summary The plan is in discussion #1727. Thanks, morluto, for the go-ahead. The site only had a light theme. With a dark system, readers got a white page. This PR adds a dark theme. It also fixes small layout problems that I found while measuring the pages. **Scope grew in review.** This PR is bigger than the plan in #1727. The automated review found four places where dark mode made things worse. I fixed them here. They are the step highlight, the dinosaur game colors and its redraw, and the Touhou flywheel arrows. A new site test came too. If smaller pieces are easier to review, I can split it. ## Problem and expected behavior - With the system set to dark, the site should be dark. With it set to light, the colors should stay as they are. - Some layout details fall short of WCAG 2.2. At 320 px, long terminal prompts and Copy buttons were cut off. Some labels were 9.6 px. Some header and footer links were 23.09 px tall. ## Change and scope The first four commits are the change, and each can be read alone. Five more came after review. They hold the four review fixes and a new site test. 1. **Layout fixes.** These change the light theme on purpose: - Long terminal prompts and code-header buttons wrap at 320 px. - Headings and table cells break long words. - Header and footer links are at least 24 px tall. - Labels under 12 px now render at 12 px or more. Inline code never drops under 0.75rem. - On the home page, the two column rows share one gap and line up on the first baseline. - Terminals, step tabs and the assembly title bar use the 5 px corner and matching padding. - Highlight chips get room around the text. The active run in a step listing is one band, not a box per line. 2. **Dark mode.** One `@media (prefers-color-scheme: dark)` block sits in `styles.css`, before the right-to-left rules. It swaps the six color variables to Catppuccin Mocha (MIT). It also sets `color-scheme: dark`. Fixed colors that would break on a dark page get dark values. The terminals get a border. The page template and the 17 pages get a second `theme-color` tag for dark. The style guide's color table gets a Dark column. 3. **Dark figures.** Pages load the five SVG figures with an img tag, so page CSS cannot reach them. Each SVG carries its own dark block. All five share one color map. Markup, labels and shapes do not change. 4. **Catalog references.** Commit 2 adds lines to every page head. That moves the line numbers that the translation catalogs cite. The command `python3 scripts/website.py translations extract` rewrites them. This commit is that run, unedited. It changes 19 files and about 31,600 lines. The changes are `#:` reference comments and one moved entry ("Main navigation"). No `msgstr` text changes. Without it, the site check fails. The error is "Translation sources changed". You can skip it when reviewing. You can also re-run the command yourself. The translated pages need no extra CSS. The build makes them from the English pages. They load the same stylesheet. The language picker and the translation notice use the color variables. The right-to-left rules set no colors. Not in this PR: the sharing image. It stays light. Link previews ignore the system setting. <details> <summary>Screenshots</summary> These are placeholder previews from my fork build, made before the port to today's main. They show the look, not this exact branch. ![Home page in dark mode, desktop](https://raw.githubusercontent.com/CassieFox23/rea/previews/previews/dark-mode/home-dark-1280.png) ![Home page in light mode, desktop](https://raw.githubusercontent.com/CassieFox23/rea/previews/previews/dark-mode/home-light-1280.png) <img src="https://raw.githubusercontent.com/CassieFox23/rea/previews/previews/dark-mode/home-dark-390.png" width="300" alt="Home page in dark mode, phone width"> ![The bullet-ring figure in dark mode](https://raw.githubusercontent.com/CassieFox23/rea/previews/previews/dark-mode/figure-th04-bullet-ring-dark.png) </details> ## Contract and boundary impact - Semantic owner and earliest changed stage: website only. - CLI and MCP/tool-catalog contract: none. - Provider, bridge, target-format, or platform compatibility: none. - Evidence, artifact, provenance, or reconstruction contract: none. - Process execution, authorization, cleanup, or containment impact: none. - Generated metadata (`docs/public/product-catalog.json`), package, or installation impact: none. ## Evidence and regression coverage All numbers below were measured on the built site. I read computed styles in headless Chromium. I judged no looks from screenshots. - Tests added: one, in `scripts/test-website.py`. Every reading page, and its built copy in each language, must have a light and a dark `theme-color` tag. The stylesheet must keep its dark block. On fa9a7e5e, before this PR, the test fails on every page. On this branch it passes. The other site tests still cover the pages, links and metadata. - Dark text contrast: 323 reading pages. At 1280 px that is 50,973 text elements. At 320 px it is 50,270. The lowest ratio is 5.97:1 at both widths. That is blue link text on a tinted highlight, on the home page. Nothing is below 4.5:1. - Dark on translated pages: the 34 Arabic and Persian pages (right to left) have the dark page color. So do the 17 Chinese pages. Every reading page has both `theme-color` tags. - Left out of every count here: the two example pages `notes-electron` and `notes-web`. They are sample apps, and this PR does not touch them. The 323 reading pages are 17 pages in each of 19 languages. - Light colors: I compared 82,992 elements on 323 pages, before and after. The colors I compared were text, background, border, outline, fill, stroke and shadow. There were 0 differences. - Light figures: a screenshot of each of the five SVGs is byte-for-byte identical before and after. The dark screenshots differ from the old ones, so the test can fail. - Figure text in dark: the five figures hold 94 text elements. For 81 of them, the script found the background behind the text. The lowest ratio is 5.97:1. For the other 13, the script found no background shape. Those 13 are not measured. - Light geometry at 320 px, on 323 pages: the smallest text went from 9.6 px to 12 px. The smallest header or footer link went from 23.09 px to 24 px. No page scrolled sideways, before or after. - `!important`: none added. - Dinosaur game: after review, the canvas reads its colors from CSS variables on `.dino-stage`. In light, its pixels match the old ones byte for byte on both pages that host it. In dark, the dinosaur is 8.3:1, cacti and text 7.9:1, and the crash color 7.6:1. The game redraws when the system theme changes, even while idle. - Touhou flywheel: in dark, two rules map its five hard-coded strokes to the accent and muted colors. They read 7.8:1 and 7.4:1, up from 2.0:1 and 2.8:1. Light keeps the old strokes. - Remaining proof gaps: see "Not run" below. ### Not run - I looked at this branch's English pages by eye in dark mode, in LibreWolf 157 (a Firefox fork, MPL-2.0). I did not look at the translated pages by eye. - No measurement of hover, focus or pressed states. - The 320 px cut-off of prompts and buttons. I measured it in an earlier pass on my fork. I did not re-measure it here. - Firefox's engine was checked by eye only, in LibreWolf 157. No measurements ran there, and nothing ran in Safari. - A Pages preview deploy. ## Validation performed All ran on this branch. The copy was clean, under `/tmp`. The Node version was 24.18.0. - `python3 scripts/website.py check`: exit 0. - `python3 scripts/test-website.py`: exit 0, 12 tests, with the new one. - `npm ci`: exit 0. - `npm run check:fast`: exit 0. This needed a git repository in the copy, because the lint step lists files with git. - `npx oxfmt --check website scripts`: exit 0. - The measuring scripts all ran to the end. They are not in the repo. ## Compatibility, safety, and release - Breaking changes or migration steps: none. Readers with a light system see the same colors. - Real Hopper/Ghidra, browser, or OS coverage: not applicable. I measured in Chromium 154 only. - Package or release metadata impact: none. - Security, privacy, process, or containment review: not needed. Only CSS, HTML, SVG and catalog comments change. Nothing adds scripts or storage. The palette is [Catppuccin Mocha](https://github.com/catppuccin/palette) (MIT). ## Review checklist - [x] This PR addresses a concrete problem or an agreed enhancement. - [ ] The PR has one focused outcome and the title follows `type(scope): outcome`. Two parts by choice, agreed in #1727. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. Not applicable: website only. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. <details> <summary>Test setup</summary> - Box: Nobara 44 (Fedora 44 base), Linux 7.2.9 - CPU: AMD Ryzen 9 5900X, 12 cores / 24 threads - RAM: 32 GB DDR4-3600 - Node: 24.18.0 - Head / base: 9e0e4454 / fa9a7e5e (#1873) - Python: 3.14.7, with polib 1.2.0 - Browser: Chromium 154.0.8037.57 (BSD-3-Clause) </details> 🤖 Generated with Claude Code (Sonnet 5.5, verified by Opus 5.5) 🦊 --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-31 00:56:27 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#4888
No description provided.