The fade between the hero map band and the school header ramped through hardcoded white and landed on var(--bg-card).
In the light theme that is white into white — invisible, as designed. In the dark theme it climbed to 95% white and then met a near-black card, putting a bright band across the full width exactly where the map is supposed to dissolve into the title.
Fading to the colour the gradient lands on is the whole trick, and it only works if that colour is a token. --bg-card-rgb now exists in both theme blocks, matching the existing --hero-ground-rgb precedent.
Two more, same file, same cause
SchoolHeroMap.module.css had no dark-theme handling at all, so this was not the only defect in it:
The controls floating over the map were unreadable in dark mode. They paired a hardcoded white background with color: var(--text-primary), which resolves to #E9EEF0 in dark — near-white text on a near-white button. These deliberately do not follow the theme, because the map tiles are light in both, so the ink is now literal too and the comment says why. A themed token is the wrong tool for a surface that never changes.
The loading skeleton flashed. It swept 50% white across var(--bg-secondary), which on a dark page is a bright pulse every 1.4s while tiles load. It now sweeps toward the card colour, a shade lighter than the ground in both themes.
The guard
A stylesheet test, not a render test — the bug is invisible in the theme it was written for, so a snapshot or a visibility assertion in jsdom would never see it. Two invariants:
No rule pairs a hardcoded white background with a themed color: var(--…).
No linear-gradient lands on a theme token while ramping through a literal colour.
Scanned across every components/**/*.module.css: these two were the only violations, so the invariants hold and the test is not noisy.
Verified by reverting each fix in turn — it names .fade and .openHint exactly, then passes again once restored.
Frontend 287 passed, tsc clean, next build green.
The fade between the hero map band and the school header ramped through hardcoded white and landed on `var(--bg-card)`.
In the light theme that is white into white — invisible, as designed. In the dark theme it climbed to **95% white** and then met a near-black card, putting a bright band across the full width exactly where the map is supposed to dissolve into the title.
Fading to the colour the gradient lands on is the whole trick, and it only works if that colour is a token. `--bg-card-rgb` now exists in both theme blocks, matching the existing `--hero-ground-rgb` precedent.
## Two more, same file, same cause
`SchoolHeroMap.module.css` had no dark-theme handling at all, so this was not the only defect in it:
**The controls floating over the map were unreadable in dark mode.** They paired a hardcoded white background with `color: var(--text-primary)`, which resolves to `#E9EEF0` in dark — near-white text on a near-white button. These deliberately do *not* follow the theme, because the map tiles are light in both, so the ink is now literal too and the comment says why. A themed token is the wrong tool for a surface that never changes.
**The loading skeleton flashed.** It swept 50% white across `var(--bg-secondary)`, which on a dark page is a bright pulse every 1.4s while tiles load. It now sweeps toward the card colour, a shade lighter than the ground in both themes.
## The guard
A stylesheet test, not a render test — the bug is invisible in the theme it was written for, so a snapshot or a visibility assertion in jsdom would never see it. Two invariants:
1. No rule pairs a hardcoded white background with a themed `color: var(--…)`.
2. No `linear-gradient` lands on a theme token while ramping through a literal colour.
Scanned across every `components/**/*.module.css`: these two were the only violations, so the invariants hold and the test is not noisy.
**Verified by reverting each fix in turn** — it names `.fade` and `.openHint` exactly, then passes again once restored.
Frontend 287 passed, `tsc` clean, `next build` green.
The fade between the map band and the school header ramped through
rgba(255,255,255,...) and landed on var(--bg-card). In the light theme
that is white into white and invisible, as designed. In the dark theme
it climbed to 95% WHITE and then met a near-black card, putting a bright
band across the full width exactly where the map should dissolve into
the title.
Fading to the colour the gradient lands on is the whole trick, and it
only works if that colour is a token — so --bg-card-rgb now exists in
both theme blocks, matching the --hero-ground-rgb precedent.
Two more defects in the same file, same cause, found while in there:
The controls floating over the map paired a hardcoded white background
with color: var(--text-primary), which resolves to #E9EEF0 in dark —
near-white text on a near-white button. These deliberately do NOT follow
the theme, because the map tiles are light in both, so the ink is now
literal too and says why. A themed token is the wrong tool for a surface
that never changes.
The loading skeleton swept 50% white across var(--bg-secondary), which
is a bright flash every 1.4s on a dark page. It now sweeps toward the
card colour, a shade lighter than the ground in both themes.
The guard is a stylesheet test rather than a render test, because the
bug is invisible in the theme it was written for. Verified by reverting
each fix in turn: it names .fade and .openHint exactly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015mWQnpye9F299NVRCCSRvj
This PR fixes two dark-theme CSS bugs in SchoolHeroMap (a hardcoded-white gradient that flashed as a bright band on dark cards, and near-white text on a near-white floating control button), introduces --bg-card-rgb tokens for both themes, and adds a regression test that statically scans component stylesheets for the same class of bug. The changes are internally consistent — the new RGB tokens match their corresponding hex values in both themes, and the gradients now resolve to matching colors in both light and dark mode.
✅ No issues found.
## 🤖 AI Code Review (Claude Code)
This PR fixes two dark-theme CSS bugs in SchoolHeroMap (a hardcoded-white gradient that flashed as a bright band on dark cards, and near-white text on a near-white floating control button), introduces --bg-card-rgb tokens for both themes, and adds a regression test that statically scans component stylesheets for the same class of bug. The changes are internally consistent — the new RGB tokens match their corresponding hex values in both themes, and the gradients now resolve to matching colors in both light and dark mode.
✅ No issues found.
tudor
merged commit 868eb344f5 into main2026-08-26 20:32:45 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
The fade between the hero map band and the school header ramped through hardcoded white and landed on
var(--bg-card).In the light theme that is white into white — invisible, as designed. In the dark theme it climbed to 95% white and then met a near-black card, putting a bright band across the full width exactly where the map is supposed to dissolve into the title.
Fading to the colour the gradient lands on is the whole trick, and it only works if that colour is a token.
--bg-card-rgbnow exists in both theme blocks, matching the existing--hero-ground-rgbprecedent.Two more, same file, same cause
SchoolHeroMap.module.csshad no dark-theme handling at all, so this was not the only defect in it:The controls floating over the map were unreadable in dark mode. They paired a hardcoded white background with
color: var(--text-primary), which resolves to#E9EEF0in dark — near-white text on a near-white button. These deliberately do not follow the theme, because the map tiles are light in both, so the ink is now literal too and the comment says why. A themed token is the wrong tool for a surface that never changes.The loading skeleton flashed. It swept 50% white across
var(--bg-secondary), which on a dark page is a bright pulse every 1.4s while tiles load. It now sweeps toward the card colour, a shade lighter than the ground in both themes.The guard
A stylesheet test, not a render test — the bug is invisible in the theme it was written for, so a snapshot or a visibility assertion in jsdom would never see it. Two invariants:
color: var(--…).linear-gradientlands on a theme token while ramping through a literal colour.Scanned across every
components/**/*.module.css: these two were the only violations, so the invariants hold and the test is not noisy.Verified by reverting each fix in turn — it names
.fadeand.openHintexactly, then passes again once restored.Frontend 287 passed,
tscclean,next buildgreen.🤖 AI Code Review (Claude Code)
This PR fixes two dark-theme CSS bugs in SchoolHeroMap (a hardcoded-white gradient that flashed as a bright band on dark cards, and near-white text on a near-white floating control button), introduces --bg-card-rgb tokens for both themes, and adds a regression test that statically scans component stylesheets for the same class of bug. The changes are internally consistent — the new RGB tokens match their corresponding hex values in both themes, and the gradients now resolve to matching colors in both light and dark mode.
✅ No issues found.