fix(design): keep below/attention off the brand hue, harden the share-card fonts
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m2s
PR Checks / Backend Smoke (pull_request) Successful in 7s
PR Checks / Build Backend (no push) (pull_request) Successful in 11s
PR Checks / Build Frontend (no push) (pull_request) Successful in 49s
PR Checks / Build Pipeline (no push) (pull_request) Successful in 10s
PR Checks / AI Code Review (Claude) (pull_request) Failing after 1m8s

Review follow-up on #86.

The blind coral -> brand rename recreated the exact collision this PR set out
to remove: coral had been both the primary CTA and the "below average" signal,
so every negative indicator followed --primary onto iris. Sixteen rules moved
back onto the status ramp — delta chips, trend-down arrows, progress-negative
values, statusBad, chipBad/badgeBad, and the urgent deadline chips.

The Ofsted scale had also lost its worst step, with grade 4 landing on brand
while 1-2 were teal and 3 was amber. It now escalates by weight rather than by
reaching for another hue: a tinted amber chip for "requires improvement", a
solid amber one for "inadequate" (5.1:1 light, 7.7:1 dark). Report-card grade 5
follows the same rule.

globals.css now describes status as valence — teal above/good, amber
below/needs-attention — which is what it has to mean for an urgent deadline,
rather than the narrower "comparison point only" the first draft claimed.

On the share-card fonts: /opengraph-image is prerendered, so the font read
happens in the builder stage where assets/ exists, and the baked PNG ships
inside .next/standalone/.next/server/app/. File tracing independently places
the fonts at .next/standalone/assets, which the existing standalone COPY
carries to /app/assets. So the reported ENOENT doesn't occur — but it depends
on the tracer resolving a runtime join(), and a miss would be a silent 500
rather than a build failure. Declared outputFileTracingIncludes for the route
and made the Dockerfile COPY explicit so neither is left to inference.

Also repointed the immutable Cache-Control rule from the deleted favicon.svg
to app/icon.svg, where it was caching a 404.

