fix(brand): match the below-average tint to its own hue, and finish the casing
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m2s
PR Checks / Backend Smoke (pull_request) Successful in 6s
PR Checks / Build Backend (no push) (pull_request) Successful in 10s
PR Checks / Build Frontend (no push) (pull_request) Successful in 43s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 10s
PR Checks / AI Code Review (Claude) (pull_request) Successful in 3m19s

Three review findings.

--status-below-bg carried the raw --coral tuple (249,115,96) instead of the
hue it belongs to (#A9481F → 169,72,31), so "below average" chips rendered a
coral-pink wash behind terracotta text — the one solid/tint pair in the file
whose hues disagreed. Alpha drops 0.15 → 0.12 to match --status-above-bg, so
the two chips read as equal weight; left at 0.15 the darker terracotta tint
takes the label to 4.45:1 on Warm White, under the 4.5 floor. At 0.12 it is
4.86:1 on cards and 4.67:1 on Warm White.

Auditing the whole file for the same class of error turned up one more:
--action-bg was also a --coral tint while --action is the darkened #BE3C27.
It is unused today and the dark-theme value was already correct, but it is
aligned so a future coral ghost button gets a matching label and ground. The
five phase pairs also "mismatch" by the same test and are deliberately left
alone: those pair a pastel ground (sage, sky, mustard, lavender) with a deeper
text hue, which is exactly what the guideline's Chips/Tags show.

The lowercase wordmark had only reached the visual chrome. Every user-visible
occurrence now matches: page title and template, appleWebApp title, authors,
OpenGraph and Twitter titles and siteName, the school page's siteName, the PWA
manifest name and short_name, the footer copyright line, the nav's aria-label,
the Web Share API strings, and the editorial paragraph. Comments in lib/*.ts
and AdmissionsView still say "SchoolCompare"; they describe the codebase rather
than the mark, so they are left to keep this diff to the reported problem.

The comment explaining why the font classes belong on <html> still described
--font-schibsted, which no longer exists. It now names --font-manrope and
--font-inter, and records that the e2e typeface assertion is the only guard —
this failure mode throws nothing and fails no unit test.

Verified: tsc clean, 159/159 tests, build green, and the rendered title is now
"School Admissions Guide | schoolcompare". Status and phase labels re-checked
on their own composited tints over both light grounds — all clear AA.
This commit is contained in:
Tudor
2026-08-07 18:33:30 +01:00
parent accc562b90
commit 39e5c11274
8 changed files with 34 additions and 25 deletions
+11 -3
View File
@@ -1,5 +1,5 @@
/*
* SchoolCompare — "Find the right school. For their future."
* schoolcompare — "Find the right school. For their future."
*
* Implements the schoolcompare brand guideline. Colour has four jobs and they
* never borrow each other's hues:
@@ -51,7 +51,9 @@
--action: #BE3C27; /* darkened coral — 5.4:1 under a white label */
--action-strong: #A33320;
--action-stronger: #8C2B1B;
--action-bg: rgba(249, 115, 96, 0.14);
/* Tint of --action, not of --coral, so a coral ghost button's label and
ground share a hue. Unused today; the dark value was already correct. */
--action-bg: rgba(190, 60, 39, 0.14);
--action-on: #FFFFFF;
/* ── Palette accents: exact brand values, for fills and tints only ── */
@@ -67,7 +69,13 @@
--status-above: #36743F;
--status-above-bg: rgba(54, 116, 63, 0.12);
--status-below: #A9481F;
--status-below-bg: rgba(249, 115, 96, 0.15);
/* The tint is the solid hue at low alpha, exactly as every other pair in
this file is. It briefly carried the raw --coral tuple instead, which
put a coral-pink wash behind terracotta text — the one mismatched pair
in the palette. Alpha matches --status-above-bg so the two chips read
as equal weight; at 0.15 the darker terracotta tint drops the label to
4.45:1 on Warm White. */
--status-below-bg: rgba(169, 72, 31, 0.12);
--status-at: #5F6A75;
--status-at-bg: rgba(95, 106, 117, 0.10);
+14 -13
View File
@@ -43,16 +43,16 @@ export const viewport: Viewport = {
export const metadata: Metadata = {
appleWebApp: {
capable: true,
title: 'SchoolCompare',
title: 'schoolcompare',
statusBarStyle: 'default',
},
title: {
default: 'SchoolCompare | Compare School Performance',
template: '%s | SchoolCompare',
default: 'schoolcompare | Compare School Performance',
template: '%s | schoolcompare',
},
description: 'Compare primary and secondary school SATs and GCSE performance across England',
keywords: 'school comparison, KS2 results, KS4 results, primary school, secondary school, England schools, SATs results, GCSE results',
authors: [{ name: 'SchoolCompare' }],
authors: [{ name: 'schoolcompare' }],
manifest: '/manifest.json',
// No `icons` key on purpose: setting it here would override the file
// conventions. app/icon.svg and app/apple-icon.tsx are the source, and
@@ -60,15 +60,15 @@ export const metadata: Metadata = {
metadataBase: new URL('https://schoolcompare.co.uk'),
openGraph: {
type: 'website',
title: 'SchoolCompare | Compare School Performance',
title: 'schoolcompare | Compare School Performance',
description: 'Compare primary and secondary school SATs and GCSE performance across England',
url: 'https://schoolcompare.co.uk',
siteName: 'SchoolCompare',
siteName: 'schoolcompare',
},
twitter: {
// summary_large_image now that there is an image worth showing.
card: 'summary_large_image',
title: 'SchoolCompare | Compare School Performance',
title: 'schoolcompare | Compare School Performance',
description: 'Compare primary and secondary school SATs and GCSE performance across England',
},
};
@@ -80,12 +80,13 @@ export default function RootLayout({
}>) {
return (
// The font variable classes must sit on <html>, not <body>. globals.css
// declares --font-display/--font-ui on :root as var(--font-schibsted),
// and a custom property's var() references resolve on the element that
// declares it. With the classes on <body>, --font-schibsted was undefined
// at :root, so --font-display computed to the guaranteed-invalid value and
// every font-family that referenced it silently fell back — the whole site
// rendered in Times.
// declares --font-display on :root as var(--font-manrope) and --font-ui as
// var(--font-inter), and a custom property's var() references resolve on
// the element that declares it. With the classes on <body>, those two are
// undefined at :root, so --font-display computes to the guaranteed-invalid
// value and every font-family referencing it silently falls back — which
// once shipped the whole site in Times. Nothing throws and no unit test
// fails, so the e2e typeface assertion is the only guard.
<html lang="en" className={`${manrope.variable} ${inter.variable}`}>
<head>
<link rel="preconnect" href="https://analytics.schoolcompare.co.uk" />
+1 -1
View File
@@ -98,7 +98,7 @@ export async function generateMetadata({ params }: SchoolPageProps): Promise<Met
description,
type: 'website',
url: `https://schoolcompare.co.uk${canonicalPath}`,
siteName: 'SchoolCompare',
siteName: 'schoolcompare',
},
twitter: {
card: 'summary',