feat(design): adopt the Cohort identity — new palette, type, mark and dark theme
PR Checks / Frontend Typecheck + Tests (pull_request) Successful in 1m6s
PR Checks / Backend Smoke (pull_request) Successful in 7s
PR Checks / Build Backend (no push) (pull_request) Successful in 12s
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 3m13s

Implements the direction agreed from the identity board: Route C ("Cohort")
with the paper ground from C1, the Schibsted Grotesk / Literata pairing from
C2, and the iris accent from C3. Dark theme is in scope from the start rather
than retrofitted.

The audit found three things wrong beyond taste:

* No brand asset set. og:image was absent entirely, so every link shared into
  a class WhatsApp group rendered as a bare grey card. apple-touch-icon pointed
  at an SVG, which iOS ignores, and the manifest shipped no PNGs, so Android
  installs had no icon. The header mark and the favicon had also drifted into
  two different logos.
* No colour discipline. --primary and --trend-down were the same coral, so the
  main CTA and "below average" shared a hue. 58 distinct hex values were spread
  across component CSS, and the chart palette was still Chart.js's stock demo
  colours.
* A dark theme that was declared but never built — themeColor announced a dark
  variant with no dark styling behind it.

What changed:

Colour now has exactly three jobs that never borrow each other's hues: brand
(iris) for interactive and identity, status (teal/amber) for above/below a
comparison point, and phase for categories. Teal/amber rather than green/red
keeps the above/below signal readable for every form of colour blindness.
Every chromatic literal in component CSS is now a token, and the JS-painted
surfaces (Chart.js, Leaflet) read the tokens through lib/theme so they follow
the theme instead of ignoring it.

The mark is the five-bar cohort spread — the same object as the distribution
strip inside a school row, built from opacity steps so it inverts cleanly.
components/Logo.tsx is the single source; the favicon, apple-icon and share
card all derive from its geometry.

globals.css drops 123 dead global classes left over from the vanilla-JS app
(only the btn family, .skip-link and .main were still referenced), along with
the noise overlay. It also gains prefers-reduced-motion support, which was
missing entirely, and a type scale so the 54 ad-hoc font sizes have somewhere
to converge.