Verified: tsc clean, 159/159 tests, clean rebuild prerenders all three image
routes with the fonts present in standalone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Tudor
2026-08-06 12:29:53 +01:00
co-authored by Claude Opus 5
parent 8ab0ac0a04
commit 8c3a5cc4e9
13 changed files with 51 additions and 30 deletions
@@ -181,8 +181,8 @@
.chipOffer::before { background: var(--status-above); }
.chipUrgent {
border-color: rgba(var(--brand-rgb), 0.4);
background: rgba(var(--brand-rgb), 0.04);
border-color: rgba(var(--status-below-rgb), 0.4);
background: rgba(var(--status-below-rgb), 0.04);
}
.chipTrack {
@@ -218,7 +218,7 @@
.chipDeadline .chipDays,
.chipUrgent .chipDays {
color: var(--brand-strong);
color: var(--status-below);
}
.chipOffer .chipDays {
+2 -2
View File
@@ -28,8 +28,8 @@
}
.bad {
background: var(--brand-bg);
color: var(--brand-strong);
background: var(--status-below-bg);
color: var(--status-below);
}
.neutral {
+3 -3
View File
@@ -1308,8 +1308,8 @@
}
.countdownChipUrgent {
border-color: rgba(var(--brand-rgb), 0.4);
background: rgba(var(--brand-rgb), 0.04);
border-color: rgba(var(--status-below-rgb), 0.4);
background: rgba(var(--status-below-rgb), 0.04);
}
.chipTrack {
@@ -1350,7 +1350,7 @@
.countdownChipDeadline .chipDays,
.countdownChipUrgent .chipDays {
color: var(--brand-strong);
color: var(--status-below);
}
.countdownChipOffer .chipDays {
+1 -1
View File
@@ -604,7 +604,7 @@ function CompactSchoolItem({ school, onAddToCompare, isInCompare, nationalAvgRwm
...(ofstedBadge.cssClass === 'ofsted1' ? { background: 'var(--status-above-bg)', color: 'var(--status-above)' } :
ofstedBadge.cssClass === 'ofsted2' ? { background: 'var(--status-above-bg)', color: 'var(--status-above)' } :
ofstedBadge.cssClass === 'ofsted3' ? { background: 'var(--status-below-bg)', color: 'var(--status-below)' } :
ofstedBadge.cssClass === 'ofsted4' ? { background: 'var(--brand-bg)', color: 'var(--brand)' } :
ofstedBadge.cssClass === 'ofsted4' ? { background: 'var(--status-below)', color: 'var(--text-inverse)' } :
ofstedBadge.cssClass === 'ofstedRc' ? { background: 'var(--phase-secondary-text)', color: 'var(--text-inverse)' } :
ofstedBadge.cssClass === 'ofstedPending' ? { background: 'var(--bg-secondary)', color: 'var(--text-muted)' } :
{ background: 'var(--bg-secondary)', color: 'var(--text-muted)' }),
+1 -1
View File
@@ -58,7 +58,7 @@ function buildPopupBadge(school: School): PopupBadge {
1: 'background:var(--status-above-bg);color:var(--status-above)',
2: 'background:var(--status-above-bg);color:var(--status-above)',
3: 'background:var(--status-below-bg);color:var(--status-below)',
4: 'background:var(--brand-bg);color:var(--brand)',
4: 'background:var(--status-below);color:var(--text-inverse)',
};
return { label: `${labels[school.ofsted_grade]}${yearStr}`, style: colours[school.ofsted_grade] };
}
+2 -2
View File
@@ -132,8 +132,8 @@
}
.trendDown {
color: var(--brand);
background: var(--brand-bg);
color: var(--status-below);
background: var(--status-below-bg);
}
.trendStable {
+2 -2
View File
@@ -139,7 +139,7 @@
}
.trendUp { color: var(--status-above); }
.trendDown { color: var(--brand); }
.trendDown { color: var(--status-below); }
.trendStable { color: var(--text-muted); }
/* Line 4: location */
@@ -204,7 +204,7 @@
.ofsted1 { background: var(--status-above-bg); color: var(--status-above); }
.ofsted2 { background: rgba(var(--status-above-rgb), 0.12); color: var(--status-above); }
.ofsted3 { background: var(--status-below-bg); color: var(--status-below); }
.ofsted4 { background: var(--brand-bg); color: var(--brand); }
.ofsted4 { background: var(--status-below); color: var(--text-inverse); }
/* ── Ofsted badge variants ──────────────────────────────────────────────── */
/* ofsted14 already defined above; these cover the two new framework states */
@@ -128,7 +128,7 @@
}
.deltaPositive { color: var(--status-above); }
.deltaNegative { color: var(--brand); }
.deltaNegative { color: var(--status-below); }
/* Line 4: location + distance */
.line4 {
@@ -207,7 +207,7 @@
.ofsted1 { background: var(--status-above-bg); color: var(--status-above); }
.ofsted2 { background: rgba(var(--status-above-rgb), 0.12); color: var(--status-above); }
.ofsted3 { background: var(--status-below-bg); color: var(--status-below); }
.ofsted4 { background: var(--brand-bg); color: var(--brand); }
.ofsted4 { background: var(--status-below); color: var(--text-inverse); }
/* ── Ofsted badge variants ──────────────────────────────────────────────── */
.ofstedRc { background: var(--phase-secondary-text); color: var(--text-inverse); }
@@ -123,8 +123,8 @@
}
.chipBad {
background: var(--brand-bg);
color: var(--brand-strong);
background: var(--status-below-bg);
color: var(--status-below);
}
.chipNeutral {
@@ -151,8 +151,8 @@
}
.badgeBad {
background: var(--brand-bg);
color: var(--brand-strong);
background: var(--status-below-bg);
color: var(--status-below);
}
.rcList {
@@ -860,7 +860,7 @@
}
.progressNegative {
color: var(--brand-strong);
color: var(--status-below);
font-weight: 700;
}
@@ -876,8 +876,8 @@
}
.statusBad {
background: var(--brand-bg);
color: var(--brand-strong);
background: var(--status-below-bg);
color: var(--status-below);
}
/* Charts Section */
@@ -1025,8 +1025,8 @@
color: var(--status-below);
}
.ofstedGrade4 {
background: var(--brand-bg);
color: var(--brand-strong);
background: var(--status-below);
color: var(--text-inverse);
}
/* Report Card grade colours (5-level scale, lower = better) */
@@ -1047,8 +1047,8 @@
color: var(--status-below);
} /* Needs attention */
.rcGrade5 {
background: var(--brand-bg);
color: var(--brand-strong);
background: var(--status-below);
color: var(--text-inverse);
} /* Urgent improvement */
/* Safeguarding value (used inside a standard metricCard) */