A fortnight ago I wrote about our stylesheet, and in particular about the .light block in it: a copy of :root line for line, minus one variable, plus color-scheme: light. I said this about who can reach it:
enableSystemis on, so the system option exists, but the default is dark rather than system, and the only control that can change it is a theme toggle that lives in the dashboard header.
That is true about the controls, and misleading about the site. Three pages have been served in the light palette this whole time, with no toggle involved, and anybody can see them without an account:
Open one of those next to the FAQ and the site changes colour.
One class name
The whole mechanism is line 6 of app/legal/layout.tsx:
<div className="light flex flex-col min-h-screen"> next-themes puts the theme name on <html> as a class, so .light exists as a selector in our stylesheet for that purpose. Nothing stops you applying the class to a div instead, and that is what this layout does. It is the only place in the entire app where the string appears as a class name. The only other mention anywhere is setTheme("light") inside the dashboard toggle.
The result is a white island inside a dark document, which I read out of the live page:
document.documentElement.className // "dark" getComputedStyle(document.documentElement).colorScheme // "dark" getComputedStyle(document.body).backgroundColor // "rgb(23, 23, 23)" getComputedStyle(document.querySelector('.light')).backgroundColor // "rgb(255, 255, 255)" getComputedStyle(document.querySelector('.light')).color // "rgb(2, 8, 23)" getComputedStyle(document.querySelector('.light')).colorScheme // "light" The root says dark, the body is still painted #171717 underneath, and a min-h-screen div covers it in white. color-scheme flips to light inside the island, because the .light block declares it and the property inherits, so form controls inside those three pages would render light while everything outside them renders dark.
--radius still resolves to .5rem inside the island, which is the one variable .light does not redeclare. The copy that is almost a duplicate turns out to be load bearing in exactly the place its one omission falls.
The seam you can actually see
<meta name="theme-color" content="#171717" /> That is set once in the root layout and is not theme aware. On a phone, the browser chrome above our privacy policy is near black and the page below it is white. It is the only part of this that a visitor notices, and it is the hardest part to fix properly, because theme-color is a document-level declaration and this is a document that has decided to be two themes at once.
Four more ways these three are not like the other 69
Our content pages all come from a registry, and the legal pages have no entry in it. That absence shows up in four places:
- No breadcrumbs. Every other page carries a visible trail and a
BreadcrumbListin its structured data. These carry neither. - One JSON-LD block. Parsing the scripts on
/legal/termsgives a singleOrganizationnode, inherited from the root layout. NoWebPage, no breadcrumb, nothing about the document itself. - A different footer. Four links, on a white background, because the layout passes
<SiteFooter className="bg-white" />. The rest of the site gets the full one. - A different kind of freshness date. In our sitemap, 69 of the 72 URLs carry a midnight timestamp that comes from the registry and means "the day this content changed". The three legal pages carry
2026-10-18T14:32:30.258Z, identical to the millisecond, because they fall back to the build clock.
That layout is also the only file in the app styling anything with raw Tailwind palette colours rather than our tokens: bg-white and border-slate-200. If the token palette ever moves, these three pages will not move with it.
And the dates the pages give themselves
Each legal page hardcodes its own:
// app/legal/cookies/page.tsx const LAST_UPDATED = "3 June 2025" // app/legal/privacy/page.tsx const LAST_UPDATED = "3 October 2026" // app/legal/terms/page.tsx const LAST_UPDATED = "18 October 2026" The cookie policy's date predates every other word on the site by over a year, and it is the page making the most checkable claim of the three:
PubTrivia uses only essential, strictly necessary cookies. We do not use advertising cookies, marketing cookies, or any third-party tracking or analytics cookies. Because none of our cookies require your consent under UK PECR, we do not display a cookie consent banner.
So I checked it, on the cookie policy page itself, in a browser with nothing stored for the domain:
document.cookie // "" Object.keys(localStorage) // [] Object.keys(sessionStorage) // [] A cookie policy that sets no cookies. The ones it describes are the authentication cookies, which exist only once you are signed in, and that is also why there is no banner: a strictly necessary cookie does not need consent under PECR. The clause that earns its place is the one about the payment provider, because the Stripe pricing table script is loaded from the root layout, which makes "pages that include our payment provider" mean every page, a fact I had to correct in a post of its own a fortnight ago.
The date is still wrong, and that is now a ticket rather than a sentence in a blog post.
What I take from it
A layout is a theme boundary, and nothing in the build will tell you that one exists. There is no warning, no type error, no lint rule. Three pages acquired a different palette, a different footer, a different structured-data profile and a different source of truth for their dates, all from one class name and one missing registry entry, and the only reason I noticed is that I went looking for a claim I had made in public and found it was not true.
Go and look at our terms, then press back to the FAQ. If your own site has a legal section, check whether it is wearing the same clothes as the rest of the site. Mine was not, for months.
![Why Object.keys(user) Returns string[], Not (keyof User)[]: TypeScript Means It](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2q4w48b9bzs43tynyhsf.png)