Verified: tsc clean, 159 unit tests pass, production build succeeds and
prerenders /icon.svg, /apple-icon and /opengraph-image. Three e2e journeys
added for the asset set, the themeColor/background match, and the dark theme
actually repainting — all silent failures that nothing on the page reveals.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Tudor
2026-08-06 12:13:04 +01:00
co-authored by Claude Opus 5
parent c298a29b61
commit 8ab0ac0a04
56 changed files with 2019 additions and 3073 deletions
+14 -6
View File
@@ -9,6 +9,7 @@
import { Line } from 'react-chartjs-2';
import { ChartOptions } from 'chart.js';
import '@/lib/chartSetup';
import { useThemeTokens, alpha } from '@/lib/theme';
import { formatAcademicYear } from '@/lib/utils';
import { fillAcademicYears } from '@/lib/compareChartData';
import type { SchoolAdmissions } from '@/lib/types';
@@ -38,6 +39,11 @@ export default function AdmissionsTrendChart({ history }: { history: SchoolAdmis
const yMin = Math.max(0, Math.floor((lo - padded) / 5) * 5);
const yMax = Math.min(100, Math.ceil((hi + padded) / 5) * 5);
// Canvas can't read var(), so pull the resolved tokens through the bridge.
const [cBrand, cGrid, cInverse, cInverseText, cCard] = useThemeTokens(
'--brand', '--chart-grid', '--surface-inverse', '--text-inverse', '--bg-card'
);
const options: ChartOptions<'line'> = {
responsive: true,
maintainAspectRatio: false,
@@ -49,7 +55,9 @@ export default function AdmissionsTrendChart({ history }: { history: SchoolAdmis
legend: { display: false },
title: { display: false },
tooltip: {
backgroundColor: 'rgba(26,22,18,0.92)',
backgroundColor: cInverse,
titleColor: cInverseText,
bodyColor: cInverseText,
padding: 10,
titleFont: { size: 12 },
bodyFont: { size: 12 },
@@ -62,7 +70,7 @@ export default function AdmissionsTrendChart({ history }: { history: SchoolAdmis
y: {
min: yMin,
max: yMax,
grid: { color: 'rgba(0,0,0,0.05)' },
grid: { color: cGrid },
ticks: { font: { size: 11 }, maxTicksLimit: 5, callback: (v) => `${v}%` },
},
x: {
@@ -80,14 +88,14 @@ export default function AdmissionsTrendChart({ history }: { history: SchoolAdmis
data: values,
clip: false as const,
spanGaps: false,
borderColor: '#e07256',
backgroundColor: 'rgba(224,114,86,0.10)',
borderColor: cBrand,
backgroundColor: alpha('--brand', 0.10),
borderWidth: 2.5,
tension: 0.3,
fill: true,
pointRadius: values.map((_, i) => (i === lastIdx ? 5 : 3)),
pointBackgroundColor: '#e07256',
pointBorderColor: '#fff',
pointBackgroundColor: cBrand,
pointBorderColor: cCard,
pointBorderWidth: values.map((_, i) => (i === lastIdx ? 2 : 0)),
pointHoverRadius: 6,
},
+79 -74
View File
@@ -27,7 +27,7 @@
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
margin-bottom: 0.85rem;
padding-left: 0.85rem;
}
@@ -39,7 +39,7 @@
display: flex;
flex-direction: column;
gap: 0.1rem;
border-left: 2px solid var(--border-color, #e5dfd5);
border-left: 2px solid var(--border);
}
.navLink {
@@ -51,33 +51,33 @@
border-left: 2px solid transparent;
font-size: 0.88rem;
font-weight: 500;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
text-decoration: none;
cursor: pointer;
transition: color 0.15s ease, border-color 0.15s ease;
}
.navLink:hover {
color: var(--text-primary, #1a1612);
color: var(--text-primary);
}
.navLinkActive {
color: var(--accent-teal, #2d7d7d);
color: var(--brand);
font-weight: 700;
border-left-color: var(--accent-teal, #2d7d7d);
border-left-color: var(--brand);
}
.navDot {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--border-color, #e5dfd5);
background: var(--border);
flex-shrink: 0;
transition: background 0.15s ease;
}
.navLinkActive .navDot {
background: var(--accent-teal, #2d7d7d);
background: var(--brand);
}
/* ─── Hero ───────────────────────────────────────────── */
@@ -95,8 +95,8 @@
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--accent-teal, #2d7d7d);
background: rgba(45, 125, 125, 0.1);
color: var(--brand);
background: rgba(var(--brand-rgb), 0.1);
padding: 0.3rem 0.7rem;
border-radius: 999px;
margin-bottom: 1rem;
@@ -107,22 +107,22 @@
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--accent-teal, #2d7d7d);
background: var(--brand);
}
.heroTitle {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
font-size: 2.75rem;
font-weight: 700;
line-height: 1.1;
letter-spacing: -0.015em;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
margin-bottom: 0.85rem;
}
.heroSub {
font-size: 1.05rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
max-width: 640px;
margin: 0 auto;
line-height: 1.55;
@@ -132,7 +132,7 @@
.countdownSection {
padding: 0 0 2.5rem;
border-bottom: 1px solid var(--border-color, #e5dfd5);
border-bottom: 1px solid var(--border);
margin-bottom: 2.5rem;
}
@@ -145,7 +145,7 @@
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
}
.countdownRail {
@@ -155,11 +155,11 @@
}
.chip {
background: var(--bg-card, #fff);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 12px;
padding: 1rem 1.1rem 0.9rem;
box-shadow: 0 2px 8px rgba(26, 22, 18, 0.06);
box-shadow: 0 2px 8px rgba(var(--shadow-rgb), 0.06);
display: flex;
flex-direction: column;
gap: 0.2rem;
@@ -177,12 +177,12 @@
border-radius: 12px 12px 0 0;
}
.chipDeadline::before { background: var(--accent-coral, #e07256); }
.chipOffer::before { background: var(--accent-teal, #2d7d7d); }
.chipDeadline::before { background: var(--brand); }
.chipOffer::before { background: var(--status-above); }
.chipUrgent {
border-color: rgba(224, 114, 86, 0.4);
background: rgba(224, 114, 86, 0.04);
border-color: rgba(var(--brand-rgb), 0.4);
background: rgba(var(--brand-rgb), 0.04);
}
.chipTrack {
@@ -196,8 +196,8 @@
margin-bottom: 0.15rem;
}
.chipTrackDeadline { color: var(--accent-coral-dark, #b04a2e); }
.chipTrackOffer { color: var(--accent-teal, #2d7d7d); }
.chipTrackDeadline { color: var(--brand-strong); }
.chipTrackOffer { color: var(--status-above); }
.chipTrackDot {
width: 5px;
@@ -208,7 +208,8 @@
}
.chipDays {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-variant-numeric: tabular-nums;
font-family: var(--font-display);
font-size: 2.6rem;
font-weight: 700;
line-height: 1;
@@ -217,17 +218,17 @@
.chipDeadline .chipDays,
.chipUrgent .chipDays {
color: var(--accent-coral-dark, #c45a3f);
color: var(--brand-strong);
}
.chipOffer .chipDays {
color: var(--accent-teal, #2d7d7d);
color: var(--status-above);
}
.chipDaysUnit {
font-size: 0.78rem;
font-weight: 500;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
margin-left: 0.2rem;
vertical-align: bottom;
line-height: 2;
@@ -236,14 +237,14 @@
.chipMilestone {
font-size: 0.85rem;
font-weight: 600;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
line-height: 1.25;
margin-top: 0.1rem;
}
.chipDate {
font-size: 0.75rem;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
margin-top: 0.05rem;
}
@@ -251,8 +252,8 @@
.track {
margin-bottom: 3rem;
background: var(--bg-card, #fff);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 14px;
overflow: hidden;
}
@@ -263,7 +264,7 @@
justify-content: space-between;
gap: 1.5rem;
padding: 1.75rem 2rem 1.5rem;
border-bottom: 1px solid var(--border-color, #e5dfd5);
border-bottom: 1px solid var(--border);
flex-wrap: wrap;
}
@@ -278,22 +279,22 @@
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
margin-bottom: 0.35rem;
}
.trackTitle {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
font-size: 1.5rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
margin-bottom: 0.4rem;
line-height: 1.2;
}
.trackSub {
font-size: 0.9rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
line-height: 1.5;
margin: 0;
}
@@ -317,13 +318,13 @@
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
}
.trackDateVal {
font-size: 0.88rem;
font-weight: 600;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
}
/* ─── Timeline ───────────────────────────────────────── */
@@ -356,27 +357,27 @@
width: 14px;
height: 14px;
border-radius: 50%;
background: var(--bg-card, #fff);
border: 2px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 2px solid var(--border);
flex-shrink: 0;
transition: border-color 0.2s ease, background 0.2s ease;
}
.stepDeadline .stepDot {
background: rgba(224, 114, 86, 0.15);
border-color: var(--accent-coral, #e07256);
background: rgba(var(--brand-rgb), 0.15);
border-color: var(--brand);
}
.stepOffer .stepDot {
background: rgba(45, 125, 125, 0.15);
border-color: var(--accent-teal, #2d7d7d);
background: rgba(var(--status-above-rgb), 0.15);
border-color: var(--status-above);
}
.stepLine {
width: 2px;
flex: 1;
min-height: 24px;
background: var(--border-color, #e5dfd5);
background: var(--border);
margin: 4px 0;
}
@@ -395,27 +396,28 @@
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
margin-bottom: 0.2rem;
}
.stepDeadline .stepDate { color: var(--accent-coral-dark, #b04a2e); }
.stepOffer .stepDate { color: var(--accent-teal, #2d7d7d); }
.stepDeadline .stepDate { color: var(--brand-strong); }
.stepOffer .stepDate { color: var(--status-above); }
.stepTitle {
font-size: 0.95rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
margin-bottom: 0.3rem;
line-height: 1.3;
}
.stepDeadline .stepTitle { color: var(--accent-coral-dark, #c45a3f); }
.stepOffer .stepTitle { color: var(--accent-teal, #2d7d7d); }
.stepDeadline .stepTitle { color: var(--brand-strong); }
.stepOffer .stepTitle { color: var(--status-above); }
.stepBody {
font-family: var(--font-prose);
font-size: 0.88rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
line-height: 1.55;
margin: 0;
}
@@ -427,13 +429,13 @@
margin-top: 0.6rem;
font-size: 0.82rem;
font-weight: 600;
color: var(--accent-teal, #2d7d7d);
color: var(--status-above);
text-decoration: none;
transition: gap 0.2s ease, color 0.2s ease;
}
.stepTool:hover {
color: var(--accent-coral-dark, #c45a3f);
color: var(--brand-strong);
gap: 0.6rem;
}
@@ -455,9 +457,9 @@
display: flex;
gap: 0.55rem;
padding: 0.6rem 0.75rem;
background: var(--accent-gold-bg, rgba(201, 162, 39, 0.12));
border: 1px solid rgba(201, 162, 39, 0.28);
border-left: 3px solid var(--accent-gold, #c9a227);
background: var(--status-below-bg);
border: 1px solid rgba(var(--status-below-rgb), 0.28);
border-left: 3px solid var(--status-below);
border-radius: 8px;
}
@@ -467,8 +469,8 @@
height: 1.05rem;
margin-top: 0.1rem;
border-radius: 50%;
background: var(--accent-gold, #c9a227);
color: #fff;
background: var(--status-below);
color: var(--text-inverse);
font-size: 0.72rem;
font-weight: 800;
line-height: 1.05rem;
@@ -482,14 +484,15 @@
.calloutTitle {
font-size: 0.82rem;
font-weight: 700;
color: var(--accent-gold-text, #7a6800);
color: var(--status-below);
line-height: 1.3;
margin-bottom: 0.15rem;
}
.calloutBody {
font-family: var(--font-prose);
font-size: 0.82rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
line-height: 1.5;
margin: 0;
}
@@ -501,10 +504,10 @@
}
.tipsHeading {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
font-size: 1.35rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
margin-bottom: 1.25rem;
}
@@ -515,16 +518,17 @@
}
.tipCard {
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
border-radius: 12px;
padding: 1.25rem;
}
.tipNumber {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-variant-numeric: tabular-nums;
font-family: var(--font-display);
font-size: 1.75rem;
font-weight: 700;
color: #7d766b; /* 3.8:1 on cream — AA large-text for this 28px numeral */
color: var(--text-muted); /* 3.8:1 on cream — AA large-text for this 28px numeral */
line-height: 1;
margin-bottom: 0.6rem;
}
@@ -532,14 +536,15 @@
.tipHeading {
font-size: 0.95rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
margin-bottom: 0.4rem;
line-height: 1.3;
}
.tipBody {
font-family: var(--font-prose);
font-size: 0.875rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
line-height: 1.55;
margin: 0;
}
@@ -557,8 +562,8 @@
position: sticky;
top: 0;
padding-top: 0;
background: var(--bg-primary, #faf8f3);
border-bottom: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-primary);
border-bottom: 1px solid var(--border);
margin: 0 -1.25rem 1rem;
padding: 0.6rem 1.25rem;
z-index: 10;
@@ -590,8 +595,8 @@
}
.navLinkActive {
background: var(--text-primary, #1a1612);
color: #fff;
background: var(--text-primary);
color: var(--text-inverse);
border-left: none;
}
@@ -43,7 +43,7 @@
min-height: 40px;
min-width: 0;
padding: 4px 10px;
border: 1px solid rgba(0, 0, 0, .12);
border: 1px solid var(--border);
border-radius: 999px;
background: transparent;
cursor: pointer;
@@ -52,8 +52,8 @@
}
.chip[aria-pressed="true"] {
background: rgba(0, 0, 0, .06);
border-color: rgba(0, 0, 0, .35);
background: var(--bg-secondary);
border-color: var(--border-strong);
}
.chipDot {
+14 -4
View File
@@ -15,6 +15,7 @@ import { useEffect, useState } from 'react';
import { Line } from 'react-chartjs-2';
import { ChartOptions, ChartDataset, PointStyle } from 'chart.js';
import '@/lib/chartSetup';
import { useSeriesColors, useThemeTokens } from '@/lib/theme';
import { buildCompareChart } from '@/lib/compareChartData';
import type { ComparisonData } from '@/lib/types';
import {
@@ -48,6 +49,13 @@ const POINT_STYLES: PointStyle[] = ['circle', 'triangle', 'rect', 'rectRot', 'st
export function ComparisonChart({ comparisonData, schools, metric, metricLabel, nationalByYear, isSecondary = false }: ComparisonChartProps) {
const isMobile = useIsMobile();
// Canvas can't resolve var(), so the series come through the token bridge.
// Same index order as CHART_COLORS, so a school's line and its DOM swatch
// stay the same colour.
const seriesColors = useSeriesColors();
const [cRef, cGrid, cInverse, cInverseText] = useThemeTokens(
'--chart-reference', '--chart-grid', '--surface-inverse', '--text-inverse'
);
const [focusedUrn, setFocusedUrn] = useState<number | null>(null);
// A focused school that leaves the basket must not linger.
@@ -67,7 +75,7 @@ export function ComparisonChart({ comparisonData, schools, metric, metricLabel,
const datasets: ChartDataset<'line'>[] = built.schoolDatasets.map((series) => {
const school = schools[series.schoolIndex];
const color = CHART_COLORS[series.schoolIndex % CHART_COLORS.length];
const color = seriesColors[series.schoolIndex % seriesColors.length];
const dimmed = focusedUrn !== null && focusedUrn !== school.urn;
return {
@@ -90,7 +98,7 @@ export function ComparisonChart({ comparisonData, schools, metric, metricLabel,
datasets.push({
label: built.englandDataset.label,
data: built.englandDataset.data,
borderColor: 'rgba(109, 104, 95, 0.9)',
borderColor: cRef,
backgroundColor: 'transparent',
borderWidth: 1.5,
borderDash: built.englandDataset.borderDash,
@@ -138,7 +146,9 @@ export function ComparisonChart({ comparisonData, schools, metric, metricLabel,
display: false,
},
tooltip: {
backgroundColor: 'rgba(0, 0, 0, 0.8)',
backgroundColor: cInverse,
titleColor: cInverseText,
bodyColor: cInverseText,
padding: isMobile ? 10 : 12,
titleFont: {
size: isMobile ? 12 : 14,
@@ -182,7 +192,7 @@ export function ComparisonChart({ comparisonData, schools, metric, metricLabel,
...(isMobile && { maxTicksLimit: 5 }),
},
grid: {
color: 'rgba(0, 0, 0, 0.05)',
color: cGrid,
},
},
x: {
@@ -23,11 +23,11 @@
flex-direction: column;
gap: 0;
padding: 1rem 1.25rem;
background: var(--bg-primary, #faf7f2);
color: var(--text-primary, #2c2420);
background: var(--bg-primary);
color: var(--text-primary);
border-radius: 16px;
box-shadow: 0 8px 32px rgba(44, 36, 32, 0.18), 0 2px 8px rgba(44, 36, 32, 0.08);
border: 1px solid var(--border-color, #e8ddd4);
box-shadow: 0 8px 32px rgba(var(--shadow-rgb), 0.18), 0 2px 8px rgba(var(--shadow-rgb), 0.08);
border: 1px solid var(--border);
min-width: 280px;
}
@@ -37,8 +37,8 @@
justify-content: center;
width: 28px;
height: 28px;
background: var(--accent-coral, #e07256);
color: white;
background: var(--brand);
color: var(--brand-on);
border-radius: 50%;
font-weight: 700;
font-size: 0.9rem;
@@ -62,13 +62,13 @@
gap: 0.5rem;
font-weight: 600;
font-size: 0.875rem;
color: var(--text-primary, #2c2420);
color: var(--text-primary);
}
.collapseBtn {
background: none;
border: none;
color: var(--text-muted, #8a7a72);
color: var(--text-muted);
cursor: pointer;
padding: 0.25rem;
line-height: 1;
@@ -79,7 +79,7 @@
}
.collapseBtn:hover {
color: var(--text-primary, #2c2420);
color: var(--text-primary);
}
.schoolList {
@@ -95,13 +95,13 @@
justify-content: space-between;
gap: 0.5rem;
padding: 0.3rem 0.5rem;
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
border-radius: var(--radius-sm, 4px);
}
.schoolName {
font-size: 0.8rem;
color: var(--text-primary, #2c2420);
color: var(--text-primary);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@@ -111,7 +111,7 @@
.removeSchoolBtn {
background: none;
border: none;
color: var(--text-muted, #8a7a72);
color: var(--text-muted);
cursor: pointer;
font-size: 1rem;
padding: 0 0.25rem;
@@ -121,7 +121,7 @@
}
.removeSchoolBtn:hover {
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
}
.toastActions {
@@ -129,13 +129,13 @@
align-items: center;
gap: 0.75rem;
padding-top: 0.625rem;
border-top: 1px solid var(--border-color, #e8ddd4);
border-top: 1px solid var(--border);
}
.btnClearAll {
background: none;
border: none;
color: var(--text-muted, #8a7a72);
color: var(--text-muted);
font-size: 0.85rem;
font-weight: 500;
cursor: pointer;
@@ -145,13 +145,13 @@
}
.btnClearAll:hover {
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
}
.btnCompare {
flex: 1;
background: var(--accent-coral, #e07256);
color: white;
background: var(--brand);
color: var(--brand-on);
padding: 0.6rem 1.25rem;
border-radius: 25px;
font-weight: 600;
@@ -164,7 +164,7 @@
.btnCompare:hover {
transform: translateY(-1px);
background: var(--accent-coral-dark, #c9614a);
background: var(--brand-strong);
}
/* Hidden on phones — the bottom tab bar's Compare badge already
+26 -26
View File
@@ -18,14 +18,14 @@
.header h1 {
font-size: 2.25rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
margin-bottom: 0.5rem;
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
}
.subtitle {
font-size: 1rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
margin: 0;
line-height: 1.6;
max-width: 60ch;
@@ -43,7 +43,7 @@
display: flex;
gap: 0;
margin-bottom: 1.5rem;
border: 1px solid var(--border-color, #e5dfd5);
border: 1px solid var(--border);
border-radius: 8px;
overflow: hidden;
width: fit-content;
@@ -53,8 +53,8 @@
padding: 0.625rem 1.5rem;
font-size: 0.9375rem;
font-weight: 500;
background: var(--bg-card, white);
color: var(--text-secondary, #5c564d);
background: var(--bg-card);
color: var(--text-secondary);
border: none;
cursor: pointer;
transition: all 0.15s ease;
@@ -62,21 +62,21 @@
}
.phaseTab:not(:last-child) {
border-right: 1px solid var(--border-color, #e5dfd5);
border-right: 1px solid var(--border);
}
.phaseTab:hover {
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
}
.phaseTabActive {
background: var(--accent-coral-dark, #b04a2e);
color: white;
background: var(--brand-strong);
color: var(--brand-on);
font-weight: 600;
}
.phaseTabActive:hover {
background: var(--accent-coral-darker, #9c3f26);
background: var(--brand-stronger);
}
/* Sticky school bar — column identity while scrolling; horizontal scroll on
@@ -87,23 +87,23 @@
position: sticky;
top: 65px;
z-index: 10;
background: var(--bg-primary, #faf7f2);
background: var(--bg-primary);
display: flex;
gap: 0.75rem;
overflow-x: auto;
padding: 0.75rem 0;
border-bottom: 1px solid var(--border-light, #e5dfd5);
border-bottom: 1px solid var(--border);
-webkit-overflow-scrolling: touch;
}
.schoolChip {
flex: 1 1 0;
min-width: 180px;
background: var(--bg-card, white);
border: 1px solid var(--border-light, #e5dfd5);
border-top: 3px solid var(--accent-coral, #e07256);
background: var(--bg-card);
border: 1px solid var(--border);
border-top: 3px solid var(--brand);
border-radius: 8px;
box-shadow: var(--shadow-soft, 0 2px 8px rgba(26, 22, 18, 0.06));
box-shadow: var(--shadow-soft, 0 2px 8px rgba(var(--shadow-rgb), 0.06));
padding: 0.55rem 0.75rem;
display: flex;
gap: 0.55rem;
@@ -126,12 +126,12 @@
font-weight: 600;
font-size: 0.92rem;
line-height: 1.25;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
text-decoration: none;
}
.chipName:hover {
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
}
/* Full name on desktop, short name on the compact mobile pills. */
@@ -142,7 +142,7 @@
.chipMeta {
display: block;
font-size: 0.78rem;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@@ -185,22 +185,22 @@
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
}
.barCaptionCount {
font-size: 0.95rem;
font-weight: 600;
line-height: 1.3;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
}
}
.chipRemove {
margin-left: auto;
border: none;
background: var(--bg-secondary, #f3ede4);
color: var(--text-muted, #6d685f);
background: var(--bg-secondary);
color: var(--text-muted);
border-radius: 50%;
width: 22px;
height: 22px;
@@ -212,9 +212,9 @@
.footnote {
font-size: 0.78rem;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
margin-top: 2.5rem;
border-top: 1px solid var(--border-light, #e5dfd5);
border-top: 1px solid var(--border);
padding-top: 1rem;
max-width: 75ch;
}
+6 -6
View File
@@ -23,16 +23,16 @@
}
.good {
background: var(--accent-teal-bg, rgba(45, 125, 125, 0.12));
color: var(--accent-teal, #2d7d7d);
background: var(--status-above-bg);
color: var(--status-above);
}
.bad {
background: var(--accent-coral-bg, rgba(224, 114, 86, 0.12));
color: var(--accent-coral-dark, #b04a2e);
background: var(--brand-bg);
color: var(--brand-strong);
}
.neutral {
background: var(--bg-secondary, #f3ede4);
color: var(--text-muted, #8a847a);
background: var(--bg-secondary);
color: var(--text-muted);
}
+1 -1
View File
@@ -61,7 +61,7 @@
border-radius: 50%;
transform: translateX(-50%);
border: 2px solid var(--bg-card);
box-shadow: 0 0 0 1px rgba(26, 22, 18, 0.08);
box-shadow: 0 0 0 1px rgba(var(--shadow-rgb), 0.08);
}
.pointLabel {
+11 -11
View File
@@ -5,15 +5,15 @@
justify-content: center;
padding: 4rem 2rem;
text-align: center;
background: var(--bg-card, white);
border: 2px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 2px solid var(--border);
border-radius: 16px;
min-height: 400px;
box-shadow: var(--shadow-soft, 0 2px 8px rgba(26, 22, 18, 0.06));
box-shadow: var(--shadow-soft, 0 2px 8px rgba(var(--shadow-rgb), 0.06));
}
.icon {
color: var(--text-muted, #8a847a);
color: var(--text-muted);
margin-bottom: 1.5rem;
opacity: 0.7;
}
@@ -22,14 +22,14 @@
margin: 0 0 0.75rem 0;
font-size: 1.5rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
font-family: var(--font-playfair), 'Playfair Display', serif;
color: var(--text-primary);
font-family: var(--font-display);
}
.message {
margin: 0 0 2rem 0;
font-size: 1rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
max-width: 500px;
line-height: 1.6;
}
@@ -38,8 +38,8 @@
padding: 0.875rem 2rem;
font-size: 1rem;
font-weight: 600;
background: var(--accent-coral, #e07256);
color: white;
background: var(--brand);
color: var(--brand-on);
border: none;
border-radius: 8px;
cursor: pointer;
@@ -47,9 +47,9 @@
}
.button:hover {
background: var(--accent-coral-dark, #c45a3f);
background: var(--brand-strong);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(224, 114, 86, 0.3);
box-shadow: 0 4px 12px rgba(var(--brand-rgb), 0.3);
}
.button:active {
+47 -47
View File
@@ -1,10 +1,10 @@
.filterBar {
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 10px;
padding: 1.5rem;
margin-bottom: 2rem;
box-shadow: var(--shadow-soft, 0 2px 8px rgba(26, 22, 18, 0.06));
box-shadow: var(--shadow-soft, 0 2px 8px rgba(var(--shadow-rgb), 0.06));
transition: opacity 0.2s ease;
}
@@ -17,9 +17,9 @@
padding: 2.5rem;
max-width: 800px;
margin: 0 auto 3rem auto;
box-shadow: 0 8px 24px rgba(26, 22, 18, 0.08);
box-shadow: 0 8px 24px rgba(var(--shadow-rgb), 0.08);
border-width: 2px;
border-color: var(--accent-coral, #e07256);
border-color: var(--brand);
}
.heroMode .omniInput {
@@ -39,12 +39,12 @@
.searchHint {
margin: 0.875rem 0 0;
font-size: 0.95rem;
color: var(--text-secondary, #5a554d);
color: var(--text-secondary);
text-align: center;
}
.searchHint strong {
color: var(--text-primary, #1a1612);
color: var(--text-primary);
font-weight: 600;
}
@@ -68,8 +68,8 @@
align-items: center;
gap: 0.5rem;
padding: 0.625rem 1.375rem;
background: var(--accent-teal, #2d7d7d);
color: #fff;
background: var(--brand);
color: var(--brand-on);
border: none;
border-radius: 999px;
font-size: 0.9375rem;
@@ -80,7 +80,7 @@
}
.nearMeBtn:hover:not(:disabled) {
background: #235f5f;
background: var(--status-above);
transform: translateY(-1px);
}
@@ -93,8 +93,8 @@
display: inline-block;
width: 14px;
height: 14px;
border: 2px solid rgba(255, 255, 255, 0.35);
border-top-color: #fff;
border: 2px solid rgba(var(--text-inverse-rgb), 0.35);
border-top-color: var(--brand-on);
border-radius: 50%;
animation: nearMeSpin 0.7s linear infinite;
flex-shrink: 0;
@@ -108,7 +108,7 @@
.geoError {
font-size: 0.8125rem;
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
margin: 0;
max-width: 340px;
text-align: center;
@@ -134,21 +134,21 @@
flex: 1;
padding: 0.875rem 1.25rem;
font-size: 1.05rem;
border: 2px solid var(--border-color, #e5dfd5);
border: 2px solid var(--border);
border-radius: 8px;
outline: none;
transition: all 0.2s ease;
background: var(--bg-card, white);
background: var(--bg-card);
font-family: inherit;
}
.omniInput:focus {
border-color: var(--accent-coral, #e07256);
box-shadow: 0 0 0 3px var(--accent-coral-bg);
border-color: var(--brand);
box-shadow: 0 0 0 3px var(--brand-bg);
}
.omniInput::placeholder {
color: var(--text-muted, #8a847a);
color: var(--text-muted);
}
.searchButton {
@@ -161,9 +161,9 @@
.spinner {
width: 20px;
height: 20px;
border: 2px solid rgba(255, 255, 255, 0.3);
border: 2px solid rgba(var(--text-inverse-rgb), 0.3);
border-radius: 50%;
border-top-color: white;
border-top-color: var(--brand-on);
animation: spin 0.8s linear infinite;
}
@@ -177,7 +177,7 @@
flex-wrap: wrap;
margin-top: 0.625rem;
padding-top: 0.625rem;
border-top: 1px solid var(--border-color, #e5dfd5);
border-top: 1px solid var(--border);
}
.filterSelect {
@@ -189,26 +189,26 @@
font-size: 0.875rem;
font-weight: 500;
font-family: inherit;
border: 1.5px solid var(--border-color, #e5dfd5);
border: 1.5px solid var(--border);
border-radius: 8px;
background-color: var(--bg-card, white);
background-color: var(--bg-card);
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%238a847a' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 0.875rem center;
background-size: 10px 6px;
cursor: pointer;
outline: none;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.filterSelect:hover {
border-color: var(--text-muted, #8a847a);
border-color: var(--text-muted);
}
.filterSelect:focus {
border-color: var(--accent-coral, #e07256);
box-shadow: 0 0 0 3px rgba(224, 114, 86, 0.12);
border-color: var(--brand);
box-shadow: 0 0 0 3px rgba(var(--brand-rgb), 0.12);
}
.clearButton {
@@ -263,7 +263,7 @@
.radiusLabel {
font-size: 0.8125rem;
font-weight: 500;
color: var(--text-secondary, #5a554d);
color: var(--text-secondary);
white-space: nowrap;
}
@@ -275,7 +275,7 @@
flex-wrap: wrap;
margin-top: 0.875rem;
padding-top: 0.875rem;
border-top: 1px solid var(--border-color, #e5dfd5);
border-top: 1px solid var(--border);
}
.controlsRow .advancedToggle {
@@ -297,14 +297,14 @@
font-size: 0.8125rem;
font-weight: 500;
font-family: inherit;
border: 1.5px solid var(--border-color, #e5dfd5);
border: 1.5px solid var(--border);
border-radius: 999px;
background-color: var(--bg-card, white);
background-color: var(--bg-card);
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%238a847a' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 0.65rem center;
background-size: 10px 6px;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
cursor: pointer;
outline: none;
transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease;
@@ -312,13 +312,13 @@
}
.controlSelect:hover {
border-color: var(--text-muted, #8a847a);
background-color: var(--bg-secondary, #f8f4ef);
border-color: var(--text-muted);
background-color: var(--bg-secondary);
}
.controlSelect:focus {
border-color: var(--accent-coral, #e07256);
box-shadow: 0 0 0 3px rgba(224, 114, 86, 0.12);
border-color: var(--brand);
box-shadow: 0 0 0 3px rgba(var(--brand-rgb), 0.12);
}
/* ── Advanced filters toggle ─────────────────────────── */
@@ -328,12 +328,12 @@
align-items: center;
gap: 0.375rem;
background: none;
border: 1.5px solid var(--border-color, #e5dfd5);
border: 1.5px solid var(--border);
border-radius: 999px;
padding: 0.4rem 0.875rem;
font-size: 0.8125rem;
font-weight: 500;
color: var(--text-secondary, #5a554d);
color: var(--text-secondary);
cursor: pointer;
font-family: inherit;
transition: all 0.15s ease;
@@ -341,24 +341,24 @@
}
.advancedToggle:hover {
border-color: var(--text-muted, #8a847a);
background-color: var(--bg-secondary, #f8f4ef);
color: var(--text-primary, #1a1612);
border-color: var(--text-muted);
background-color: var(--bg-secondary);
color: var(--text-primary);
}
/* When filters are applied, promote the toggle to a coral pill so users
can see at a glance that the result list is being narrowed. */
.advancedToggleActive {
border-color: var(--accent-coral, #e07256);
background: var(--accent-coral-bg, rgba(224, 114, 86, 0.12));
color: var(--accent-coral, #e07256);
border-color: var(--brand);
background: var(--brand-bg);
color: var(--brand);
font-weight: 600;
}
.advancedToggleActive:hover {
border-color: var(--accent-coral-dark, #c45a3f);
background: var(--accent-coral-bg, rgba(224, 114, 86, 0.18));
color: var(--accent-coral-dark, #c45a3f);
border-color: var(--brand-strong);
background: var(--brand-bg);
color: var(--brand-strong);
}
.chevronDown,
+13 -13
View File
@@ -1,6 +1,6 @@
.footer {
background: var(--accent-navy, #2c3e50);
color: var(--bg-secondary, #f3ede4);
background: var(--text-primary);
color: var(--bg-secondary);
margin-top: auto;
}
@@ -27,22 +27,22 @@
margin: 0;
font-size: 1.25rem;
font-weight: 700;
color: var(--bg-primary, #faf7f2);
font-family: var(--font-playfair), 'Playfair Display', serif;
color: var(--bg-primary);
font-family: var(--font-display);
}
.description {
margin: 0;
font-size: 0.875rem;
line-height: 1.6;
color: rgba(250, 247, 242, 0.7);
color: rgba(var(--text-inverse-rgb), 0.7);
}
.sectionTitle {
margin: 0;
font-size: 0.875rem;
font-weight: 600;
color: var(--accent-gold, #c9a227);
color: var(--status-below);
text-transform: uppercase;
letter-spacing: 0.05em;
}
@@ -58,24 +58,24 @@
.link {
font-size: 0.875rem;
color: rgba(250, 247, 242, 0.7);
color: rgba(var(--text-inverse-rgb), 0.7);
text-decoration: none;
transition: color 0.2s ease;
}
.link:hover {
color: var(--accent-gold, #c9a227);
color: var(--status-below);
}
.linkDisabled {
font-size: 0.875rem;
color: rgba(250, 247, 242, 0.4);
color: rgba(var(--text-inverse-rgb), 0.4);
cursor: not-allowed;
}
.bottom {
padding-top: 2rem;
border-top: 1px solid rgba(250, 247, 242, 0.15);
border-top: 1px solid rgba(var(--text-inverse-rgb), 0.15);
display: flex;
flex-direction: column;
gap: 0.5rem;
@@ -85,15 +85,15 @@
.disclaimer {
margin: 0;
font-size: 0.875rem;
color: rgba(250, 247, 242, 0.6);
color: rgba(var(--text-inverse-rgb), 0.6);
}
.disclaimer .link {
color: var(--accent-coral, #e07256);
color: var(--brand);
}
.disclaimer .link:hover {
color: var(--accent-gold, #c9a227);
color: var(--status-below);
}
@media (max-width: 768px) {
+163 -154
View File
@@ -16,8 +16,8 @@
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--accent-teal, #2d7d7d);
background: rgba(45, 125, 125, 0.1);
color: var(--brand);
background: rgba(var(--brand-rgb), 0.1);
padding: 0.3rem 0.7rem;
border-radius: 999px;
margin-bottom: 1rem;
@@ -28,37 +28,37 @@
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--accent-teal, #2d7d7d);
background: var(--brand);
}
.heroTitle {
font-size: 3rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
margin-bottom: 0.85rem;
line-height: 1.08;
letter-spacing: -0.015em;
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
max-width: 840px;
margin-left: auto;
margin-right: auto;
}
.heroEmph {
color: var(--accent-coral-dark, #c45a3f);
color: var(--brand-strong);
font-style: italic;
}
.heroDescription {
font-size: 1.05rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
margin: 0 auto 0.5rem;
max-width: 680px;
line-height: 1.55;
}
.heroDescription strong {
color: var(--text-primary, #1a1612);
color: var(--text-primary);
font-weight: 700;
}
@@ -111,7 +111,7 @@
.viewToggle {
display: flex;
gap: 0.2rem;
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
padding: 0.2rem;
border-radius: 6px;
}
@@ -127,18 +127,18 @@
border: none;
border-radius: 5px;
cursor: pointer;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
transition: all 0.2s ease;
}
.viewToggleBtn:hover {
color: var(--text-primary, #1a1612);
color: var(--text-primary);
}
.viewToggleBtn.active {
background: var(--bg-card, white);
color: var(--accent-coral-dark, #b04a2e);
box-shadow: 0 2px 4px rgba(26, 22, 18, 0.08);
background: var(--bg-card);
color: var(--brand-strong);
box-shadow: 0 2px 4px rgba(var(--shadow-rgb), 0.08);
}
.viewToggleBtn svg {
@@ -166,7 +166,7 @@
.mapContainer {
border-radius: 10px;
overflow: hidden;
border: 1px solid var(--border-color, #e5dfd5);
border: 1px solid var(--border);
height: 100%;
}
@@ -184,17 +184,17 @@
}
.compactList::-webkit-scrollbar-track {
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
border-radius: 3px;
}
.compactList::-webkit-scrollbar-thumb {
background: var(--border-color, #e5dfd5);
background: var(--border);
border-radius: 3px;
}
.compactList::-webkit-scrollbar-thumb:hover {
background: var(--text-muted, #8a847a);
background: var(--text-muted);
}
/* Compact School Item */
@@ -204,15 +204,15 @@
align-items: center;
gap: 0.75rem;
padding: 0.625rem 0.75rem;
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 8px;
transition: all 0.2s ease;
}
.compactItem:hover {
border-color: var(--accent-coral, #e07256);
box-shadow: 0 2px 6px rgba(26, 22, 18, 0.05);
border-color: var(--brand);
box-shadow: 0 2px 6px rgba(var(--shadow-rgb), 0.05);
}
.compactItemContent {
@@ -230,7 +230,7 @@
.compactItemName {
font-weight: 600;
font-size: 0.8125rem;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
text-decoration: none;
white-space: nowrap;
overflow: hidden;
@@ -238,7 +238,7 @@
}
.compactItemName:hover {
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
}
.distanceBadge {
@@ -246,8 +246,8 @@
padding: 0.0625rem 0.375rem;
font-size: 0.6875rem;
font-weight: 600;
background: var(--accent-teal, #2d7d7d);
color: white;
background: var(--brand);
color: var(--brand-on);
border-radius: 3px;
}
@@ -255,25 +255,25 @@
display: flex;
gap: 0.375rem;
font-size: 0.6875rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
margin-bottom: 0.25rem;
}
.compactItemMeta span:not(:last-child)::after {
content: '·';
margin-left: 0.375rem;
color: var(--text-muted, #8a847a);
color: var(--text-muted);
}
.compactItemStats {
display: flex;
gap: 0.75rem;
font-size: 0.6875rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
}
.compactStat strong {
color: var(--text-primary, #1a1612);
color: var(--text-primary);
}
.compactItemActions {
@@ -292,8 +292,8 @@
font-size: 1.5rem;
font-weight: 700;
margin-bottom: 0.5rem;
color: var(--text-primary, #1a1612);
font-family: var(--font-playfair), 'Playfair Display', serif;
color: var(--text-primary);
font-family: var(--font-display);
}
/* Decorative coral bar under section headings */
@@ -302,14 +302,14 @@
display: block;
width: 50px;
height: 2px;
background: var(--accent-coral, #e07256);
background: var(--brand);
border-radius: 1px;
margin-top: 0.5rem;
}
.sectionDescription {
font-size: 0.9375rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
margin: 0;
line-height: 1.5;
}
@@ -336,22 +336,22 @@
.emptyState {
text-align: center;
padding: 2.5rem 1.5rem;
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 10px;
}
.emptyStateTitle {
font-size: 1.25rem;
font-weight: 600;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
margin-bottom: 0.375rem;
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
}
.emptyStateDescription {
font-size: 0.9375rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
max-width: 380px;
margin: 0 auto;
}
@@ -419,9 +419,9 @@
/* Highlighted List Item */
.highlightedItem .compactItem {
border-color: var(--accent-teal, #2d7d7d);
box-shadow: 0 0 0 1px var(--accent-teal, #2d7d7d);
background: var(--bg-secondary, #f3ede4);
border-color: var(--brand);
box-shadow: 0 0 0 1px var(--brand);
background: var(--bg-secondary);
}
/* Mobile Bottom Sheet */
@@ -443,9 +443,9 @@
.bottomSheet {
position: relative;
background: var(--bg-card, white);
background: var(--bg-card);
border-radius: 12px;
box-shadow: 0 -4px 24px rgba(26, 22, 18, 0.15);
box-shadow: 0 -4px 24px rgba(var(--shadow-rgb), 0.15);
pointer-events: auto;
animation: slideUpSheet 0.3s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
@@ -467,16 +467,16 @@
right: -12px;
width: 30px;
height: 30px;
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.25rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
cursor: pointer;
box-shadow: 0 2px 8px rgba(26, 22, 18, 0.1);
box-shadow: 0 2px 8px rgba(var(--shadow-rgb), 0.1);
z-index: 10;
}
@@ -522,7 +522,7 @@
.quickSearchChip {
padding: 0.375rem 0.875rem;
background: var(--bg-card);
border: 1px solid var(--border-color, #e0ddd8);
border: 1px solid var(--border);
border-radius: 999px;
font-size: 0.875rem;
color: var(--text-secondary);
@@ -531,9 +531,9 @@
}
.quickSearchChip:hover {
background: var(--accent-coral-dark);
color: white;
border-color: var(--accent-coral-dark);
background: var(--brand-strong);
color: var(--brand-on);
border-color: var(--brand-strong);
}
.exploringRow {
@@ -546,7 +546,7 @@
.exploringLabel {
font-size: 0.72rem;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
font-weight: 500;
letter-spacing: 0.04em;
text-transform: uppercase;
@@ -564,19 +564,19 @@
align-items: center;
gap: 0.4rem;
padding: 0.5rem 0.95rem;
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 999px;
font-size: 0.82rem;
font-weight: 500;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
text-decoration: none;
transition: all 0.15s ease;
}
.exploringChip:hover {
border-color: var(--accent-coral, #e07256);
color: var(--accent-coral-dark, #c45a3f);
border-color: var(--brand);
color: var(--brand-strong);
transform: translateY(-1px);
}
@@ -606,16 +606,16 @@
}
.hiwHeading {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
font-size: 1.75rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
margin: 0;
}
.hiwSub {
font-size: 0.875rem;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
}
.hiwGrid {
@@ -625,18 +625,18 @@
}
.hiwCard {
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 14px;
padding: 1.25rem;
box-shadow: 0 2px 8px rgba(26, 22, 18, 0.06);
box-shadow: 0 2px 8px rgba(var(--shadow-rgb), 0.06);
display: flex;
flex-direction: column;
gap: 0.9rem;
}
.hiwVisual {
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
border-radius: 10px;
padding: 0.9rem;
min-height: 180px;
@@ -657,11 +657,11 @@
font-weight: 600;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
}
.hiwPhaseLabel strong {
color: var(--accent-teal, #2d7d7d);
color: var(--brand);
font-weight: 700;
}
@@ -676,20 +676,20 @@
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
}
.hiwTitle {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
font-size: 1.1rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
line-height: 1.25;
}
.hiwDesc {
font-size: 0.86rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
line-height: 1.45;
margin: 0;
}
@@ -713,7 +713,7 @@
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
margin-bottom: 0.1rem;
}
@@ -723,16 +723,16 @@
align-items: baseline;
gap: 0.2rem;
font-size: 0.44rem;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.01em;
white-space: nowrap;
}
.miniRowHead strong {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
font-size: 0.62rem;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
font-weight: 700;
letter-spacing: 0;
text-transform: none;
@@ -741,7 +741,7 @@
.miniTrack {
height: 5px;
border-radius: 2px;
background: rgba(45, 125, 125, 0.08);
background: rgba(var(--status-above-rgb), 0.08);
position: relative;
overflow: visible;
}
@@ -749,21 +749,21 @@
.miniBarExp {
height: 100%;
border-radius: 2px;
background: var(--accent-teal-light, #3a9e9e);
background: var(--brand);
}
.miniBarExc {
height: 100%;
border-radius: 2px;
background: var(--accent-teal, #2d7d7d);
background: var(--brand);
}
.miniNatPill {
position: absolute;
top: -9px;
transform: translateX(-50%);
background: var(--accent-coral, #e07256);
color: #fff;
background: var(--brand);
color: var(--text-inverse);
font-size: 0.4rem;
font-weight: 700;
padding: 0.05rem 0.2rem;
@@ -791,21 +791,21 @@
display: flex;
justify-content: space-between;
font-size: 0.5rem;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.att8Track {
height: 7px;
background: rgba(45, 125, 125, 0.08);
background: rgba(var(--status-above-rgb), 0.08);
border-radius: 3px;
position: relative;
}
.att8Fill {
height: 100%;
background: var(--accent-teal, #2d7d7d);
background: var(--brand);
border-radius: 3px;
}
@@ -814,25 +814,28 @@
top: -2px;
bottom: -2px;
width: 1.5px;
background: rgba(224, 114, 86, 0.6);
background: rgba(var(--brand-rgb), 0.6);
z-index: 2;
}
.att8Score {
font-variant-numeric: tabular-nums;
text-align: right;
}
.att8Value {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-variant-numeric: tabular-nums;
font-family: var(--font-display);
font-size: 1.5rem;
font-weight: 700;
color: var(--accent-teal, #2d7d7d);
color: var(--status-above);
line-height: 1;
}
.att8Delta {
font-variant-numeric: tabular-nums;
font-size: 0.55rem;
color: var(--accent-teal, #2d7d7d);
color: var(--status-above);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.04em;
@@ -853,31 +856,31 @@
align-items: center;
gap: 0.5rem;
padding-bottom: 0.4rem;
border-bottom: 1.5px solid var(--border-color, #e5dfd5);
border-bottom: 1.5px solid var(--border);
}
.ofstedBullet {
display: block;
width: 3px;
height: 1em;
background: var(--accent-coral, #e07256);
background: var(--brand);
border-radius: 2px;
flex-shrink: 0;
}
.ofstedTitle {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
font-size: 0.85rem;
font-weight: 600;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
}
.ofstedFramework {
align-self: flex-start;
padding: 0.15rem 0.5rem;
border-radius: 4px;
background: rgba(90, 58, 110, 0.12);
color: #5a3a6e;
background: rgba(var(--phase-secondary-rgb), 0.12);
color: var(--phase-secondary-text);
font-size: 0.5rem;
font-weight: 700;
letter-spacing: 0.05em;
@@ -899,7 +902,7 @@
.rcArea {
font-size: 0.62rem;
color: var(--text-secondary, #4a453d);
color: var(--text-secondary);
}
.rcChip {
@@ -913,13 +916,13 @@
}
.rcChipGood {
background: rgba(45, 125, 125, 0.12);
color: var(--accent-teal, #2d7d7d);
background: rgba(var(--status-above-rgb), 0.12);
color: var(--status-above);
}
.rcChipNeutral {
background: var(--accent-gold-bg, rgba(180, 150, 40, 0.12));
color: var(--accent-gold-text, #7a6800);
background: var(--status-below-bg);
color: var(--status-below);
}
/* Safeguarding is a separate binary met/not-met judgement, not a graded area,
@@ -931,30 +934,30 @@
gap: 0.5rem;
margin-top: 0.05rem;
padding-top: 0.35rem;
border-top: 1px dashed var(--border-color, #e5dfd5);
border-top: 1px dashed var(--border);
}
.rcSep {
color: var(--text-muted, #8a847a);
color: var(--text-muted);
font-style: italic;
}
.rcChipMet {
background: transparent;
color: var(--accent-teal, #2d7d7d);
border: 1px solid rgba(45, 125, 125, 0.4);
color: var(--status-above);
border: 1px solid rgba(var(--status-above-rgb), 0.4);
}
.ofstedMeta {
font-size: 0.6rem;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
}
/* Compare preview */
.comparePreview {
width: 100%;
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 8px;
overflow: hidden;
font-size: 0.6rem;
@@ -963,23 +966,23 @@
.compareHead {
display: grid;
grid-template-columns: 1fr repeat(2, 1fr);
background: rgba(45, 125, 125, 0.1);
background: rgba(var(--status-above-rgb), 0.1);
padding: 0.35rem 0.5rem;
gap: 0.35rem;
}
.compareHeadCell {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
font-size: 0.62rem;
font-weight: 700;
color: var(--accent-teal, #2d7d7d);
color: var(--status-above);
line-height: 1.2;
}
.compareHeadLabel {
font-family: inherit;
font-size: 0.48rem;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
font-weight: 500;
letter-spacing: 0.08em;
text-transform: uppercase;
@@ -990,37 +993,37 @@
grid-template-columns: 1fr repeat(2, 1fr);
padding: 0.3rem 0.5rem;
gap: 0.35rem;
border-top: 1px solid var(--border-color, #e5dfd5);
border-top: 1px solid var(--border);
align-items: baseline;
}
.compareRowLabel {
font-size: 0.55rem;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.compareRowVal {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
font-size: 0.72rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
}
.compareRowValHi {
color: var(--accent-teal, #2d7d7d);
color: var(--status-above);
}
.compareFoot {
font-size: 0.52rem;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
padding: 0.35rem 0.5rem;
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
text-transform: uppercase;
letter-spacing: 0.06em;
text-align: center;
border-top: 1px solid var(--border-color, #e5dfd5);
border-top: 1px solid var(--border);
}
@media (max-width: 768px) {
@@ -1065,8 +1068,8 @@
grid-template-columns: 1.4fr 1fr;
gap: 2rem;
padding: 1.75rem;
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 14px;
}
@@ -1078,30 +1081,34 @@
.editorialKicker {
font-size: 0.68rem;
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
}
.editorialHeading {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
font-size: 1.35rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
margin: 0;
line-height: 1.25;
}
/* Running prose is the one place the serif appears. Slightly larger than the
UI around it because Literata's x-height sits lower than the grotesque's. */
.editorialText p {
font-size: 0.92rem;
color: var(--text-secondary, #5c564d);
line-height: 1.6;
font-family: var(--font-prose);
font-size: 0.97rem;
color: var(--text-secondary);
line-height: 1.65;
margin: 0;
max-width: 62ch;
}
.factbox {
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
border-radius: 10px;
padding: 1.25rem;
display: flex;
@@ -1110,10 +1117,10 @@
}
.factboxHeading {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
font-size: 1rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
margin: 0 0 0.85rem;
}
@@ -1122,7 +1129,7 @@
justify-content: space-between;
align-items: baseline;
padding: 0.5rem 0;
border-bottom: 1px solid var(--border-color, #e5dfd5);
border-bottom: 1px solid var(--border);
font-size: 0.85rem;
gap: 0.5rem;
}
@@ -1132,13 +1139,13 @@
}
.factKey {
color: var(--text-muted, #6d685f);
color: var(--text-muted);
}
.factVal {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
font-weight: 700;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
text-align: right;
}
@@ -1168,7 +1175,7 @@
.sortSelect {
padding: 0.375rem 0.75rem;
border: 1px solid var(--border-color, #e0ddd8);
border: 1px solid var(--border);
border-radius: var(--radius-md);
background: var(--bg-card);
color: var(--text-secondary);
@@ -1189,7 +1196,7 @@
gap: 0.375rem;
padding: 0.25rem 0.625rem;
background: var(--bg-secondary);
border: 1px solid var(--border-color, #e0ddd8);
border: 1px solid var(--border);
border-radius: 999px;
font-size: 0.8rem;
color: var(--text-secondary);
@@ -1216,8 +1223,9 @@
}
.loadMoreCount {
font-variant-numeric: tabular-nums;
font-size: 0.875rem;
color: var(--text-muted, #8a847a);
color: var(--text-muted);
margin: 0;
}
@@ -1231,7 +1239,7 @@
.admissionsStrip {
padding: 1.5rem 0 2rem;
border-top: 1px solid var(--border-color, #e5dfd5);
border-top: 1px solid var(--border);
}
.stripHeader {
@@ -1248,12 +1256,12 @@
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
}
.stripCta {
font-size: 0.82rem;
color: var(--accent-teal, #2d7d7d);
color: var(--brand);
font-weight: 600;
text-decoration: none;
}
@@ -1269,11 +1277,11 @@
}
.countdownChip {
background: var(--bg-card, #fff);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 12px;
padding: 1rem 1.1rem 0.9rem;
box-shadow: 0 2px 8px rgba(26, 22, 18, 0.06);
box-shadow: 0 2px 8px rgba(var(--shadow-rgb), 0.06);
display: flex;
flex-direction: column;
gap: 0.2rem;
@@ -1292,16 +1300,16 @@
}
.countdownChipDeadline::before {
background: var(--accent-coral, #e07256);
background: var(--brand);
}
.countdownChipOffer::before {
background: var(--accent-teal, #2d7d7d);
background: var(--status-above);
}
.countdownChipUrgent {
border-color: rgba(224, 114, 86, 0.4);
background: rgba(224, 114, 86, 0.04);
border-color: rgba(var(--brand-rgb), 0.4);
background: rgba(var(--brand-rgb), 0.04);
}
.chipTrack {
@@ -1316,11 +1324,11 @@
}
.chipTrackDeadline {
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
}
.chipTrackOffer {
color: var(--accent-teal, #2d7d7d);
color: var(--status-above);
}
.chipTrackDot {
@@ -1332,7 +1340,8 @@
}
.chipDays {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-variant-numeric: tabular-nums;
font-family: var(--font-display);
font-size: 2.6rem;
font-weight: 700;
line-height: 1;
@@ -1341,18 +1350,18 @@
.countdownChipDeadline .chipDays,
.countdownChipUrgent .chipDays {
color: var(--accent-coral-dark, #c45a3f);
color: var(--brand-strong);
}
.countdownChipOffer .chipDays {
color: var(--accent-teal, #2d7d7d);
color: var(--status-above);
}
.chipDaysUnit {
font-family: 'DM Sans', sans-serif;
font-family: var(--font-ui);
font-size: 0.78rem;
font-weight: 500;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
margin-left: 0.2rem;
vertical-align: bottom;
line-height: 2;
@@ -1361,14 +1370,14 @@
.chipMilestone {
font-size: 0.85rem;
font-weight: 600;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
line-height: 1.25;
margin-top: 0.1rem;
}
.chipDate {
font-size: 0.75rem;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
margin-top: 0.05rem;
}
+10 -10
View File
@@ -573,10 +573,10 @@ function CompactSchoolItem({ school, onAddToCompare, isInCompare, nationalAvgRwm
rwmDelta == null
? {}
: rwmDelta >= 2
? { fontSize: '0.7rem', color: 'var(--accent-teal, #2d7d7d)', fontWeight: 600 }
? { fontSize: '0.7rem', color: 'var(--status-above)', fontWeight: 600 }
: rwmDelta <= -2
? { fontSize: '0.7rem', color: 'var(--accent-coral, #e07256)', fontWeight: 600 }
: { fontSize: '0.7rem', color: 'var(--text-muted, #8a847a)' };
? { fontSize: '0.7rem', color: 'var(--brand)', fontWeight: 600 }
: { fontSize: '0.7rem', color: 'var(--text-muted)' };
return (
<div className={styles.compactItem}>
@@ -601,13 +601,13 @@ function CompactSchoolItem({ school, onAddToCompare, isInCompare, nationalAvgRwm
fontWeight: 600,
borderRadius: '3px',
whiteSpace: 'nowrap',
...(ofstedBadge.cssClass === 'ofsted1' ? { background: 'var(--accent-teal-bg)', color: 'var(--accent-teal, #2d7d7d)' } :
ofstedBadge.cssClass === 'ofsted2' ? { background: 'rgba(60,140,60,0.12)', color: '#2f7a2f' } :
ofstedBadge.cssClass === 'ofsted3' ? { background: 'var(--accent-gold-bg)', color: 'var(--accent-gold-text, #7a6800)' } :
ofstedBadge.cssClass === 'ofsted4' ? { background: 'var(--accent-coral-bg)', color: 'var(--accent-coral, #e07256)' } :
ofstedBadge.cssClass === 'ofstedRc' ? { background: '#5a3a6e', color: '#fff' } :
ofstedBadge.cssClass === 'ofstedPending' ? { background: '#e0e0e0', color: '#666' } :
{ background: '#e0e0e0', color: '#666' }),
...(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 === '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)' }),
}}
>
{ofstedBadge.label}
+10 -10
View File
@@ -11,7 +11,7 @@
/* font-size:0 hides the button's own "?" text node; the ::before glyph
below carries the visible circled "?" at its own explicit size. */
font-size: 0;
color: var(--text-muted, #8a7a72);
color: var(--text-muted);
cursor: help;
line-height: 1;
user-select: none;
@@ -34,17 +34,17 @@
.icon:hover,
.icon[aria-expanded='true'],
.icon:focus-visible {
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
}
.tooltip {
z-index: 9999;
width: max-content;
max-width: min(260px, calc(100vw - 24px));
background: var(--bg-primary, #faf7f2);
border: 1px solid var(--border-color, #e8ddd4);
background: var(--bg-primary);
border: 1px solid var(--border);
border-radius: 10px;
box-shadow: 0 4px 16px rgba(44, 36, 32, 0.15);
box-shadow: 0 4px 16px rgba(var(--shadow-rgb), 0.15);
padding: 0.6rem 0.75rem;
display: flex;
flex-direction: column;
@@ -52,26 +52,26 @@
}
.arrow {
fill: var(--bg-primary, #faf7f2);
stroke: var(--border-color, #e8ddd4);
fill: var(--bg-primary);
stroke: var(--border);
stroke-width: 1px;
}
.label {
font-weight: 600;
font-size: 0.75rem;
color: var(--text-primary, #2c2420);
color: var(--text-primary);
}
.plain {
font-size: 0.75rem;
color: var(--text-secondary, #5a4a44);
color: var(--text-secondary);
line-height: 1.4;
}
.detail {
font-size: 0.7rem;
color: var(--text-muted, #8a7a72);
color: var(--text-muted);
line-height: 1.4;
margin-top: 0.1rem;
}
@@ -22,10 +22,10 @@ interface LeafletHeroMapInnerProps {
// reliably inside Leaflet's divIcon HTML string (no CSS-module dependency).
const PIN_HTML = `
<div style="position:relative;width:26px;height:26px">
<span style="position:absolute;left:50%;top:74%;width:32px;height:32px;transform:translate(-50%,-50%);border-radius:50%;background:rgba(224,114,86,.25)"></span>
<span style="position:absolute;left:50%;top:74%;width:32px;height:32px;transform:translate(-50%,-50%);border-radius:50%;background:var(--brand-bg)"></span>
<svg width="26" height="34" viewBox="0 0 26 34" style="filter:drop-shadow(0 3px 4px rgba(0,0,0,.35))">
<path d="M13 0C5.8 0 0 5.8 0 13c0 9.2 13 21 13 21s13-11.8 13-21C26 5.8 20.2 0 13 0Z" fill="#e07256"/>
<circle cx="13" cy="13" r="5" fill="#fff"/>
<path d="M13 0C5.8 0 0 5.8 0 13c0 9.2 13 21 13 21s13-11.8 13-21C26 5.8 20.2 0 13 0Z" fill="var(--brand)"/>
<circle cx="13" cy="13" r="5" fill="var(--text-inverse)"/>
</svg>
</div>`;
+16 -16
View File
@@ -48,21 +48,21 @@ function buildPopupBadge(school: School): PopupBadge {
// ofsted_framework is the raw event grouping, never "ReportCard").
if (school.ofsted_rc_date) {
const rcYear = new Date(school.ofsted_rc_date).getFullYear();
return { label: `Report Card · ${rcYear}`, style: 'background:#5a3a6e;color:#fff' };
return { label: `Report Card · ${rcYear}`, style: 'background:var(--phase-secondary-text);color:var(--text-inverse)' };
}
const year = school.ofsted_date ? new Date(school.ofsted_date).getFullYear() : null;
const yearStr = year ? ` · ${year}` : '';
if (school.ofsted_grade) {
const labels: Record<number, string> = { 1: 'Outstanding', 2: 'Good', 3: 'Req. Improvement', 4: 'Inadequate' };
const colours: Record<number, string> = {
1: 'background:#d4f0ea;color:#2d7d7d',
2: 'background:rgba(60,140,60,0.12);color:#2f7a2f',
3: 'background:#fef3cd;color:#7a6800',
4: 'background:#fde8e0;color:#e07256',
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)',
};
return { label: `${labels[school.ofsted_grade]}${yearStr}`, style: colours[school.ofsted_grade] };
}
return { label: 'Not yet inspected', style: 'background:#e0e0e0;color:#666' };
return { label: 'Not yet inspected', style: 'background:var(--bg-secondary);color:var(--text-muted)' };
}
export default function LeafletMapInner({ schools, center, zoom, referencePoint, onMarkerClick, nationalAvgRwm, laAverages }: LeafletMapInnerProps) {
@@ -99,7 +99,7 @@ export default function LeafletMapInner({ schools, center, zoom, referencePoint,
const refIcon = L.divIcon({
html: `<div style="
width: 20px; height: 20px;
background: #e07256;
background: var(--brand);
border: 3px solid white;
border-radius: 50%;
box-shadow: 0 2px 8px rgba(0,0,0,0.35);
@@ -145,13 +145,13 @@ export default function LeafletMapInner({ schools, center, zoom, referencePoint,
const sign = diff >= 0 ? '+' : '';
// Att8 scores range 090 in 0.1 increments; ±0.5 is meaningful here
// vs primary RWM % where ±2 pts is the threshold
const colour = diff >= 0.5 ? '#2d7d7d' : diff <= -0.5 ? '#e07256' : '#8a847a';
const colour = diff >= 0.5 ? 'var(--status-above)' : diff <= -0.5 ? 'var(--brand)' : 'var(--text-muted)';
const laName = escapeHtml(school.local_authority ?? 'LA');
deltaLine = `<div style="font-size:11px;font-weight:600;color:${colour}">${sign}${diff} vs ${laName} avg</div>`;
}
metricHtml = `<div style="margin-bottom:4px">
<span style="font-size:20px;font-weight:700;color:#1a1612;font-family:Georgia,serif">${score.toFixed(1)}</span>
<span style="font-size:11px;color:#8a847a;margin-left:4px">Attainment 8</span>
<span style="font-size:20px;font-weight:700;color:var(--text-primary);font-family:Georgia,serif">${score.toFixed(1)}</span>
<span style="font-size:11px;color:var(--text-muted);margin-left:4px">Attainment 8</span>
${deltaLine}
</div>`;
} else if (school.rwm_expected_pct != null) {
@@ -159,7 +159,7 @@ export default function LeafletMapInner({ schools, center, zoom, referencePoint,
let deltaLine = '';
if (nationalAvgRwm != null) {
const diff = Math.round(rwm - nationalAvgRwm);
const colour = diff >= 2 ? '#2d7d7d' : diff <= -2 ? '#e07256' : '#8a847a';
const colour = diff >= 2 ? 'var(--status-above)' : diff <= -2 ? 'var(--brand)' : 'var(--text-muted)';
const text =
diff >= 2 ? `+${diff} pts vs national` :
diff <= -2 ? `${diff} pts vs national` :
@@ -167,8 +167,8 @@ export default function LeafletMapInner({ schools, center, zoom, referencePoint,
deltaLine = `<div style="font-size:11px;font-weight:600;color:${colour}">${text}</div>`;
}
metricHtml = `<div style="margin-bottom:4px">
<span style="font-size:20px;font-weight:700;color:#1a1612;font-family:Georgia,serif">${rwm}%</span>
<span style="font-size:11px;color:#8a847a;margin-left:4px">Reading, Writing &amp; Maths</span>
<span style="font-size:20px;font-weight:700;color:var(--text-primary);font-family:Georgia,serif">${rwm}%</span>
<span style="font-size:11px;color:var(--text-muted);margin-left:4px">Reading, Writing &amp; Maths</span>
${deltaLine}
</div>`;
}
@@ -177,14 +177,14 @@ export default function LeafletMapInner({ schools, center, zoom, referencePoint,
const popupContent = `<div style="font-family:system-ui,sans-serif;min-width:240px;max-width:280px;padding:0">
<div style="display:flex;justify-content:space-between;align-items:flex-start;gap:8px;margin-bottom:6px">
<strong style="font-size:13px;color:#1a1612;line-height:1.3">${escapeHtml(school.school_name)}</strong>
<strong style="font-size:13px;color:var(--text-primary);line-height:1.3">${escapeHtml(school.school_name)}</strong>
<span style="font-size:10px;font-weight:700;padding:2px 6px;border-radius:3px;white-space:nowrap;flex-shrink:0;${badge.style}">${badge.label}</span>
</div>
<div style="font-size:11px;color:#8a847a;margin-bottom:8px">
<div style="font-size:11px;color:var(--text-muted);margin-bottom:8px">
${phaseLabel}${school.local_authority ? ` · ${escapeHtml(school.local_authority)}` : ''}${distanceStr}
</div>
${metricHtml}
<a href="${slug}" style="display:block;text-align:center;padding:6px;background:#2d7d7d;color:white;border-radius:5px;text-decoration:none;font-size:12px;font-weight:600;margin-top:8px">View Details →</a>
<a href="${slug}" style="display:block;text-align:center;padding:6px;background:var(--status-above);color:white;border-radius:5px;text-decoration:none;font-size:12px;font-weight:600;margin-top:8px">View Details →</a>
</div>`;
marker.bindPopup(popupContent);
@@ -5,19 +5,19 @@
}
.skeletonCard {
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 12px;
padding: 1.5rem;
box-shadow: var(--shadow-soft, 0 2px 8px rgba(26, 22, 18, 0.06));
box-shadow: var(--shadow-soft, 0 2px 8px rgba(var(--shadow-rgb), 0.06));
}
.skeleton {
background: linear-gradient(
90deg,
var(--bg-secondary, #f3ede4) 25%,
rgba(224, 114, 86, 0.08) 50%,
var(--bg-secondary, #f3ede4) 75%
var(--bg-secondary) 25%,
rgba(var(--brand-rgb), 0.08) 50%,
var(--bg-secondary) 75%
);
background-size: 200% 100%;
animation: shimmer 1.5s ease-in-out infinite;
@@ -56,7 +56,7 @@
gap: 1rem;
margin-bottom: 1.5rem;
padding: 1rem;
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
border-radius: 8px;
}
@@ -82,11 +82,11 @@
}
.skeletonListItem {
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 12px;
padding: 1.5rem;
box-shadow: var(--shadow-soft, 0 2px 8px rgba(26, 22, 18, 0.06));
box-shadow: var(--shadow-soft, 0 2px 8px rgba(var(--shadow-rgb), 0.06));
}
.listTitle {
+65
View File
@@ -0,0 +1,65 @@
/**
* The SchoolCompare mark.
*
* Five bars: a cohort, with one school picked out. It is the same object as
* the distribution strip inside a school row, at a different size — the logo
* teaches the chart and the chart reinforces the logo.
*
* Built from opacity steps over `currentColor` rather than fixed greys, so it
* inverts cleanly on any ground without a second artwork. The highlighted bar
* is the only element that takes the brand hue.
*
* This is the single source for the mark. The favicon and the generated icons
* derive from the same geometry (see BARS) — previously the header and the
* favicon had drifted into two different logos.
*/
/** x, y, width, height, and whether this bar is the highlighted school. */
export const BARS: ReadonlyArray<[number, number, number, number, boolean]> = [
[2, 26, 6, 12, false],
[10, 16, 6, 22, false],
[18, 8, 6, 30, false],
[26, 14, 6, 24, true],
[34, 28, 4, 10, false],
];
const COHORT_OPACITY = [0.22, 0.38, 0.55, 1, 0.22];
interface LogoMarkProps {
className?: string;
/** Rendered size in px. Defaults to inheriting via CSS. */
size?: number;
/** Colour of the highlighted bar. Defaults to the brand token. */
accent?: string;
title?: string;
}
export function LogoMark({ className, size, accent = 'var(--brand)', title }: LogoMarkProps) {
return (
<svg
className={className}
width={size}
height={size}
viewBox="0 0 40 40"
fill="none"
xmlns="http://www.w3.org/2000/svg"
role={title ? 'img' : undefined}
aria-hidden={title ? undefined : true}
aria-label={title}
>
{title ? <title>{title}</title> : null}
{BARS.map(([x, y, w, h, isSchool], i) => (
<rect
key={x}
x={x}
y={y}
width={w}
height={h}
rx={1}
fill={isSchool ? accent : 'currentColor'}
opacity={isSchool ? 1 : COHORT_OPACITY[i]}
/>
))}
</svg>
);
}
+13 -13
View File
@@ -1,7 +1,7 @@
.overlay {
position: fixed;
inset: 0;
background: rgba(26, 22, 18, 0.6);
background: rgba(var(--shadow-rgb), 0.6);
display: flex;
align-items: center;
justify-content: center;
@@ -20,15 +20,15 @@
}
.modal {
background: var(--bg-card, white);
background: var(--bg-card);
border-radius: 16px;
box-shadow: 0 20px 40px rgba(26, 22, 18, 0.2);
box-shadow: 0 20px 40px rgba(var(--shadow-rgb), 0.2);
max-height: 90vh;
overflow: hidden;
display: flex;
flex-direction: column;
animation: slideIn 0.3s ease;
border: 1px solid var(--border-color, #e5dfd5);
border: 1px solid var(--border);
}
@keyframes slideIn {
@@ -62,22 +62,22 @@
justify-content: space-between;
align-items: center;
padding: 1.5rem;
border-bottom: 1px solid var(--border-color, #e5dfd5);
border-bottom: 1px solid var(--border);
}
.title {
margin: 0;
font-size: 1.25rem;
font-weight: 600;
color: var(--text-primary, #1a1612);
font-family: var(--font-playfair), 'Playfair Display', serif;
color: var(--text-primary);
font-family: var(--font-display);
}
.closeButton {
padding: 0.5rem;
background: transparent;
border: none;
color: var(--text-muted, #8a847a);
color: var(--text-muted);
cursor: pointer;
border-radius: 8px;
transition: all 0.2s ease;
@@ -87,8 +87,8 @@
}
.closeButton:hover {
background: var(--bg-secondary, #f3ede4);
color: var(--accent-coral, #e07256);
background: var(--bg-secondary);
color: var(--brand);
}
.content {
@@ -102,16 +102,16 @@
}
.content::-webkit-scrollbar-track {
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
}
.content::-webkit-scrollbar-thumb {
background: var(--border-color, #e5dfd5);
background: var(--border);
border-radius: 4px;
}
.content::-webkit-scrollbar-thumb:hover {
background: var(--text-muted, #8a847a);
background: var(--text-muted);
}
@media (max-width: 640px) {
+38 -28
View File
@@ -2,9 +2,9 @@
position: sticky;
top: 0;
z-index: 1000;
background: var(--bg-card, white);
border-bottom: 1px solid var(--border-color, #e5dfd5);
box-shadow: 0 2px 8px rgba(26, 22, 18, 0.06);
background: var(--bg-card);
border-bottom: 1px solid var(--border);
box-shadow: 0 2px 8px rgba(var(--shadow-rgb), 0.06);
}
.container {
@@ -27,7 +27,7 @@
margin: -0.375rem -0.5rem;
padding: 0.375rem 0.5rem;
text-decoration: none;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
font-size: 1.25rem;
font-weight: 700;
transition: color 0.2s ease;
@@ -35,14 +35,16 @@
}
.logo:hover {
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
}
/* currentColor paints the four cohort bars; the mark supplies the brand hue
for the highlighted one itself. So this is ink, not brand. */
.logoIcon {
display: inline-flex;
width: 36px;
height: 36px;
color: var(--accent-coral, #e07256);
width: 32px;
height: 32px;
color: var(--text-primary);
}
.logoIcon svg {
@@ -51,9 +53,17 @@
}
.logoText {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
font-weight: 700;
letter-spacing: -0.01em;
letter-spacing: -0.022em;
}
.logoTextAccent {
color: var(--brand);
}
.logo:hover .logoTextAccent {
color: var(--brand-strong);
}
.nav {
@@ -69,7 +79,7 @@
padding: 0.625rem 1rem;
font-size: 0.9375rem;
font-weight: 500;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
text-decoration: none;
border-radius: 6px;
transition: all 0.2s ease;
@@ -83,7 +93,7 @@
left: 1rem;
right: 1rem;
height: 2px;
background: var(--accent-coral, #e07256);
background: var(--brand);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.25s ease;
@@ -91,8 +101,8 @@
}
.navLink:hover {
color: var(--text-primary, #1a1612);
background: var(--bg-secondary, #f3ede4);
color: var(--text-primary);
background: var(--bg-secondary);
}
.navLink:hover::after {
@@ -100,8 +110,8 @@
}
.navLink.active {
color: var(--accent-coral-dark, #b04a2e);
background: var(--accent-coral-bg);
color: var(--brand-strong);
background: var(--brand-bg);
}
.navLink.active::after {
@@ -117,11 +127,11 @@
padding: 0 0.375rem;
font-size: 0.75rem;
font-weight: 600;
color: white;
background: var(--accent-coral, #e07256);
color: var(--brand-on);
background: var(--brand);
border-radius: 9999px;
animation: badgePop 0.3s ease-out;
box-shadow: 0 2px 6px rgba(224, 114, 86, 0.4);
box-shadow: 0 2px 6px rgba(var(--brand-rgb), 0.4);
}
@keyframes badgePop {
@@ -153,7 +163,7 @@
flex: 1;
min-height: 56px;
padding: 0.375rem 0.25rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
text-decoration: none;
font-size: 0.6875rem;
font-weight: 500;
@@ -163,11 +173,11 @@
}
.tab:active {
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
}
.tabActive {
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
}
.tabIconWrap {
@@ -200,9 +210,9 @@
padding: 0 5px;
font-size: 0.6875rem;
font-weight: 700;
color: white;
background: var(--accent-coral, #e07256);
border: 2px solid var(--bg-card, white);
color: var(--brand-on);
background: var(--brand);
border: 2px solid var(--bg-card);
border-radius: 9999px;
animation: badgePop 0.3s ease-out;
}
@@ -230,9 +240,9 @@
left: 0;
right: 0;
z-index: 1000;
background: var(--bg-card, white);
border-top: 1px solid var(--border-color, #e5dfd5);
box-shadow: 0 -2px 12px rgba(26, 22, 18, 0.06);
background: var(--bg-card);
border-top: 1px solid var(--border);
box-shadow: 0 -2px 12px rgba(var(--shadow-rgb), 0.06);
/* Respect iPhone home-indicator (bottom) and notch (left/right in
landscape) insets so the tab content never sits under system UI. */
padding-bottom: env(safe-area-inset-bottom, 0);
+5 -6
View File
@@ -9,6 +9,7 @@ import { useEffect } from 'react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { useComparison } from '@/hooks/useComparison';
import { LogoMark } from './Logo';
import styles from './Navigation.module.css';
type IconProps = { className?: string };
@@ -91,13 +92,11 @@ export function Navigation() {
<div className={styles.container}>
<Link href="/" className={styles.logo} aria-label="SchoolCompare home">
<span className={styles.logoIcon}>
<svg viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<circle cx="20" cy="20" r="18" stroke="currentColor" strokeWidth="2" />
<path d="M20 6L20 34M8 14L32 14M6 20L34 20M8 26L32 26" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
<circle cx="20" cy="20" r="3" fill="currentColor" />
</svg>
<LogoMark />
</span>
<span className={styles.logoText}>
School<span className={styles.logoTextAccent}>Compare</span>
</span>
<span className={styles.logoText}>SchoolCompare</span>
</Link>
<nav className={styles.nav} aria-label="Main navigation">
+19 -19
View File
@@ -8,7 +8,7 @@
.info {
font-size: 0.875rem;
color: var(--text-muted, #8a847a);
color: var(--text-muted);
}
.controls {
@@ -21,18 +21,18 @@
padding: 0.5rem 1rem;
font-size: 0.875rem;
font-weight: 500;
background: var(--bg-card, white);
color: var(--text-secondary, #5c564d);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
color: var(--text-secondary);
border: 1px solid var(--border);
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
}
.navButton:hover:not(:disabled) {
background: var(--bg-secondary, #f3ede4);
border-color: var(--accent-coral, #e07256);
color: var(--text-primary, #1a1612);
background: var(--bg-secondary);
border-color: var(--brand);
color: var(--text-primary);
}
.navButton:disabled {
@@ -51,32 +51,32 @@
padding: 0.5rem 0.75rem;
font-size: 0.875rem;
font-weight: 500;
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 8px;
cursor: pointer;
transition: all 0.2s ease;
}
.pageButton {
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
}
.pageButton:hover {
background: var(--bg-secondary, #f3ede4);
border-color: var(--accent-coral, #e07256);
color: var(--text-primary, #1a1612);
background: var(--bg-secondary);
border-color: var(--brand);
color: var(--text-primary);
}
.pageButtonActive {
background: var(--accent-coral, #e07256);
color: white;
border-color: var(--accent-coral, #e07256);
background: var(--brand);
color: var(--brand-on);
border-color: var(--brand);
}
.pageButtonActive:hover {
background: var(--accent-coral-dark, #c45a3f);
border-color: var(--accent-coral-dark, #c45a3f);
background: var(--brand-strong);
border-color: var(--brand-strong);
}
.ellipsis {
@@ -84,7 +84,7 @@
align-items: center;
padding: 0.5rem 0.75rem;
font-size: 0.875rem;
color: var(--text-muted, #8a847a);
color: var(--text-muted);
}
@media (max-width: 640px) {
@@ -12,10 +12,10 @@
.trendSummary {
font-size: 0.875rem;
font-weight: 600;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
padding: 0.5rem 0.875rem;
background: var(--bg-secondary, #f3ede4);
border-left: 3px solid var(--accent-teal, #2d7d7d);
background: var(--bg-secondary);
border-left: 3px solid var(--brand);
border-radius: 0 4px 4px 0;
align-self: flex-start;
}
@@ -34,7 +34,7 @@
.covidNote,
.chartHint {
font-size: 0.75rem;
color: var(--text-muted, #8a847a);
color: var(--text-muted);
margin: 0;
font-style: italic;
}
@@ -52,7 +52,7 @@
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
margin-bottom: 0.4rem;
}
@@ -63,9 +63,9 @@
}
.chip {
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card, #fff);
color: var(--text-secondary, #5c564d);
border: 1px solid var(--border);
background: var(--bg-card);
color: var(--text-secondary);
padding: 0.4rem 0.75rem;
border-radius: 999px;
font-size: 0.8125rem;
@@ -78,7 +78,7 @@
}
.chip:active {
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
}
.chip:disabled {
@@ -87,21 +87,21 @@
}
.chipActive {
background: var(--accent-coral-dark, #b04a2e);
color: white;
border-color: var(--accent-coral, #e07256);
background: var(--brand-strong);
color: var(--brand-on);
border-color: var(--brand);
font-weight: 600;
}
.chipActive:active {
background: var(--accent-coral-dark, #c45a3f);
background: var(--brand-strong);
}
.miniLegend {
display: flex;
gap: 0.875rem;
font-size: 0.75rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
margin-top: -0.25rem;
}
+37 -24
View File
@@ -11,6 +11,7 @@
'use client';
import { useMemo, useState } from 'react';
import { useThemeTokens, alpha } from '@/lib/theme';
import { Line } from 'react-chartjs-2';
import { ChartOptions, ChartDataset } from 'chart.js';
import '@/lib/chartSetup';
@@ -124,9 +125,17 @@ export function PerformanceChart({
const gapYears = axisYears.filter(y => !byYear.has(y));
const hasGap = gapYears.length > 0;
// Chart.js paints to a canvas, so it needs resolved colours rather than
// var(). Reading them through the token bridge keeps the series on the
// brand palette and lets them follow the theme.
const [c1, c2, c3, c4, c5, c6, cGrid, cRef, cInverse, cInverseText] = useThemeTokens(
'--chart-1', '--chart-2', '--chart-3', '--chart-4', '--chart-5', '--chart-6',
'--chart-grid', '--chart-reference', '--surface-inverse', '--text-inverse'
);
// ── Datasets (full set; mobile filters them via the active chip) ─────
const refLineStyle = {
borderColor: 'rgba(90,80,70,0.35)',
borderColor: cRef,
backgroundColor: 'transparent',
borderWidth: 1.5,
borderDash: [6, 4] as number[],
@@ -140,8 +149,8 @@ export function PerformanceChart({
{
label: 'Attainment 8',
data: col('attainment_8_score'),
borderColor: '#2d7d7d',
backgroundColor: 'rgba(45,125,125,0.08)',
borderColor: c1,
backgroundColor: alpha('--chart-1', 0.08),
borderWidth: 2.5,
tension: 0.3,
pointRadius: 4,
@@ -151,8 +160,8 @@ export function PerformanceChart({
{
label: 'English & Maths Grade 4+',
data: col('english_maths_standard_pass_pct'),
borderColor: '#c9a227',
backgroundColor: 'rgba(201,162,39,0.08)',
borderColor: c2,
backgroundColor: alpha('--chart-2', 0.08),
borderWidth: 1.5,
tension: 0.3,
pointRadius: 3,
@@ -161,8 +170,8 @@ export function PerformanceChart({
{
label: 'Progress 8',
data: col('progress_8_score'),
borderColor: 'rgb(139,92,246)',
backgroundColor: 'rgba(139,92,246,0.08)',
borderColor: c3,
backgroundColor: alpha('--chart-3', 0.08),
borderWidth: 1.5,
tension: 0.3,
pointRadius: 3,
@@ -179,8 +188,8 @@ export function PerformanceChart({
{
label: 'Reading, Writing & Maths expected %',
data: col('rwm_expected_pct'),
borderColor: '#2d7d7d',
backgroundColor: 'rgba(45,125,125,0.08)',
borderColor: c1,
backgroundColor: alpha('--chart-1', 0.08),
borderWidth: 2.5,
tension: 0.3,
pointRadius: 4,
@@ -190,8 +199,8 @@ export function PerformanceChart({
{
label: 'Exceeding expected level',
data: col('rwm_high_pct'),
borderColor: '#c9a227',
backgroundColor: 'rgba(201,162,39,0.08)',
borderColor: c2,
backgroundColor: alpha('--chart-2', 0.08),
borderWidth: 1.5,
tension: 0.3,
pointRadius: 3,
@@ -206,8 +215,8 @@ export function PerformanceChart({
{
label: 'Reading progress',
data: col('reading_progress'),
borderColor: 'rgb(59,130,246)',
backgroundColor: 'rgba(59,130,246,0.08)',
borderColor: c4,
backgroundColor: alpha('--chart-4', 0.08),
borderWidth: 1.5,
tension: 0.3,
pointRadius: 3,
@@ -217,8 +226,8 @@ export function PerformanceChart({
{
label: 'Writing progress',
data: col('writing_progress'),
borderColor: 'rgb(139,92,246)',
backgroundColor: 'rgba(139,92,246,0.08)',
borderColor: c3,
backgroundColor: alpha('--chart-3', 0.08),
borderWidth: 1.5,
tension: 0.3,
pointRadius: 3,
@@ -228,8 +237,8 @@ export function PerformanceChart({
{
label: 'Maths progress',
data: col('maths_progress'),
borderColor: 'rgb(236,72,153)',
backgroundColor: 'rgba(236,72,153,0.08)',
borderColor: c5,
backgroundColor: alpha('--chart-5', 0.08),
borderWidth: 1.5,
tension: 0.3,
pointRadius: 3,
@@ -301,7 +310,9 @@ export function PerformanceChart({
},
title: { display: false },
tooltip: {
backgroundColor: 'rgba(26,22,18,0.92)',
backgroundColor: cInverse,
titleColor: cInverseText,
bodyColor: cInverseText,
padding: 12,
titleFont: { size: 13 },
bodyFont: { size: 12 },
@@ -321,7 +332,7 @@ export function PerformanceChart({
type: 'linear', display: true, position: 'left',
title: { display: true, text: isSecondary ? 'Score / %' : 'Percentage (%)', font: { size: 11 } },
min: 0, max: isSecondary ? undefined : 100,
grid: { color: 'rgba(0,0,0,0.05)' },
grid: { color: cGrid },
ticks: { font: { size: 11 } },
},
y1: {
@@ -346,7 +357,9 @@ export function PerformanceChart({
legend: { display: false },
title: { display: false },
tooltip: {
backgroundColor: 'rgba(26,22,18,0.92)',
backgroundColor: cInverse,
titleColor: cInverseText,
bodyColor: cInverseText,
padding: 10,
titleFont: { size: 12 },
bodyFont: { size: 11 },
@@ -364,7 +377,7 @@ export function PerformanceChart({
y: {
type: 'linear', display: true, position: 'left',
min: mobileYBounds.min, max: mobileYBounds.max,
grid: { color: 'rgba(0,0,0,0.05)' },
grid: { color: cGrid },
ticks: { font: { size: 10 }, maxTicksLimit: 5 },
},
x: {
@@ -429,9 +442,9 @@ export function PerformanceChart({
belong together. */}
{isMobile && activeChip === 'progress' && (
<div className={styles.miniLegend}>
<span><span className={styles.miniDot} style={{ background: 'rgb(59,130,246)' }} />Reading</span>
<span><span className={styles.miniDot} style={{ background: 'rgb(139,92,246)' }} />Writing</span>
<span><span className={styles.miniDot} style={{ background: 'rgb(236,72,153)' }} />Maths</span>
<span><span className={styles.miniDot} style={{ background: c4 }} />Reading</span>
<span><span className={styles.miniDot} style={{ background: c3 }} />Writing</span>
<span><span className={styles.miniDot} style={{ background: c5 }} />Maths</span>
</div>
)}
+55 -54
View File
@@ -11,14 +11,14 @@
.header h1 {
font-size: 2.25rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
margin-bottom: 0.5rem;
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
}
.subtitle {
font-size: 1rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
margin: 0;
line-height: 1.6;
}
@@ -28,7 +28,7 @@
display: flex;
gap: 0;
margin-bottom: 1.5rem;
border: 1px solid var(--border-color, #e5dfd5);
border: 1px solid var(--border);
border-radius: 8px;
overflow: hidden;
width: fit-content;
@@ -38,8 +38,8 @@
padding: 0.625rem 1.5rem;
font-size: 0.9375rem;
font-weight: 500;
background: var(--bg-card, white);
color: var(--text-secondary, #5c564d);
background: var(--bg-card);
color: var(--text-secondary);
border: none;
cursor: pointer;
transition: all 0.15s ease;
@@ -47,34 +47,34 @@
}
.phaseTab:not(:last-child) {
border-right: 1px solid var(--border-color, #e5dfd5);
border-right: 1px solid var(--border);
}
.phaseTab:hover {
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
}
.phaseTabActive {
background: var(--accent-coral-dark, #b04a2e);
color: white;
background: var(--brand-strong);
color: var(--brand-on);
font-weight: 600;
}
.phaseTabActive:hover {
background: var(--accent-coral-darker, #9c3f26);
background: var(--brand-stronger);
}
/* Filters */
.filters {
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 12px;
padding: 1.5rem;
margin-bottom: 2rem;
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
box-shadow: var(--shadow-soft, 0 2px 8px rgba(26, 22, 18, 0.06));
box-shadow: var(--shadow-soft, 0 2px 8px rgba(var(--shadow-rgb), 0.06));
}
.filterGroup {
@@ -88,7 +88,7 @@
.filterLabel {
font-size: 0.9375rem;
font-weight: 600;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
white-space: nowrap;
}
@@ -98,44 +98,44 @@
max-width: 100%;
padding: 0.625rem 1rem;
font-size: 0.9375rem;
border: 1px solid var(--border-color, #e5dfd5);
border: 1px solid var(--border);
border-radius: 8px;
background: var(--bg-card, white);
color: var(--text-primary, #1a1612);
background: var(--bg-card);
color: var(--text-primary);
cursor: pointer;
transition: all 0.2s ease;
}
.filterSelect:hover {
border-color: var(--accent-coral, #e07256);
border-color: var(--brand);
}
.filterSelect:focus {
outline: none;
border-color: var(--accent-coral, #e07256);
box-shadow: 0 0 0 3px var(--accent-coral-bg);
border-color: var(--brand);
box-shadow: 0 0 0 3px var(--brand-bg);
}
.filterSelect optgroup {
font-weight: 700;
color: var(--text-primary, #1a1612);
background: var(--bg-secondary, #f3ede4);
color: var(--text-primary);
background: var(--bg-secondary);
padding: 0.5rem 0;
}
.filterSelect option {
font-weight: 400;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
padding: 0.375rem 1rem;
}
/* Rankings Section */
.rankingsSection {
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 12px;
padding: 2rem;
box-shadow: var(--shadow-soft, 0 2px 8px rgba(26, 22, 18, 0.06));
box-shadow: var(--shadow-soft, 0 2px 8px rgba(var(--shadow-rgb), 0.06));
}
.tableWrapper {
@@ -151,15 +151,15 @@
}
.rankingsTable thead {
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
}
.rankingsTable th {
padding: 1rem;
text-align: left;
font-weight: 600;
color: var(--text-primary, #1a1612);
border-bottom: 2px solid var(--border-color, #e5dfd5);
color: var(--text-primary);
border-bottom: 2px solid var(--border);
white-space: nowrap;
text-transform: uppercase;
font-size: 0.75rem;
@@ -206,8 +206,8 @@
.rankingsTable td {
padding: 1rem;
border-bottom: 1px solid var(--border-color, #e5dfd5);
color: var(--text-secondary, #5c564d);
border-bottom: 1px solid var(--border);
color: var(--text-secondary);
}
.rankingsTable tbody tr:last-child td {
@@ -216,24 +216,24 @@
/* Alternating row backgrounds for visual rhythm */
.rankingsTable tbody tr:nth-child(even) {
background: rgba(243, 237, 228, 0.5);
background: rgba(var(--text-inverse-rgb), 0.5);
}
.rankingsTable tbody tr:hover {
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
}
/* Top 3 Highlighting with Gold */
.rank1 {
background: linear-gradient(90deg, rgba(201, 162, 39, 0.15) 0%, transparent 100%) !important;
background: linear-gradient(90deg, rgba(var(--status-below-rgb), 0.15) 0%, transparent 100%) !important;
}
.rank2 {
background: linear-gradient(90deg, rgba(192, 192, 192, 0.15) 0%, transparent 100%) !important;
background: linear-gradient(90deg, rgba(var(--medal-silver-rgb), 0.15) 0%, transparent 100%) !important;
}
.rank3 {
background: linear-gradient(90deg, rgba(205, 127, 50, 0.15) 0%, transparent 100%) !important;
background: linear-gradient(90deg, rgba(var(--medal-bronze-rgb), 0.15) 0%, transparent 100%) !important;
}
.rankCell {
@@ -241,7 +241,7 @@
align-items: center;
gap: 0.5rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
}
/* Styled rank badges for top 3 */
@@ -254,8 +254,8 @@
border-radius: 50%;
font-size: 1rem;
font-weight: 700;
color: white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
color: var(--brand-on);
box-shadow: 0 2px 8px rgba(var(--shadow-rgb), 0.15);
position: relative;
}
@@ -265,30 +265,31 @@
inset: -2px;
border-radius: 50%;
border: 2px solid transparent;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.4), transparent) border-box;
background: linear-gradient(135deg, rgba(var(--text-inverse-rgb), 0.4), transparent) border-box;
mask: linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0);
mask-composite: exclude;
-webkit-mask-composite: xor;
}
.rankBadge1 {
background: linear-gradient(135deg, #c9a227 0%, #e8c547 50%, #c9a227 100%);
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
background: linear-gradient(135deg, var(--status-below) 0%, var(--medal-gold) 50%, var(--status-below) 100%);
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.2);
}
.rankBadge2 {
background: linear-gradient(135deg, #8c8c8c 0%, #c0c0c0 50%, #8c8c8c 100%);
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
background: linear-gradient(135deg, var(--text-muted) 0%, var(--medal-silver) 50%, var(--text-muted) 100%);
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.2);
}
.rankBadge3 {
background: linear-gradient(135deg, #a5673f 0%, #cd7f32 50%, #a5673f 100%);
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
background: linear-gradient(135deg, var(--status-below) 0%, var(--medal-bronze) 50%, var(--status-below) 100%);
text-shadow: 0 1px 2px rgba(var(--shadow-rgb), 0.2);
}
.rankNumber {
font-variant-numeric: tabular-nums;
font-size: 1rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
}
.schoolCell {
@@ -296,18 +297,18 @@
}
.schoolLink {
color: var(--text-primary, #1a1612);
color: var(--text-primary);
text-decoration: none;
transition: color 0.2s ease;
}
.schoolLink:hover {
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
}
.areaCell,
.typeCell {
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
}
/* LA subline under the school name — mobile only (Area column hidden there). */
@@ -315,7 +316,7 @@
display: none;
font-size: 0.75rem;
font-weight: 400;
color: var(--text-muted, #8a847a);
color: var(--text-muted);
}
.valueCell {
@@ -324,7 +325,7 @@
}
.valueCell strong {
color: var(--accent-teal, #2d7d7d);
color: var(--status-above);
font-weight: 700;
}
@@ -346,7 +347,7 @@
.noResults {
text-align: center;
padding: 4rem 2rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
}
.noResults p {
+14 -14
View File
@@ -17,7 +17,7 @@
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
margin-bottom: 0.75rem;
}
@@ -41,7 +41,7 @@
top: 0;
height: 100%;
width: 1px;
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
}
/* ── Per-bar national average marker ──
@@ -54,7 +54,7 @@
bottom: -3px;
width: 2px;
transform: translateX(-50%);
background: var(--accent-coral, #e07256);
background: var(--brand);
border-radius: 2px;
z-index: 4;
pointer-events: none;
@@ -69,7 +69,7 @@
width: 5px;
height: 5px;
border-radius: 50%;
background: var(--accent-coral, #e07256);
background: var(--brand);
}
.barHeaderRight {
@@ -81,7 +81,7 @@
.natLabel {
font-size: 0.55rem;
font-weight: 700;
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
text-transform: uppercase;
letter-spacing: 0.03em;
}
@@ -123,18 +123,18 @@
}
.barExpected {
background: var(--accent-teal-light, #3a9e9e);
background: var(--brand);
}
.barExceeding {
background: var(--accent-teal, #2d7d7d);
background: var(--brand);
}
.barLabel {
font-family: var(--font-playfair), 'Playfair Display', Georgia, serif;
font-family: var(--font-display);
font-size: 0.78rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
white-space: nowrap;
position: relative;
z-index: 3;
@@ -142,7 +142,7 @@
.barLabelSuffix {
font-weight: 500;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
font-size: 0.6rem;
text-transform: uppercase;
letter-spacing: 0.06em;
@@ -153,7 +153,7 @@
position: relative;
height: 14px;
margin-top: 0.3rem;
border-top: 1px solid var(--border-color, #e5dfd5);
border-top: 1px solid var(--border);
}
.rulerTick {
@@ -161,7 +161,7 @@
top: 0;
width: 1px;
height: 3px;
background: var(--border-color, #e5dfd5);
background: var(--border);
}
.rulerLabel {
@@ -169,7 +169,7 @@
top: 5px;
font-size: 0.5rem;
font-weight: 500;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
transform: translateX(-50%);
letter-spacing: 0.01em;
opacity: 0.7;
@@ -198,7 +198,7 @@
gap: 0.35rem;
font-size: 0.65rem;
font-weight: 500;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
}
.legendSwatch {
+3 -3
View File
@@ -145,15 +145,15 @@ export default function SatsChart({ subjects }: SatsChartProps) {
</div>
<div className={styles.legend}>
<div className={styles.legendItem}>
<div className={styles.legendSwatch} style={{ background: 'var(--accent-teal-light, #3a9e9e)' }} />
<div className={styles.legendSwatch} style={{ background: 'var(--status-above)' }} />
Expected standard
</div>
<div className={styles.legendItem}>
<div className={styles.legendSwatch} style={{ background: 'var(--accent-teal, #2d7d7d)' }} />
<div className={styles.legendSwatch} style={{ background: 'var(--status-above)' }} />
Exceeding / high score
</div>
<div className={styles.legendItem}>
<div className={styles.legendSwatch} style={{ background: 'var(--accent-coral, #e07256)', width: '3px', height: '12px', borderRadius: '2px' }} />
<div className={styles.legendSwatch} style={{ background: 'var(--brand)', width: '3px', height: '12px', borderRadius: '2px' }} />
National average
</div>
</div>
+25 -24
View File
@@ -1,6 +1,6 @@
.card {
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-left: 3px solid transparent;
border-radius: 10px;
padding: 1rem 1.125rem;
@@ -8,13 +8,13 @@
}
.card.cardInCompare {
border-color: var(--accent-teal, #2d7d7d);
box-shadow: 0 0 0 1px var(--accent-teal, #2d7d7d);
border-color: var(--brand);
box-shadow: 0 0 0 1px var(--brand);
}
.card:hover {
border-left-color: var(--accent-coral, #e07256);
box-shadow: var(--shadow-medium, 0 4px 20px rgba(26, 22, 18, 0.1));
border-left-color: var(--brand);
box-shadow: var(--shadow-medium, 0 4px 20px rgba(var(--shadow-rgb), 0.1));
transform: translateY(-1px);
}
@@ -31,24 +31,24 @@
font-size: 1rem;
font-weight: 600;
line-height: 1.35;
font-family: var(--font-playfair), 'Playfair Display', serif;
font-family: var(--font-display);
}
.title a {
color: var(--text-primary, #1a1612);
color: var(--text-primary);
text-decoration: none;
transition: color 0.2s ease;
}
.title a:hover {
color: var(--accent-coral, #e07256);
color: var(--brand);
}
.distance {
font-size: 0.75rem;
color: var(--accent-teal, #2d7d7d);
color: var(--brand);
white-space: nowrap;
background: var(--accent-teal-bg);
background: var(--brand-bg);
padding: 0.125rem 0.5rem;
border-radius: 12px;
font-weight: 500;
@@ -63,9 +63,9 @@
.metaItem {
font-size: 0.75rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
padding: 0.125rem 0.5rem;
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
border-radius: 3px;
}
@@ -75,9 +75,9 @@
gap: 0.625rem;
margin-bottom: 0.875rem;
padding: 0.625rem 0.75rem;
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
border-radius: 6px;
border: 1px solid var(--border-color, #e5dfd5);
border: 1px solid var(--border);
}
.metric {
@@ -88,12 +88,13 @@
.metricLabel {
font-size: 0.6875rem;
color: var(--text-muted, #8a847a);
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.metricValue {
font-variant-numeric: tabular-nums;
display: flex;
align-items: center;
gap: 0.375rem;
@@ -101,7 +102,7 @@
.metricValue strong {
font-size: 1rem;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
font-weight: 700;
}
@@ -126,18 +127,18 @@
}
.trendUp {
color: var(--accent-teal, #2d7d7d);
background: var(--accent-teal-bg);
color: var(--status-above);
background: var(--status-above-bg);
}
.trendDown {
color: var(--accent-coral, #e07256);
background: var(--accent-coral-bg);
color: var(--brand);
background: var(--brand-bg);
}
.trendStable {
color: var(--text-muted, #8a847a);
background: rgba(138, 132, 122, 0.15);
color: var(--text-muted);
background: rgba(var(--muted-rgb), 0.15);
}
.actions {
@@ -156,7 +157,7 @@
.metricHint {
font-size: 0.7rem;
color: var(--text-muted, #8a847a);
color: var(--text-muted);
display: block;
margin-top: 1px;
font-weight: 400;
@@ -6,7 +6,7 @@
position: relative;
width: 100%;
height: 210px;
background: #dfe6e2;
background: var(--bg-secondary);
isolation: isolate;
}
@@ -47,7 +47,7 @@
width: 100%;
height: 100%;
background:
linear-gradient(100deg, rgba(255, 255, 255, 0) 40%, rgba(255, 255, 255, .5) 50%, rgba(255, 255, 255, 0) 60%) #e7e2da;
linear-gradient(100deg, rgba(255, 255, 255, 0) 40%, rgba(255, 255, 255, .5) 50%, rgba(255, 255, 255, 0) 60%) var(--bg-secondary);
background-size: 200% 100%;
animation: shimmer 1.4s infinite;
}
@@ -85,11 +85,11 @@
border-radius: 999px;
font-size: 13px;
font-weight: 600;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
background: rgba(255, 255, 255, .85);
-webkit-backdrop-filter: blur(6px);
backdrop-filter: blur(6px);
box-shadow: 0 2px 10px rgba(0, 0, 0, .16);
box-shadow: 0 2px 10px rgba(var(--shadow-rgb), .16);
opacity: 0;
transform: translateY(4px);
transition: opacity .16s ease, transform .16s ease;
@@ -118,7 +118,7 @@
rgba(255, 255, 255, .35) 35%,
rgba(255, 255, 255, .75) 62%,
rgba(255, 255, 255, .95) 82%,
var(--bg-card, #fff) 100%);
var(--bg-card) 100%);
}
.closeBtn {
@@ -134,9 +134,9 @@
border: none;
border-radius: 8px;
background: rgba(255, 255, 255, .92);
color: var(--text-primary, #1a1612);
color: var(--text-primary);
cursor: pointer;
box-shadow: 0 2px 10px rgba(0, 0, 0, .2);
box-shadow: 0 2px 10px rgba(var(--shadow-rgb), .2);
}
.closeBtn:hover {
+4 -4
View File
@@ -33,12 +33,12 @@
border: 2px solid rgba(0, 0, 0, 0.2);
border-radius: 4px;
cursor: pointer;
color: #333;
color: var(--text-primary);
transition: background 0.15s ease, color 0.15s ease;
}
.fullscreenBtn:hover {
background: #f4f4f4;
background: var(--bg-secondary);
color: #000;
}
@@ -57,9 +57,9 @@
.spinner {
width: 2rem;
height: 2rem;
border: 3px solid rgba(224, 114, 86, 0.3);
border: 3px solid rgba(var(--brand-rgb), 0.3);
border-radius: 50%;
border-top-color: var(--accent-coral, #e07256);
border-top-color: var(--brand);
animation: spin 0.8s linear infinite;
}
+36 -35
View File
@@ -2,8 +2,8 @@
display: flex;
align-items: center;
gap: 1rem;
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-left: 3px solid transparent;
border-radius: 8px;
padding: 1rem 1.25rem;
@@ -12,17 +12,17 @@
}
.row:hover {
box-shadow: 0 2px 8px rgba(26, 22, 18, 0.06);
box-shadow: 0 2px 8px rgba(var(--shadow-rgb), 0.06);
}
/* Phase border colours */
.phasePrimary { border-left-color: var(--phase-primary, #5b8cbf); }
.phaseAllThrough { border-left-color: var(--phase-all-through, #7a9a6d); }
.phaseNursery { border-left-color: var(--phase-nursery, #e0a0b0); }
.phasePrimary { border-left-color: var(--phase-primary); }
.phaseAllThrough { border-left-color: var(--phase-all-through); }
.phaseNursery { border-left-color: var(--phase-nursery); }
.rowInCompare {
border-left-color: var(--accent-teal, #2d7d7d);
background: var(--bg-secondary, #f3ede4);
border-left-color: var(--brand);
background: var(--bg-secondary);
}
@keyframes rowFadeIn {
@@ -50,7 +50,7 @@
.schoolName {
font-size: 0.9375rem;
font-weight: 600;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
text-decoration: none;
white-space: nowrap;
overflow: hidden;
@@ -60,7 +60,7 @@
}
.schoolName:hover {
color: var(--accent-coral, #e07256);
color: var(--brand);
}
/* Phase label pill */
@@ -96,8 +96,8 @@
line-height: 1.4;
border-radius: 4px;
white-space: nowrap;
background: rgba(26, 22, 18, 0.05);
color: var(--text-secondary, #5c564d);
background: rgba(var(--shadow-rgb), 0.05);
color: var(--text-secondary);
}
/* Line 3: stats */
@@ -115,10 +115,11 @@
}
.statValue {
font-variant-numeric: tabular-nums;
font-size: 0.9375rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
font-family: var(--font-playfair), 'Playfair Display', serif;
color: var(--text-primary);
font-family: var(--font-display);
display: inline-flex;
align-items: center;
gap: 0.2rem;
@@ -126,7 +127,7 @@
.statLabel {
font-size: 0.75rem;
color: var(--text-muted, #8a847a);
color: var(--text-muted);
white-space: nowrap;
}
@@ -137,9 +138,9 @@
margin-left: 1px;
}
.trendUp { color: var(--accent-teal, #2d7d7d); }
.trendDown { color: var(--accent-coral, #e07256); }
.trendStable { color: var(--text-muted, #8a847a); }
.trendUp { color: var(--status-above); }
.trendDown { color: var(--brand); }
.trendStable { color: var(--text-muted); }
/* Line 4: location */
.line4 {
@@ -148,13 +149,13 @@
flex-wrap: wrap;
gap: 0;
font-size: 0.8rem;
color: var(--text-muted, #8a847a);
color: var(--text-muted);
}
.line4 span:not(:last-child)::after {
content: '·';
margin: 0 0.4rem;
color: var(--border-color, #e5dfd5);
color: var(--border);
}
.distanceBadge {
@@ -162,8 +163,8 @@
padding: 0.0625rem 0.375rem;
font-size: 0.75rem;
font-weight: 600;
background: var(--accent-teal, #2d7d7d);
color: white;
background: var(--brand);
color: var(--brand-on);
border-radius: 3px;
}
@@ -200,23 +201,23 @@
font-weight: 400;
}
.ofsted1 { background: var(--accent-teal-bg); color: var(--accent-teal, #2d7d7d); }
.ofsted2 { background: rgba(60, 140, 60, 0.12); color: #2f7a2f; }
.ofsted3 { background: var(--accent-gold-bg); color: var(--accent-gold-text, #7a6800); }
.ofsted4 { background: var(--accent-coral-bg); color: var(--accent-coral, #e07256); }
.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); }
/* ── Ofsted badge variants ──────────────────────────────────────────────── */
/* ofsted14 already defined above; these cover the two new framework states */
.ofstedRc { background: #5a3a6e; color: #fff; }
.ofstedRc { background: var(--phase-secondary-text); color: var(--text-inverse); }
/* Inspected but with no overall grade (OEIF post-Sept-2024) — neutral slate,
distinct from the grey "Not yet inspected" pending state. */
.ofstedInspected { background: #e6ecf2; color: #45586b; }
.ofstedPending { background: #e0e0e0; color: #666; }
.ofstedInspected { background: var(--phase-primary-bg); color: var(--phase-primary-text); }
.ofstedPending { background: var(--border); color: var(--text-muted); }
/* ── vs-national delta line (under RWM metric) ──────────────────────────── */
.vsNational { font-size: 0.7rem; color: var(--accent-teal, #2d7d7d); font-weight: 600; }
.vsNationalNeg { font-size: 0.7rem; color: var(--accent-coral, #e07256); font-weight: 600; }
.vsNationalFlat { font-size: 0.7rem; color: var(--text-muted, #8a847a); }
.vsNational { font-size: 0.7rem; color: var(--status-above); font-weight: 600; }
.vsNationalNeg { font-size: 0.7rem; color: var(--brand); font-weight: 600; }
.vsNationalFlat { font-size: 0.7rem; color: var(--text-muted); }
/* ── Mobile ──────────────────────────────────────────── */
@media (max-width: 640px) {
@@ -257,7 +258,7 @@
/* GIAS "Open, but proposed to close" marker */
.attrClosing {
background: #fdf6e3;
color: #8a6200;
border: 1px solid #e2c96f;
background: var(--status-below-bg);
color: var(--status-below);
border: 1px solid var(--status-below-bg);
}
@@ -3,9 +3,9 @@
}
.warning {
background: var(--accent-gold-bg);
border: 1px solid var(--accent-gold, #c9a227);
color: var(--text-primary, #1a1612);
background: var(--status-below-bg);
border: 1px solid var(--status-below);
color: var(--text-primary);
padding: 1rem;
border-radius: 8px;
margin-bottom: 1rem;
@@ -21,21 +21,21 @@
width: 100%;
padding: 0.875rem 1rem;
font-size: 1rem;
border: 2px solid var(--border-color, #e5dfd5);
border: 2px solid var(--border);
border-radius: 8px;
background: var(--bg-card, white);
color: var(--text-primary, #1a1612);
background: var(--bg-card);
color: var(--text-primary);
transition: all 0.2s ease;
}
.searchInput::placeholder {
color: var(--text-muted, #8a847a);
color: var(--text-muted);
}
.searchInput:focus {
outline: none;
border-color: var(--accent-coral, #e07256);
box-shadow: 0 0 0 3px var(--accent-coral-bg);
border-color: var(--brand);
box-shadow: 0 0 0 3px var(--brand-bg);
}
.searchSpinner {
@@ -45,9 +45,9 @@
transform: translateY(-50%);
width: 1.25rem;
height: 1.25rem;
border: 2px solid rgba(224, 114, 86, 0.3);
border: 2px solid rgba(var(--brand-rgb), 0.3);
border-radius: 50%;
border-top-color: var(--accent-coral, #e07256);
border-top-color: var(--brand);
animation: spin 0.6s linear infinite;
}
@@ -71,17 +71,17 @@
}
.results::-webkit-scrollbar-track {
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
border-radius: 4px;
}
.results::-webkit-scrollbar-thumb {
background: var(--border-color, #e5dfd5);
background: var(--border);
border-radius: 4px;
}
.results::-webkit-scrollbar-thumb:hover {
background: var(--text-muted, #8a847a);
background: var(--text-muted);
}
.resultItem {
@@ -90,16 +90,16 @@
align-items: center;
gap: 1rem;
padding: 1rem;
background: var(--bg-secondary, #f3ede4);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-secondary);
border: 1px solid var(--border);
border-radius: 10px;
transition: all 0.2s ease;
}
.resultItem:hover {
background: var(--bg-card, white);
border-color: var(--accent-coral, #e07256);
box-shadow: var(--shadow-soft, 0 2px 8px rgba(26, 22, 18, 0.06));
background: var(--bg-card);
border-color: var(--brand);
box-shadow: var(--shadow-soft, 0 2px 8px rgba(var(--shadow-rgb), 0.06));
}
.schoolInfo {
@@ -110,7 +110,7 @@
.schoolName {
font-size: 1rem;
font-weight: 600;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
margin-bottom: 0.25rem;
white-space: nowrap;
overflow: hidden;
@@ -125,7 +125,7 @@
display: flex;
gap: 1rem;
font-size: 0.875rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
}
.schoolMeta span {
@@ -138,14 +138,14 @@
.noResults {
text-align: center;
padding: 2rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
font-size: 0.9375rem;
}
.hint {
text-align: center;
padding: 2rem;
color: var(--text-muted, #8a847a);
color: var(--text-muted);
font-size: 0.9375rem;
}
@@ -2,8 +2,8 @@
display: flex;
align-items: center;
gap: 1rem;
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-left: 3px solid transparent;
border-radius: 8px;
padding: 1rem 1.25rem;
@@ -12,17 +12,17 @@
}
.row:hover {
box-shadow: 0 2px 8px rgba(26, 22, 18, 0.06);
box-shadow: 0 2px 8px rgba(var(--shadow-rgb), 0.06);
}
/* Phase border colours */
.phaseSecondary { border-left-color: var(--phase-secondary, #9b6bb0); }
.phaseAllThrough { border-left-color: var(--phase-all-through, #7a9a6d); }
.phasePost16 { border-left-color: var(--phase-post16, #c4915e); }
.phaseSecondary { border-left-color: var(--phase-secondary); }
.phaseAllThrough { border-left-color: var(--phase-all-through); }
.phasePost16 { border-left-color: var(--phase-post16); }
.rowInCompare {
border-left-color: var(--accent-teal, #2d7d7d);
background: var(--bg-secondary, #f3ede4);
border-left-color: var(--brand);
background: var(--bg-secondary);
}
@keyframes rowFadeIn {
@@ -50,7 +50,7 @@
.schoolName {
font-size: 0.9375rem;
font-weight: 600;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
text-decoration: none;
white-space: nowrap;
overflow: hidden;
@@ -60,7 +60,7 @@
}
.schoolName:hover {
color: var(--accent-coral, #e07256);
color: var(--brand);
}
/* Line 2: context tags */
@@ -81,8 +81,8 @@
line-height: 1.4;
border-radius: 4px;
white-space: nowrap;
background: rgba(26, 22, 18, 0.05);
color: var(--text-secondary, #5c564d);
background: rgba(var(--shadow-rgb), 0.05);
color: var(--text-secondary);
}
/* Line 3: KS4 stats */
@@ -100,22 +100,24 @@
}
.statValueLarge {
font-variant-numeric: tabular-nums;
font-size: 1.125rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
font-family: var(--font-playfair), 'Playfair Display', serif;
color: var(--text-primary);
font-family: var(--font-display);
}
.statValue {
font-variant-numeric: tabular-nums;
font-size: 0.9375rem;
font-weight: 700;
color: var(--text-primary, #1a1612);
font-family: var(--font-playfair), 'Playfair Display', serif;
color: var(--text-primary);
font-family: var(--font-display);
}
.statLabel {
font-size: 0.75rem;
color: var(--text-muted, #8a847a);
color: var(--text-muted);
white-space: nowrap;
}
@@ -125,8 +127,8 @@
white-space: nowrap;
}
.deltaPositive { color: #2f7a2f; }
.deltaNegative { color: var(--accent-coral, #e07256); }
.deltaPositive { color: var(--status-above); }
.deltaNegative { color: var(--brand); }
/* Line 4: location + distance */
.line4 {
@@ -135,13 +137,13 @@
flex-wrap: wrap;
gap: 0;
font-size: 0.8rem;
color: var(--text-muted, #8a847a);
color: var(--text-muted);
}
.line4 span:not(:last-child)::after {
content: '·';
margin: 0 0.4rem;
color: var(--border-color, #e5dfd5);
color: var(--border);
}
.distanceBadge {
@@ -149,8 +151,8 @@
padding: 0.0625rem 0.375rem;
font-size: 0.75rem;
font-weight: 600;
background: var(--accent-teal, #2d7d7d);
color: white;
background: var(--brand);
color: var(--brand-on);
border-radius: 3px;
}
@@ -175,15 +177,15 @@
font-size: 0.75rem;
font-weight: 600;
line-height: 1.4;
background: rgba(26, 22, 18, 0.05);
color: var(--text-secondary, #5c564d);
background: rgba(var(--shadow-rgb), 0.05);
color: var(--text-secondary);
border-radius: 4px;
white-space: nowrap;
}
.selectiveTag {
background: rgba(180, 120, 0, 0.1);
color: #8a6200;
background: rgba(var(--status-below-rgb), 0.1);
color: var(--status-below);
}
/* ── Ofsted badge ────────────────────────────────────── */
@@ -202,17 +204,17 @@
font-weight: 400;
}
.ofsted1 { background: var(--accent-teal-bg); color: var(--accent-teal, #2d7d7d); }
.ofsted2 { background: rgba(60, 140, 60, 0.12); color: #2f7a2f; }
.ofsted3 { background: var(--accent-gold-bg); color: var(--accent-gold-text, #7a6800); }
.ofsted4 { background: var(--accent-coral-bg); color: var(--accent-coral, #e07256); }
.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); }
/* ── Ofsted badge variants ──────────────────────────────────────────────── */
.ofstedRc { background: #5a3a6e; color: #fff; }
.ofstedRc { background: var(--phase-secondary-text); color: var(--text-inverse); }
/* Inspected but with no overall grade (OEIF post-Sept-2024) — neutral slate,
distinct from the grey "Not yet inspected" pending state. */
.ofstedInspected { background: #e6ecf2; color: #45586b; }
.ofstedPending { background: #e0e0e0; color: #666; }
.ofstedInspected { background: var(--phase-primary-bg); color: var(--phase-primary-text); }
.ofstedPending { background: var(--border); color: var(--text-muted); }
/* ── Right actions column ────────────────────────────── */
.rowActions {
@@ -268,7 +270,7 @@
}
.closingTag {
background: #fdf6e3;
color: #8a6200;
border: 1px solid #e2c96f;
background: var(--status-below-bg);
color: var(--status-below);
border: 1px solid var(--status-below-bg);
}
@@ -1,15 +1,15 @@
/* Special-school / PRU / AP context note: soft, informational (teal), not a
warning. Shared by both detail views so the styling can't drift. */
.note {
background: var(--bg-secondary, #f3ede4);
border-left: 4px solid var(--accent-teal, #2d7d7d);
background: var(--bg-secondary);
border-left: 4px solid var(--brand);
border-radius: 0 6px 6px 0;
padding: 0.7rem 1rem;
margin: 0 0 1rem;
font-size: 0.9rem;
line-height: 1.5;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
}
.note strong {
color: var(--text-primary, #1a1612);
color: var(--text-primary);
}
@@ -1,6 +1,6 @@
.moreMeasures {
margin-top: 0.5rem;
border-top: 1px solid var(--border-light);
border-top: 1px solid var(--border);
padding-top: 0.75rem;
}
@@ -8,7 +8,7 @@
cursor: pointer;
font-weight: 600;
font-size: 0.88rem;
color: var(--accent-coral-dark);
color: var(--brand-strong);
}
.stripNote {
@@ -88,7 +88,7 @@ export function CompareAtAGlance({
)}
{display.kind === 'transitional' && (
<>
<span className={s.badge} style={{ backgroundColor: '#e2e8f0', color: '#475569' }}>
<span className={s.badge} style={{ backgroundColor: 'var(--bg-secondary)', color: 'var(--text-secondary)' }}>
No overall grade
</span>
<span className={s.small}>Sub-judgements only</span>
@@ -54,7 +54,7 @@ function ResultCell({ display }: { display: OfstedDisplay }) {
if (display.kind === 'transitional') {
return (
<>
<span className={s.badge} style={{ backgroundColor: '#e2e8f0', color: '#475569' }}>
<span className={s.badge} style={{ backgroundColor: 'var(--bg-secondary)', color: 'var(--text-secondary)' }}>
No overall grade
</span>
<span className={s.small}>
@@ -5,10 +5,10 @@
.explore summary {
cursor: pointer;
font-weight: 600;
color: var(--accent-coral-dark);
color: var(--brand-strong);
padding: 0.85rem 1.1rem;
background: var(--bg-card);
border: 1px solid var(--border-light);
border: 1px solid var(--border);
border-radius: 8px;
}
@@ -17,7 +17,7 @@
}
.inner {
border: 1px solid var(--border-light);
border: 1px solid var(--border);
border-top: none;
border-radius: 0 0 8px 8px;
background: var(--bg-card);
@@ -43,7 +43,7 @@
font-size: 0.9rem;
padding: 0.4rem 0.6rem;
border-radius: 8px;
border: 1px solid var(--border-light);
border: 1px solid var(--border);
background: var(--bg-card);
color: var(--text-primary);
max-width: 100%;
@@ -9,12 +9,12 @@
}
.sectionTitle {
font-family: var(--font-playfair), 'Playfair Display', Georgia, serif;
font-family: var(--font-display);
font-size: 1.45rem;
font-weight: 700;
margin: 0;
padding-left: 0.75rem;
border-left: 3px solid var(--accent-coral-dark);
border-left: 3px solid var(--brand-strong);
}
.how {
@@ -36,7 +36,7 @@
back into the shared grid. */
.measure {
background: var(--bg-card);
border: 1px solid var(--border-light);
border: 1px solid var(--border);
border-radius: 12px;
box-shadow: var(--shadow-soft);
padding: 0.75rem 0.85rem;
@@ -59,7 +59,7 @@
gap: 0.35rem 0.5rem;
flex-wrap: wrap;
padding: 0.5rem 0;
border-top: 1px solid var(--border-light);
border-top: 1px solid var(--border);
margin-top: 0.5rem;
font-size: 0.95rem;
}
@@ -113,18 +113,18 @@
}
.chipGood {
background: rgba(45, 125, 125, 0.14);
color: var(--accent-teal);
background: rgba(var(--status-above-rgb), 0.14);
color: var(--status-above);
}
.chipWarn {
background: var(--accent-gold-bg);
color: var(--accent-gold-text);
background: var(--status-below-bg);
color: var(--status-below);
}
.chipBad {
background: var(--accent-coral-bg);
color: var(--accent-coral-dark);
background: var(--brand-bg);
color: var(--brand-strong);
}
.chipNeutral {
@@ -141,18 +141,18 @@
}
.badgeGood {
background: rgba(45, 125, 125, 0.14);
color: var(--accent-teal);
background: rgba(var(--status-above-rgb), 0.14);
color: var(--status-above);
}
.badgeWarn {
background: var(--accent-gold-bg);
color: var(--accent-gold-text);
background: var(--status-below-bg);
color: var(--status-below);
}
.badgeBad {
background: var(--accent-coral-bg);
color: var(--accent-coral-dark);
background: var(--brand-bg);
color: var(--brand-strong);
}
.rcList {
@@ -200,7 +200,7 @@
.card {
background: var(--bg-card);
border: 1px solid var(--border-light);
border: 1px solid var(--border);
border-radius: 16px;
box-shadow: var(--shadow-soft);
padding: 1.25rem 1.5rem;
@@ -208,7 +208,7 @@
}
.link {
color: var(--accent-coral-dark);
color: var(--brand-strong);
}
@media (min-width: 761px) {
@@ -230,14 +230,14 @@
.rowLabel {
color: var(--text-secondary);
padding: 0.85rem 0.5rem 0.85rem 0;
border-bottom: 1px solid var(--border-light);
border-bottom: 1px solid var(--border);
}
.cell {
display: block;
padding: 0.85rem 0.25rem;
border-top: none;
border-bottom: 1px solid var(--border-light);
border-bottom: 1px solid var(--border);
margin-top: 0;
}
@@ -19,7 +19,7 @@
padding: 0.25rem 0;
font-size: 1.0625rem;
font-weight: 600;
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
background: none;
border: none;
cursor: pointer;
@@ -29,7 +29,7 @@
.topBack:hover {
color: var(--accent-coral-dark, #c85a3e);
color: var(--brand-strong);
text-decoration: underline;
text-underline-offset: 2px;
}
@@ -38,8 +38,8 @@
/* Header Section */
.header {
position: relative;
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 10px;
/* Padding lives on .headerContent so the map band can bleed to the edges. */
padding: 0;
@@ -88,12 +88,13 @@
.headerHasMap .actions .btnAdd {
/* Sits on the map hero, which renders light in both themes. */
background: rgba(255, 255, 255, 0.9);
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
border-color: transparent;
-webkit-backdrop-filter: blur(6px);
backdrop-filter: blur(6px);
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.16);
box-shadow: 0 2px 10px rgba(var(--shadow-rgb), 0.16);
}
@@ -116,14 +117,14 @@
padding: 0;
font: inherit;
font-weight: 600;
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
cursor: pointer;
white-space: nowrap;
}
.mapLink:hover {
color: var(--accent-coral-dark, #c45a3f);
color: var(--brand-strong);
text-decoration: underline;
text-underline-offset: 2px;
}
@@ -137,11 +138,11 @@
.schoolName {
font-size: clamp(2rem, 5vw, 3.25rem);
font-weight: 700;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
margin-bottom: 0.5rem;
line-height: 1.1;
letter-spacing: -0.01em;
font-family: var(--font-playfair), "Playfair Display", serif;
font-family: var(--font-display);
}
@@ -155,16 +156,16 @@
.metaItem {
font-size: 0.8125rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
padding: 0.125rem 0.5rem;
background: var(--bg-secondary, #f3ede4);
background: var(--bg-secondary);
border-radius: 3px;
}
.address {
font-size: 0.875rem;
color: var(--text-muted, #8a847a);
color: var(--text-muted);
margin: 0 0 0.75rem;
}
@@ -180,18 +181,18 @@
.headerDetail {
font-size: 0.8125rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
}
.headerDetail strong {
color: var(--text-primary, #1a1612);
color: var(--text-primary);
font-weight: 600;
}
.headerDetail a {
color: var(--accent-teal, #2d7d7d);
color: var(--brand);
text-decoration: none;
}
@@ -213,7 +214,7 @@
border: none;
font-size: 0.8125rem;
font-weight: 600;
color: var(--accent-teal, #2d7d7d);
color: var(--brand);
cursor: pointer;
}
@@ -236,25 +237,25 @@
cursor: pointer;
transition: all 0.2s ease;
white-space: nowrap;
box-shadow: var(--shadow-soft, 0 2px 8px rgba(26, 22, 18, 0.08));
box-shadow: var(--shadow-soft, 0 2px 8px rgba(var(--shadow-rgb), 0.08));
}
.btnAdd {
background: var(--accent-coral-dark, #b04a2e);
color: white;
background: var(--brand-strong);
color: var(--brand-on);
}
.btnAdd:hover {
background: var(--accent-coral-darker, #9c3f26);
background: var(--brand-stronger);
transform: translateY(-1px);
}
.btnRemove {
background: var(--accent-teal, #2d7d7d);
color: white;
background: var(--brand);
color: var(--brand-on);
}
@@ -270,13 +271,13 @@
position: sticky;
top: 64px; /* global header height on desktop */
z-index: 10;
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-top: none;
border-radius: 0 0 10px 10px;
padding: 0.5rem 0.75rem;
margin-bottom: 1rem;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
box-shadow: 0 2px 4px rgba(var(--shadow-rgb), 0.04);
display: flex;
align-items: center;
gap: 0.5rem;
@@ -291,9 +292,9 @@
padding: 0.3rem 0.625rem;
font-size: 0.75rem;
font-weight: 600;
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
background: none;
border: 1px solid var(--border-color, #e5dfd5);
border: 1px solid var(--border);
border-radius: 4px;
cursor: pointer;
white-space: nowrap;
@@ -302,8 +303,8 @@
.sectionNavBack:hover {
background: var(--bg-secondary, #f3ede4);
border-color: var(--accent-coral, #e07256);
background: var(--bg-secondary);
border-color: var(--brand);
}
@@ -334,7 +335,7 @@
padding: 0.3rem 0.625rem;
font-size: 0.75rem;
font-weight: 500;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
text-decoration: none;
border-radius: 4px;
transition: all 0.15s ease;
@@ -344,21 +345,21 @@
.sectionNavLink:hover {
background: var(--bg-secondary, #f3ede4);
color: var(--text-primary, #1a1612);
background: var(--bg-secondary);
color: var(--text-primary);
}
.sectionNavLinkActive {
background: var(--accent-coral-dark, #b04a2e);
color: white;
background: var(--brand-strong);
color: var(--brand-on);
font-weight: 600;
}
.sectionNavLinkActive:hover {
background: var(--accent-coral-dark, #c45a3f);
color: white;
background: var(--brand-strong);
color: var(--brand-on);
}
@@ -373,12 +374,12 @@
gap: 0.5rem;
min-height: 38px;
padding: 0.34rem 0.7rem;
background: var(--bg-secondary, #f3ede4);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-secondary);
border: 1px solid var(--border);
border-radius: 8px;
cursor: pointer;
font-family: var(--font-dm-sans), "DM Sans", sans-serif;
color: var(--text-primary, #1a1612);
font-family: var(--font-ui);
color: var(--text-primary);
}
@@ -396,7 +397,7 @@
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
}
@@ -411,7 +412,7 @@
.sectionNavMenuChev {
flex: none;
color: var(--text-muted, #6d685f);
color: var(--text-muted);
font-size: 0.7rem;
}
@@ -426,9 +427,9 @@
width: 38px;
height: 38px;
border-radius: 9px;
border: 1px solid var(--accent-coral-dark, #b04a2e);
background: var(--accent-coral-dark, #b04a2e);
color: white;
border: 1px solid var(--brand-strong);
background: var(--brand-strong);
color: var(--brand-on);
cursor: pointer;
transition: background 0.15s ease, border-color 0.15s ease;
}
@@ -447,9 +448,9 @@
width: 16px;
height: 16px;
border-radius: 50%;
background: var(--bg-card, white);
color: var(--accent-coral-dark, #c45a3f);
border: 1.5px solid var(--accent-coral, #e07256);
background: var(--bg-card);
color: var(--brand-strong);
border: 1.5px solid var(--brand);
display: flex;
align-items: center;
justify-content: center;
@@ -460,9 +461,9 @@
.sectionNavCompareIconIn {
background: var(--bg-card, white);
border-color: var(--accent-teal, #2d7d7d);
color: var(--accent-teal, #2d7d7d);
background: var(--bg-card);
border-color: var(--brand);
color: var(--brand);
}
@@ -474,9 +475,9 @@
padding: 0.34rem 0.7rem;
font-size: 0.75rem;
font-weight: 600;
color: white;
background: var(--accent-coral-dark, #b04a2e);
border: 1px solid var(--accent-coral-dark, #b04a2e);
color: var(--brand-on);
background: var(--brand-strong);
border: 1px solid var(--brand-strong);
border-radius: 999px;
cursor: pointer;
white-space: nowrap;
@@ -485,21 +486,21 @@
.sectionNavCompare:hover {
background: var(--accent-coral-darker, #9c3f26);
border-color: var(--accent-coral-darker, #9c3f26);
background: var(--brand-stronger);
border-color: var(--brand-stronger);
}
.sectionNavCompareIn {
background: var(--bg-card, white);
color: var(--accent-teal, #2d7d7d);
border-color: var(--accent-teal, #2d7d7d);
background: var(--bg-card);
color: var(--brand);
border-color: var(--brand);
}
.sectionNavCompareIn:hover {
background: var(--bg-secondary, #f3ede4);
border-color: var(--accent-teal, #2d7d7d);
background: var(--bg-secondary);
border-color: var(--brand);
}
@@ -512,8 +513,8 @@
padding: 0.34rem 0.65rem;
font-size: 0.75rem;
font-weight: 600;
color: var(--text-primary, #1a1612);
background: var(--bg-secondary, #f3ede4);
color: var(--text-primary);
background: var(--bg-secondary);
border: none;
border-radius: 999px;
cursor: pointer;
@@ -523,7 +524,7 @@
.sectionNavAll:hover {
background: var(--border-color, #e5dfd5);
background: var(--border);
}
@@ -531,7 +532,7 @@
position: fixed;
inset: 0;
z-index: 1500;
background: rgba(26, 22, 18, 0.28);
background: rgba(var(--shadow-rgb), 0.28);
}
@@ -543,19 +544,19 @@
width: 230px;
max-height: min(70vh, 460px);
overflow-y: auto;
background: var(--bg-card, white);
border: 1px solid var(--border-color, #e5dfd5);
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 12px;
box-shadow: 0 18px 44px rgba(26, 22, 18, 0.2);
box-shadow: 0 18px 44px rgba(var(--shadow-rgb), 0.2);
padding: 0.35rem;
}
.sectionsPanelHead {
font-family: var(--font-playfair), "Playfair Display", Georgia, serif;
font-family: var(--font-display);
font-size: 0.9rem;
font-weight: 600;
color: var(--text-primary, #1a1612);
color: var(--text-primary);
padding: 0.4rem 0.6rem 0.5rem;
}
@@ -568,44 +569,44 @@
padding: 0.55rem 0.6rem;
border-radius: 8px;
font-size: 0.85rem;
color: var(--text-secondary, #5c564d);
color: var(--text-secondary);
text-decoration: none;
transition: background 0.12s ease;
}
.sectionsItem:hover {
background: var(--bg-secondary, #f3ede4);
color: var(--text-primary, #1a1612);
background: var(--bg-secondary);
color: var(--text-primary);
}
.sectionsItemActive {
background: var(--accent-coral-bg, rgba(224, 114, 86, 0.12));
color: var(--accent-coral-dark, #c45a3f);
background: var(--brand-bg);
color: var(--brand-strong);
font-weight: 600;
}
.sectionsTick {
color: var(--accent-coral-dark, #b04a2e);
color: var(--brand-strong);
}
/* GIAS "Open, but proposed to close" notice strip */
.closingStrip {
background: #fdf6e3;
border-left: 4px solid #e2c96f;
background: var(--status-below-bg);
border-left: 4px solid var(--status-below-bg);
border-radius: 0 6px 6px 0;
padding: 0.55rem 0.9rem;
margin: 0.5rem 0;
font-size: 0.88rem;
color: #6e5a00;
color: var(--status-below);
max-width: 68ch;
}
.closingStrip strong {
color: #8a6200;
color: var(--status-below);
}
@media (max-width: 640px) {
@@ -738,7 +739,7 @@
max-height: 74vh;
border-radius: 16px 16px 0 0;
padding: 0.5rem 0.6rem calc(0.8rem + env(safe-area-inset-bottom, 0));
box-shadow: 0 -10px 40px rgba(26, 22, 18, 0.25);
box-shadow: 0 -10px 40px rgba(var(--shadow-rgb), 0.25);
}
.sectionsItem {
File diff suppressed because it is too large Load Diff