+ );
+}
diff --git a/nextjs-app/lib/metrics.ts b/nextjs-app/lib/metrics.ts
new file mode 100644
index 0000000..e679a45
--- /dev/null
+++ b/nextjs-app/lib/metrics.ts
@@ -0,0 +1,113 @@
+/**
+ * Plain-language metric labels and explanations.
+ * Single source of truth for all metric display strings.
+ */
+
+export interface MetricExplanation {
+ label: string;
+ plain: string;
+ detail?: string;
+}
+
+export const METRIC_EXPLANATIONS: Record = {
+ rwm_expected_pct: {
+ label: 'Reading, Writing & Maths',
+ plain: '% of pupils achieving the expected standard in all three subjects at age 11',
+ detail: 'The national average is around 60%. Higher means more pupils reached the expected level.',
+ },
+ rwm_high_pct: {
+ label: 'Higher Standard — Reading, Writing & Maths',
+ plain: '% of pupils exceeding the expected level in all three subjects',
+ detail: 'A more demanding threshold. The national average is around 8%.',
+ },
+ reading_expected_pct: {
+ label: 'Reading — Expected Standard',
+ plain: '% of pupils achieving the expected standard in reading at age 11',
+ },
+ writing_expected_pct: {
+ label: 'Writing — Expected Standard',
+ plain: '% of pupils achieving the expected standard in writing at age 11',
+ },
+ maths_expected_pct: {
+ label: 'Maths — Expected Standard',
+ plain: '% of pupils achieving the expected standard in maths at age 11',
+ },
+ reading_high_pct: {
+ label: 'Reading — Higher Standard',
+ plain: '% of pupils exceeding the expected level in reading',
+ },
+ writing_high_pct: {
+ label: 'Writing — Higher Standard',
+ plain: '% of pupils exceeding the expected level in writing',
+ },
+ maths_high_pct: {
+ label: 'Maths — Higher Standard',
+ plain: '% of pupils exceeding the expected level in maths',
+ },
+ gps_expected_pct: {
+ label: 'Grammar & Spelling',
+ plain: '% of pupils achieving the expected standard in grammar, punctuation & spelling',
+ },
+ science_expected_pct: {
+ label: 'Science',
+ plain: '% of pupils achieving the expected standard in science',
+ },
+ reading_progress: {
+ label: 'Reading Progress',
+ plain: 'How much pupils improved in reading compared to similar schools',
+ detail: '0 = national average. Positive means better-than-average progress from Year 2 to Year 6.',
+ },
+ writing_progress: {
+ label: 'Writing Progress',
+ plain: 'How much pupils improved in writing compared to similar schools',
+ detail: '0 = national average. Positive means better-than-average progress from Year 2 to Year 6.',
+ },
+ maths_progress: {
+ label: 'Maths Progress',
+ plain: 'How much pupils improved in maths compared to similar schools',
+ detail: '0 = national average. Positive means better-than-average progress from Year 2 to Year 6.',
+ },
+ reading_avg_score: {
+ label: 'Reading Average Score',
+ plain: 'Average scaled score in the reading test (range 80–120, average = 100)',
+ },
+ maths_avg_score: {
+ label: 'Maths Average Score',
+ plain: 'Average scaled score in the maths test (range 80–120, average = 100)',
+ },
+ gps_avg_score: {
+ label: 'Grammar & Spelling Average Score',
+ plain: 'Average scaled score in the grammar, punctuation & spelling test',
+ },
+ overall_absence_pct: {
+ label: 'Absence Rate',
+ plain: '% of school sessions missed due to any reason',
+ detail: 'Lower is better. The national average is around 5%.',
+ },
+ persistent_absence_pct: {
+ label: 'Persistent Absence',
+ plain: '% of pupils missing 10% or more of school sessions',
+ detail: 'Lower is better. Persistent absence can significantly affect attainment.',
+ },
+ rwm_expected_disadvantaged_pct: {
+ label: 'Disadvantaged Pupils — Reading, Writing & Maths',
+ plain: '% of disadvantaged pupils achieving the expected standard in all three subjects',
+ },
+ disadvantaged_gap: {
+ label: 'Disadvantaged Gap',
+ plain: 'Difference in attainment between disadvantaged pupils and their peers',
+ detail: 'A smaller gap means the school is doing more to support disadvantaged pupils.',
+ },
+};
+
+/**
+ * Returns a plain-English band label for a KS2 progress score.
+ * Progress scores are centred at 0 (= national average).
+ */
+export function progressBand(score: number): string {
+ if (score > 3) return 'well above average';
+ if (score > 1) return 'above average';
+ if (score >= -1) return 'around average';
+ if (score >= -3) return 'below average';
+ return 'well below average';
+}