No saved pupils yet. Complete a snapshot and click Save.
Built by Jack Flanagan · snapshotschools.co.uk
Pupil Snapshot
Snapshot captures where a young person is now, where they're heading, and what needs to happen to get them there. Built around the four areas of SEND, it gives everyone — from the class teacher to an external agency — the same clear, consistent picture. Because the end goal of SEND education is preparation for life and adulthood. This tool is built on that belief.
Pupil Details
Full Name
Known As
Completed By
Date Completed
School Setting
Key Stage
Primary Area of Need
School-specific fields (New Bridge School)
Pathway
My Class
Additional Information
Add photo
Pupil Snapshot
—
Complete the Snapshot tab to generate a summary.
Built by Jack Flanagan · snapshotschools.co.uk
User Guide
The Eight Domains
Support Levels
Each domain is scored A–E based on the level of support required. Scores are calculated automatically from your selections.
How scoring works
Within each domain, sub-domain scores are combined using a top-heavy weighted average — so a single severe need drives the score up, rather than being averaged away. Two or more high-level scores will always result in an E.
Built by Jack Flanagan · snapshotschools.co.uk
FAQ
Coming Soon
My School
My School will let you configure Snapshot for your setting — add your own pathways, class groups, destinations framework and staff. Each school gets its own personalised version of the tool.
Pathways
Add your school's own pathway model and destination framework
Classes
Set up your class groups and assign pupils across your setting
Staff
Manage who can access and complete snapshots across your school
Reports
View whole-school need profiles and export cohort-level summaries
Six fictional profiles covering a range of SEND settings, pathways and need profiles — including two Engagement Model pupils. Click any card to load the profile into the tool.
JM
James Mitchell · Jamie
Special School · KS4 · Pathway One · Cognition & Learning
Load →
Jamie is a Year 9 student who presents with moderate learning needs. He is working 2–3 years below expected levels in literacy and numeracy and requires scaffolded support across all learning activities. Jamie communicates verbally, is generally well-regulated and is fully ambulant and independent for personal care. He responds well to visual timetables and structured routines, and is on track toward supported employment and semi-independent living.
SM
Sarah Mitchell · Sarah
Special School · KS3 · Pathway Four · Sensory & Physical
Load →
Sarah is a Year 8 student who presents with complex physical and medical needs. She is a powered wheelchair user who requires a hoist for all transfers and is PEG fed, with a full individual healthcare plan covering seizure management and postural care. Sarah communicates using an eye-gaze device with SALT support. She benefits from calm, familiar environments and consistent adults. Specialist residential provision with high-quality care represents a genuinely successful adult life for Sarah.
RT
Ryan Thomas · Ryan
Special School · KS4 · Pathway Five · SEMH
Load →
Ryan is a Year 9 student who presents with significant social, emotional and mental health needs. He requires 1:1 support throughout the school day and has an active de-escalation plan with CAMHS involvement. Anxiety and emotional dysregulation are his primary barriers to learning. Ryan is physically able and fully independent for personal care. He engages positively with music and creative digital work, which form the basis of his transition aspirations.
AR
Aisha Rahman · Aisha ENGAGEMENT MODEL
Special School · KS2 · Pathway Four · Sensory & Physical
Load →
Aisha is a Year 4 student who presents with profound and multiple learning difficulties and is assessed on the Engagement Model. She has no formal communication system and expresses herself through pleasure and distress responses. Aisha requires 2:1 support at all times and is PEG fed with a full IHP covering seizure management and postural care. She is most responsive in calm, familiar environments and engages positively with music and gentle sensory activities.
LO
Liam Okafor · Liam ENGAGEMENT MODEL
Special School · KS3 · Pathway Three · Communication & Interaction
Load →
Liam is a Year 8 student who presents with autism and associated learning difficulties and is assessed on the Engagement Model. He has no formal communication system in place — a SALT assessment is currently pending. Liam is physically able but requires 1:1 support throughout the day due to significant anxiety around change and limited safety awareness. He responds well to object-based routines and water-based sensory activities, and a communication passport is currently being developed.
PS
Priya Sharma · Priya
Resourced Provision · KS4 · Pathway Two · Communication & Interaction
Load →
Priya is a Year 10 student who presents with autism and ADHD. She is placed in a resourced provision attached to a mainstream school and accesses some mainstream lessons with support. Priya is academically strong but experiences significant anxiety, sensory processing difficulties and challenges with executive function. She is self-aware about her diagnosis and engages well with strategies when they are explained to her. She has a clear aspiration toward further education in STEM.
All profiles are fictional and do not represent real pupils.
J
Coming Soon
About Jack Flanagan
A proper about page is on the way — the story behind Snapshot, the thinking that went into it, and what comes next.
const TAB_IDS = ["snapshot","summary","guide","faq","myschool","demo","about"];
function switchTab(t) {
TAB_IDS.forEach(id => {
document.getElementById("tab-"+id).classList.toggle("active", id===t);
document.querySelectorAll(".tab-btn").forEach(b => {
if(b.textContent.trim().toLowerCase()===id) b.classList.toggle("active", id===t);
});
});
if(t==="summary") { updateSummaryHeader(); renderSummary(); }
}
// ── DOMAIN DATA ──
const DOMAIN_DEFS = [
{
key:"comm", label:"Communication & Interaction", color:"#38BDF8",
subdomains:[
{key:"howComm", label:"How they communicate", type:"descriptor", options:[
{score:1, label:"Verbal — clear and functional"},
{score:2, label:"Verbal — limited, delayed or unclear"},
{score:3, label:"Verbal with support (symbols, visuals, Signalong/BSL)"},
{score:4, label:"AAC device (low or high tech)"},
{score:4, label:"Non-verbal — gesture, eye pointing, behaviour"},
{score:5, label:"No reliable communication method"},
]},
{key:"understanding", label:"Understanding", type:"descriptor", options:[
{score:1, label:"Understands verbal language well"},
{score:2, label:"Needs simple language and short instructions"},
{score:3, label:"Needs visual support alongside verbal instruction"},
{score:4, label:"Limited understanding — single words or objects of reference"},
{score:5, label:"Minimal or no reliable understanding"},
]},
{key:"commSupport", label:"Communication support required", type:"scale",
labels:["A","B","C","D","E"],
descs:["Good communication practice sufficient","Visual timetables and symbols in environment","Individual communication passport or system in place","Consistent 1:1 adult to facilitate all communication","Specialist SALT and fully bespoke system required"]
},
]
},
{
key:"cog", label:"Cognition & Learning", color:"#7c3aed",
subdomains:[
{key:"cogRoute", label:"Assessment route", type:"route"},
{key:"yearGroup", label:"Pupil year group", type:"nc_year_group", routeA:true},
{key:"ncEnglish", label:"English — currently working at", type:"nc_level", subject:"English", routeA:true},
{key:"ncMaths", label:"Maths — currently working at", type:"nc_level", subject:"Maths", routeA:true},
{key:"learningSupport", label:"Learning support needed", type:"scale", routeA:true,
labels:["A","B","C","D","E"],
descs:["Independent with minimal adult support","Needs differentiated resources and regular prompting","Needs adult scaffolding throughout all activities","Requires fully adapted and personalised curriculum","Pre-formal or sensory curriculum — Engagement Model"]
},
{key:"exploration", label:"Exploration", type:"engagement", routeB:true},
{key:"realisation", label:"Realisation", type:"engagement", routeB:true},
{key:"anticipation", label:"Anticipation", type:"engagement", routeB:true},
{key:"persistence", label:"Persistence", type:"engagement", routeB:true},
{key:"initiation", label:"Initiation", type:"engagement", routeB:true},
]
},
{
key:"semh", label:"Social, Emotional & Mental Health", color:"#10B981",
subdomains:[
{key:"emotionalWellbeing", label:"Emotional wellbeing", type:"descriptor", options:[
{score:1, label:"Generally positive — resilient and settled"},
{score:2, label:"Some difficulties — periods of low mood or anxiety"},
{score:3, label:"Regular difficulties — impacts daily school life"},
{score:4, label:"Significant difficulties — frequent crisis points"},
{score:5, label:"Complex or acute needs — multi-agency involvement"},
]},
{key:"semhSupport", label:"Support currently in place", type:"descriptor", options:[
{score:1, label:"Universal — good relationships and positive environment"},
{score:2, label:"Targeted — pastoral support or nurture provision"},
{score:3, label:"Specialist — CAMHS or external agency involved"},
{score:4, label:"Intensive — crisis planning or risk management in place"},
{score:5, label:"Intensive multi-agency — complex coordinated support"},
]},
{key:"regulation", label:"Emotional regulation", type:"scale",
labels:["A","B","C","D","E"],
descs:["Self-regulates well — minimal adult support","Usually manages with adult prompting at key points","Regularly needs adult co-regulation","Frequently dysregulated — needs intensive adult support","Requires consistent 1:1 co-regulation throughout the day"]
},
{key:"anxiety", label:"Anxiety", type:"scale",
labels:["A","B","C","D","E"],
descs:["Minimal anxiety — low day-to-day impact","Occasional low-level responses — generally self-resolving","Regular anxiety — requires adult de-escalation","Frequent significant anxiety — planned intervention required","At times of distress requires planned physical intervention from RPI-trained staff"]
},
{key:"socialComm", label:"Social communication", type:"scale",
labels:["A","B","C","D","E"],
descs:["Builds and maintains peer relationships confidently","Some social difficulties — generally positive relationships","Limited peer relationships — frequently misreads situations","Unable to form peer relationships — very limited social awareness","Requires intensive adult facilitation for all social interactions"]
},
]
},
{
key:"sensory", label:"Sensory & Physical", color:"#F59E0B",
subdomains:[
{key:"mobility", label:"Mobility", type:"descriptor", options:[
{score:1, label:"Fully ambulant — no physical needs"},
{score:2, label:"Ambulant with support — monitoring or fatigue management"},
{score:2, label:"Walking frame or crutches — independent with aids"},
{score:3, label:"Manual wheelchair — self propelling"},
{score:4, label:"Manual wheelchair — needs pushing"},
{score:3, label:"Powered wheelchair — independent"},
{score:4, label:"Powered wheelchair — needs assistance or adapted controls"},
{score:5, label:"Fixed specialist seating — cannot self propel"},
{score:5, label:"ACHEEVA bed user — fully dependent for all movement"},
]},
{key:"transfers", label:"Transfers", type:"descriptor", options:[
{score:1, label:"No transfer needs"},
{score:2, label:"Can transfer with verbal prompting"},
{score:3, label:"Physical assistance required — one person"},
{score:4, label:"Physical assistance required — two person"},
{score:5, label:"Hoist required — manual handling plan in place"},
]},
{key:"postural", label:"Postural needs", type:"descriptor", options:[
{score:1, label:"No postural support needed"},
{score:2, label:"Some positioning support during activities"},
{score:3, label:"Specialist seating or cushioning required"},
{score:5, label:"Full postural management programme in place"},
]},
{key:"fatigue", label:"Fatigue", type:"scale",
labels:["A","B","C","D","E"],
descs:["No fatigue issues","Tires toward end of day","Regular rest breaks needed","Significant fatigue — timetable adapted","Medical fatigue condition — specific management plan"]
},
{key:"sensoryProcessing", label:"Sensory processing", type:"scale",
labels:["A","B","C","D","E"],
descs:["Minimal sensory difficulty","Some sensitivities managed with minor adaptations","Regular sensory difficulties — planned adaptations and breakout space needed","Frequently overwhelmed — significant modifications required","Requires carefully designed low-stimulus environment and OT involvement"]
},
]
},
{
key:"medical", label:"Health", color:"#f87171",
subdomains:[
{key:"medication", label:"Medication during school day", type:"yesno"},
{key:"epilepsy", label:"Epilepsy", type:"descriptor", options:[
{score:1, label:"No epilepsy"},
{score:2, label:"Diagnosed — currently controlled"},
{score:3, label:"Diagnosed — occasional seizures at school"},
{score:4, label:"Diagnosed — regular seizures — emergency protocol in place"},
{score:5, label:"Complex epilepsy — continuous monitoring and specialist protocol required"},
]},
{key:"feeding", label:"Feeding needs", type:"descriptor", options:[
{score:1, label:"Independent — no support needed"},
{score:2, label:"Needs prompting or supervision at mealtimes"},
{score:3, label:"Physical assistance required at mealtimes"},
{score:3, label:"Modified diet or texture requirements"},
{score:4, label:"SALT involved in feeding plan"},
{score:5, label:"PEG or gastrostomy feeding"},
]},
{key:"ehcpPlan", label:"Individual Healthcare Plan in place", type:"yesno"},
]
},
{
key:"independence", label:"Life Skills & Independence", color:"#A78BFA",
subdomains:[
{key:"staffRatio", label:"Staffing ratio required", type:"descriptor", options:[
{score:1, label:"Whole class support sufficient — teacher led"},
{score:2, label:"Small group support — TA involvement"},
{score:3, label:"Regular 1:1 check-ins throughout the day"},
{score:4, label:"1:1 support at all times"},
{score:5, label:"2:1 support at all times"},
{score:5, label:"2:1 plus specialist equipment or protocols"},
]},
{key:"movingAround", label:"Moving around school", type:"descriptor", options:[
{score:1, label:"Independent — moves freely without support"},
{score:2, label:"Independent within familiar routes"},
{score:3, label:"Needs adult escort between lessons"},
{score:4, label:"1:1 escort at all times"},
{score:5, label:"Cannot access corridor or communal areas without full support"},
]},
{key:"safetyAwareness", label:"Safety awareness", type:"descriptor", options:[
{score:1, label:"Good safety awareness — understands risk"},
{score:2, label:"Some awareness — occasional reminders needed"},
{score:3, label:"Limited awareness — needs constant supervision"},
{score:4, label:"No safety awareness — presents risk to self"},
{score:5, label:"Presents risk to self and others — behaviour support plan in place"},
]},
{key:"communityAccess", label:"Community access", type:"descriptor", options:[
{score:1, label:"Independent in community"},
{score:2, label:"Supported in community — 1:1"},
{score:3, label:"Community access with full adult supervision and planning"},
{score:4, label:"Community access not currently possible without specialist support"},
{score:5, label:"No community access at this time"},
]},
{key:"personalCare", label:"Personal care", type:"scale",
labels:["A","B","C","D","E"],
descs:["Manages all personal care independently","Occasional prompting for hygiene or eating routines","Regular support needed — close supervision at mealtimes","High level of adult assistance — 1:1 required at mealtimes","Requires full adult assistance for all personal care including specialist feeding support"]
},
]
},
{
key:"destinations", label:"Destinations", color:"#f472b6",
subdomains:[
{key:"independence", label:"Independent living", type:"transition",
currentDescs:[
"Building strong daily living skills — independence is developing well",
"Developing daily living skills with support — making good progress",
"Daily living skills emerging — requires structured programme to develop",
"Limited daily living skills — high level of adult support across all routines",
"Fully dependent across all daily living — pre-formal skills development needed"
]
},
{key:"communityAccess", label:"Community participation", type:"transition",
currentDescs:[
"Accesses community confidently — uses transport, attends activities, navigates independently",
"Accesses community with some support — building toward independence",
"Community access with adult support — familiar environments and planned activities",
"Limited community access — 1:1 support and significant planning required",
"Community access not currently possible without specialist support"
]
},
{key:"takingControl", label:"Taking control", type:"transition",
currentDescs:[
"Strong self-advocacy — expresses preferences, makes choices, directs support confidently",
"Developing self-advocacy — makes choices with support and guidance",
"Supported decision-making — needs structured support to express preferences",
"Limited self-direction — relies on familiar adults for most decisions",
"Full adult facilitation required — communication of preferences is emerging"
]
},
{key:"takingPart", label:"Taking part", type:"transition",
currentDescs:[
"Engaged in learning and activity — working toward meaningful occupation post-18",
"Engaged with support — developing skills for future employment or structured activity",
"Participation with adult facilitation — building foundations for structured activity",
"Emerging engagement — accessing structured sessions with high adult input",
"Pre-participation — sensory and relationship-based provision forming the foundation"
]
},
]
},
{
key:"behaviour", label:"Regulation & Anxiety Response", color:"#fb923c",
subdomains:[
{key:"howDistress", label:"How anxiety and dysregulation present", type:"descriptor", options:[
{score:1, label:"Verbal — communicates anxiety or distress clearly and directly"},
{score:2, label:"Mood and engagement shift — changes in pace, quietness or withdrawal signal rising anxiety"},
{score:3, label:"Body language and physical proximity — facial expression, posture and movement communicate how they are feeling"},
{score:4, label:"Heightened responses — increased volume, refusal or leaving spaces communicate overwhelming distress"},
{score:5, label:"Physical communication of distress — self-directed or other-directed behaviour communicates extreme dysregulation and requires a planned compassionate response"},
]},
{key:"triggers", label:"Known triggers", type:"descriptor", options:[
{score:1, label:"No consistent triggers identified — generally responds well to everyday demands"},
{score:2, label:"Some triggers identified — manageable with awareness, flexibility and minor adjustments"},
{score:3, label:"Clear triggers known — timetable, environment and transitions are proactively planned around them"},
{score:4, label:"Frequent or unpredictable triggers — daily proactive planning and demand-awareness essential"},
{score:5, label:"Triggers are pervasive and demand-related — a demand avoidance or PBS profile is in place"},
]},
{key:"earlyWarning", label:"Early warning signs", type:"descriptor", options:[
{score:1, label:"No significant pre-escalation pattern — moves between calm and resolved with little transition"},
{score:2, label:"Subtle early signs visible to familiar adults — reduced eye contact, quieter, increased movement"},
{score:3, label:"Clear early warning signs known to staff — pacing, repetitive language, self-stimulatory behaviour"},
{score:4, label:"Early warning window is short — adults must notice and respond quickly to prevent escalation"},
{score:5, label:"Early warning signs are minimal or absent — dysregulation can be sudden and intense"},
]},
{key:"deEscalation", label:"Supporting through dysregulation", type:"descriptor", options:[
{score:1, label:"Calm adult acknowledgement is enough — young person finds their way back to calm quickly"},
{score:2, label:"Reduced demands, space and a warm, non-judgmental adult presence are effective"},
{score:3, label:"Specific co-regulation strategies required — named adult, quiet space, sensory tools or known script"},
{score:4, label:"Intensive, consistent co-regulation needed — 1:1 with a trusted adult using an agreed, rehearsed approach"},
{score:5, label:"Specialist response required — only specifically trained staff should support during peak distress; written protocol in place"},
]},
{key:"recovery", label:"Recovery and return to calm", type:"descriptor", options:[
{score:1, label:"Recovers quickly and independently — ready to re-engage within a short time"},
{score:2, label:"Needs some time and space — usually returns to calm with light, non-directive support"},
{score:3, label:"Structured recovery needed — familiar adult, quiet environment and a planned, gradual return"},
{score:4, label:"Recovery takes significant time — adult support is needed throughout before re-engagement is possible"},
{score:5, label:"Recovery can extend across the session or day — an individual recovery and reintegration plan is essential"},
]},
{key:"regulationSupport", label:"Level of regulation support required", type:"scale",
labels:["A","B","C","D","E"],
descs:[
"Universal — warm relationships, predictable routine and a calm, low-demand environment are sufficient",
"Targeted — proactive strategies in place; familiar adults ready to adjust and support at key moments",
"Specialist — individual regulation plan in place; environment, staffing and timetable adapted accordingly",
"Intensive — full Positive Behaviour Support plan; consistent, rehearsed approach from all adults every day",
"Specialist restrictive — written physical intervention protocol; multi-agency oversight; compassionate, rights-based approach central to all planning"
]
},
]
},
];
// ── STATE ──
let scores = {};
let subScores = {};
let yesNoState = {};
let transitionState = {}; // {domainKey.subKey: {current:0, goal:0, flags:[], notes:''}}
let ncData = {yearGroup:null, ncEnglish:null, ncMaths:null};
let cogRoute = 'A';
let photoDataUrl = "";
let currentName = "";
let selectedSetting = "", selectedKS = "", selectedNeed = "";
let selectedPathway = "", selectedClass = "";
let demoActive = false, demoWho = '';
// Initialize scores
DOMAIN_DEFS.forEach(d => {
scores[d.key] = 0;
d.subdomains.forEach(s => { subScores[d.key+'.'+s.key] = 0; });
});
// ── WHEEL DRAWING ──
const INT = 600;
const wheelCanvas = document.createElement('canvas');
wheelCanvas.id = 'wheelCanvas'; wheelCanvas.style.display='none';
document.body.appendChild(wheelCanvas);
wheelCanvas.width = INT; wheelCanvas.height = INT;
const ctx = wheelCanvas.getContext('2d');
const summaryCanvas = document.getElementById('summaryCanvas');
summaryCanvas.width = INT; summaryCanvas.height = INT;
const sdw = 360;
summaryCanvas.style.width = sdw+'px'; summaryCanvas.style.height = sdw+'px';
const sctx = summaryCanvas.getContext('2d');
function drawWheelOnCtx(c, forPDF, type) {
const cx = INT/2, cy = INT/2;
const outerR = INT * 0.34; // smaller — leaves room for labels
const innerR = INT * 0.12;
const bandR = (outerR - innerR) / 5;
const labelR = INT * 0.44; // labels further out, never clipped
const n = DOMAIN_DEFS.length;
const bg = forPDF ? '#ffffff' : '#0e1016';
const divider = forPDF ? '#ffffff' : '#0e1016';
c.clearRect(0, 0, INT, INT);
if(type === 'radar') {
// ── RADAR WHEEL ──
const gridColor = forPDF ? '#e5e7eb' : '#252836';
const axisColor = forPDF ? '#d1d5db' : '#374151';
// Draw 5 grid polygons
for(let band = 1; band <= 5; band++) {
const r = innerR + band * bandR;
c.beginPath();
for(let i = 0; i < n; i++) {
const angle = (i * (360/n) - 90) * Math.PI/180;
const px = cx + r * Math.cos(angle);
const py = cy + r * Math.sin(angle);
i === 0 ? c.moveTo(px, py) : c.lineTo(px, py);
}
c.closePath();
c.strokeStyle = gridColor; c.lineWidth = band === 5 ? 1.5 : 1; c.stroke();
}
// Axis lines
for(let i = 0; i < n; i++) {
const angle = (i * (360/n) - 90) * Math.PI/180;
c.beginPath();
c.moveTo(cx, cy);
c.lineTo(cx + outerR * Math.cos(angle), cy + outerR * Math.sin(angle));
c.strokeStyle = axisColor; c.lineWidth = 1; c.stroke();
}
// Data polygon
const pts = DOMAIN_DEFS.map((d, i) => {
const sc = scores[d.key] || 0;
const r = sc > 0 ? innerR + sc * bandR : innerR;
const angle = (i * (360/n) - 90) * Math.PI/180;
return [cx + r * Math.cos(angle), cy + r * Math.sin(angle)];
});
// Fill
c.beginPath();
pts.forEach(([px, py], i) => i === 0 ? c.moveTo(px, py) : c.lineTo(px, py));
c.closePath();
c.fillStyle = '#5B6CF9'; c.globalAlpha = 0.15; c.fill(); c.globalAlpha = 1;
// Stroke
c.beginPath();
pts.forEach(([px, py], i) => i === 0 ? c.moveTo(px, py) : c.lineTo(px, py));
c.closePath();
c.strokeStyle = '#f5c842'; c.lineWidth = 2.5; c.stroke();
// Dots
DOMAIN_DEFS.forEach((d, i) => {
const [px, py] = pts[i];
const sc = scores[d.key] || 0;
if(sc > 0) {
c.beginPath(); c.arc(px, py, INT*0.016, 0, Math.PI*2);
c.fillStyle = d.color; c.fill();
}
});
// Domain labels — use labelR so they never clip
DOMAIN_DEFS.forEach((d, i) => {
const angle = (i * (360/n) - 90) * Math.PI/180;
const lx = cx + labelR * Math.cos(angle);
const ly = cy + labelR * Math.sin(angle);
c.fillStyle = d.color;
c.font = `bold ${INT*0.030}px Arial`;
c.textAlign = 'center'; c.textBaseline = 'middle';
const shortLabels = {comm:'Comms',cog:'Cog',semh:'SEMH',sensory:'Sensory',medical:'Health',independence:'Life Skills',destinations:'Dest.',behaviour:'Regulation'};
c.fillText(shortLabels[d.key], lx, ly);
});
// A-E ring labels — small, between axis and first segment
const lblAngle = ((-90) + (360/n)*0.5) * Math.PI/180;
['A','B','C','D','E'].forEach((lbl, i) => {
const r = innerR + (i + 0.5) * bandR;
const lx = cx + r * Math.cos(lblAngle);
const ly = cy + r * Math.sin(lblAngle);
c.fillStyle = forPDF ? '#aaa' : '#4b5563';
c.font = `${INT*0.026}px Arial`;
c.textAlign = 'center'; c.textBaseline = 'middle';
c.fillText(lbl, lx, ly);
});
// Centre dot
c.beginPath(); c.arc(cx, cy, INT*0.016, 0, Math.PI*2);
c.fillStyle = '#f5c842'; c.fill();
} else {
// ── SNAPSHOT WHEEL ──
// Step 1: base segments — always visible, vibrant enough to read
DOMAIN_DEFS.forEach((d, i) => {
const startAngle = (i * (360/n) - 90) * Math.PI/180;
const endAngle = ((i+1) * (360/n) - 90) * Math.PI/180;
c.beginPath();
c.moveTo(cx + innerR*Math.cos(startAngle), cy + innerR*Math.sin(startAngle));
c.arc(cx, cy, outerR, startAngle, endAngle);
c.arc(cx, cy, innerR, endAngle, startAngle, true);
c.closePath();
c.fillStyle = d.color;
c.globalAlpha = forPDF ? 0.20 : 0.45;
c.fill(); c.globalAlpha = 1;
});
// Step 2: scored fill — single solid shape from inner to score level, clean
DOMAIN_DEFS.forEach((d, i) => {
const startAngle = (i * (360/n) - 90) * Math.PI/180;
const endAngle = ((i+1) * (360/n) - 90) * Math.PI/180;
const sc = scores[d.key] || 0;
if(sc === 0) return;
const filledR = innerR + sc * bandR;
c.beginPath();
c.moveTo(cx + innerR*Math.cos(startAngle), cy + innerR*Math.sin(startAngle));
c.arc(cx, cy, filledR, startAngle, endAngle);
c.arc(cx, cy, innerR, endAngle, startAngle, true);
c.closePath();
c.fillStyle = d.color;
c.globalAlpha = forPDF ? 0.75 : 0.88;
c.fill(); c.globalAlpha = 1;
});
// Ring borders — subtle, just to show band lines
for(let band = 1; band <= 5; band++) {
const r = innerR + band * bandR;
c.beginPath(); c.arc(cx, cy, r, 0, Math.PI*2);
c.strokeStyle = divider;
c.globalAlpha = band === 5 ? 1 : 0.6;
c.lineWidth = band === 5 ? 1.5 : 0.5; c.stroke();
c.globalAlpha = 1;
}
// Segment dividers
for(let i = 0; i < n; i++) {
const angle = (i * (360/n) - 90) * Math.PI/180;
c.beginPath();
c.moveTo(cx + innerR*Math.cos(angle), cy + innerR*Math.sin(angle));
c.lineTo(cx + outerR*Math.cos(angle), cy + outerR*Math.sin(angle));
c.strokeStyle = divider; c.lineWidth = 2; c.stroke();
}
// Domain labels — snug against the wheel
const shortLabels = {comm:'Comms',cog:'Cog',semh:'SEMH',sensory:'Sensory',medical:'Health',independence:'Life Skills',destinations:'Dest.',behaviour:'Regulation'};
DOMAIN_DEFS.forEach((d, i) => {
const midAngle = ((i + 0.5) * (360/n) - 90) * Math.PI/180;
const lx = cx + (outerR + INT*0.065) * Math.cos(midAngle);
const ly = cy + (outerR + INT*0.065) * Math.sin(midAngle);
c.fillStyle = d.color;
c.font = `bold ${INT*0.026}px Arial`;
c.textAlign = 'center'; c.textBaseline = 'middle';
c.fillText(shortLabels[d.key], lx, ly);
});
// Inner circle
c.beginPath(); c.arc(cx, cy, innerR, 0, Math.PI*2);
c.fillStyle = bg; c.fill();
c.beginPath(); c.arc(cx, cy, innerR, 0, Math.PI*2);
c.strokeStyle = '#f5c842'; c.lineWidth = 3; c.stroke();
// Person icon — matches logo proportions exactly
c.fillStyle = '#f5c842';
const headR = innerR * 0.285;
const headY = cy - innerR * 0.18;
const bodyR = innerR * 0.44;
const bodyY = cy + innerR * 0.30;
c.beginPath(); c.arc(cx, headY, headR, 0, Math.PI*2); c.fill();
c.beginPath(); c.arc(cx, bodyY, bodyR, Math.PI, 0); c.fill();
}
}
let wheelType = 'snapshot'; // 'snapshot' or 'radar'
function drawWheel() {
drawWheelOnCtx(ctx, false, wheelType);
drawWheelOnCtx(sctx, false, wheelType);
}
// ── SCORE CALCULATION ──
function calcDomainScore(domainKey) {
const def = DOMAIN_DEFS.find(d => d.key === domainKey);
const scoredSubs = [];
def.subdomains.forEach(s => {
const sk = domainKey+'.'+s.key;
const v = subScores[sk] || 0;
if(s.type === 'route') return;
if(s.type === 'transition') {
const ts = transitionState[domainKey+'.'+s.key];
if(ts && ts.current > 0) scoredSubs.push(ts.current);
return;
}
if(s.routeA && cogRoute !== 'A') return;
if(s.routeB && cogRoute !== 'B') return;
if(v > 0) scoredSubs.push(v);
});
if(scoredSubs.length === 0) return 0;
// Engagement Model route — minimum D (4)
if(domainKey === 'cog' && cogRoute === 'B') {
const sorted = [...scoredSubs].sort((a,b) => b-a);
const weights = [0.5, 0.3, 0.15, 0.04, 0.01];
let total = 0, wSum = 0;
sorted.forEach((v, i) => { const w = weights[i]||0.01; total += v*w; wSum += w; });
const raw = Math.round(total/wSum);
return Math.max(4, Math.min(5, raw)); // floor of D
}
// Sort highest first
scoredSubs.sort((a,b) => b-a);
// Hard rules
const hasE = scoredSubs.some(v => v === 5);
const highCount = scoredSubs.filter(v => v >= 4).length;
if(highCount >= 2) return 5;
if(hasE) return Math.max(4, scoredSubs[0]);
// Weighted top-heavy
const weights = [0.5, 0.3, 0.15, 0.04, 0.01];
let total = 0, wSum = 0;
scoredSubs.forEach((v, i) => { const w = weights[i]||0.01; total += v*w; wSum += w; });
return Math.min(5, Math.max(1, Math.round(total/wSum)));
}
function updateDomainScore(domainKey) {
const def = DOMAIN_DEFS.find(d=>d.key===domainKey);
const card = document.getElementById('dcard-'+domainKey);
// Calculate score from all currently set subScores
let sc = calcDomainScore(domainKey);
// Auto-fill only unset scales (score === 0) based on calculated score
if(card && sc > 0) {
let filled = false;
def.subdomains.forEach(sub => {
if(sub.type !== 'scale') return;
if(sub.routeA && cogRoute !== 'A') return;
if(sub.routeB && cogRoute !== 'B') return;
const sk = domainKey+'.'+sub.key;
if((subScores[sk]||0) === 0) {
subScores[sk] = sc;
filled = true;
const btns = Array.from(card.querySelectorAll('.scale-desc-btn,.scale-btn')).filter(b =>
(b.getAttribute('onclick')||'').includes("'"+sub.key+"'")
);
btns.forEach((b) => {
const bScore = parseInt(b.getAttribute('data-score'));
if(bScore === sc) {
b.classList.add('selected');
b.style.borderColor = def.color;
}
});
}
});
if(filled) sc = calcDomainScore(domainKey);
}
scores[domainKey] = sc;
const badge = document.getElementById('badge-'+domainKey);
if(badge) {
if(sc > 0) {
const letter = 'ABCDE'[sc-1];
const label = ['Emerging','Developing','Established','Complex','Specialist'][sc-1];
const badgeColors = {1:'#4ade80',2:'#a3e635',3:'#f59e0b',4:'#f97316',5:'#ef4444'};
badge.innerHTML = `✓${letter}${label}`;
badge.style.cssText = `background:${def.color}18;border:1px solid ${def.color}55;padding:3px 12px;border-radius:12px;min-width:120px;text-align:center;`;
badge.classList.add('scored');
} else {
badge.innerHTML = '—';
badge.removeAttribute('style');
badge.classList.remove('scored');
}
}
drawWheel();
updateSummaryHeader();
}
// ── DESCRIPTOR SELECT ──
function setDescriptor(domainKey, subKey, score, btn) {
const sk = domainKey+'.'+subKey;
subScores[sk] = score;
// Deselect siblings
btn.closest('.desc-grid').querySelectorAll('.desc-btn').forEach(b => b.classList.remove('selected'));
btn.classList.add('selected');
const def = DOMAIN_DEFS.find(d=>d.key===domainKey);
btn.style.borderColor = def.color;
btn.closest('.desc-grid').querySelectorAll('.desc-btn:not(.selected)').forEach(b => b.style.borderColor='');
updateDomainScore(domainKey);
runCrossChecks(domainKey, subKey, score);
}
// ── CROSS-CHECK RULES ENGINE ──
function lockDescRange(domainKey, subKey, minScore, maxScore, reason) {
const card = document.getElementById('dcard-'+domainKey);
if(!card) return;
const btns = Array.from(card.querySelectorAll('.desc-btn')).filter(b =>
(b.getAttribute('onclick')||'').includes("'"+subKey+"'")
);
let resetNeeded = false;
btns.forEach(b => {
const m = (b.getAttribute('onclick')||'').match(/,(\d+),/);
if(!m) return;
const s = parseInt(m[1]);
if(s < minScore || s > maxScore) {
if(b.classList.contains('selected')) { b.classList.remove('selected'); b.style.borderColor=''; resetNeeded=true; }
b.disabled = true; b.style.opacity='0.22'; b.style.cursor='not-allowed';
b.setAttribute('data-locked', reason);
b.setAttribute('data-orig-onclick', b.getAttribute('onclick'));
b.setAttribute('onclick', 'handleLockedClick(event,this)');
} else {
unlockDescBtn(b);
}
});
if(resetNeeded) showCrossNote(domainKey, subKey, reason);
}
function lockScaleRange(domainKey, subKey, minScore, maxScore, reason) {
const card = document.getElementById('dcard-'+domainKey);
if(!card) return;
const btns = Array.from(card.querySelectorAll('.scale-desc-btn')).filter(b =>
(b.getAttribute('onclick')||'').includes("'"+subKey+"'")
);
let resetNeeded = false;
btns.forEach(b => {
const s = parseInt(b.getAttribute('data-score')||'0');
if(s < minScore || s > maxScore) {
if(b.classList.contains('selected')) { b.classList.remove('selected'); b.style.borderColor=''; resetNeeded=true; }
b.disabled = true; b.style.opacity='0.22'; b.style.cursor='not-allowed';
b.setAttribute('data-locked', reason);
b.setAttribute('data-orig-onclick', b.getAttribute('onclick'));
b.setAttribute('onclick', 'handleLockedClick(event,this)');
} else {
unlockScaleBtn(b);
}
});
if(resetNeeded) showCrossNote(domainKey, subKey, reason);
}
function unlockDescBtn(b) {
b.disabled = false; b.style.opacity=''; b.style.cursor='';
if(b.getAttribute('data-orig-onclick')) { b.setAttribute('onclick', b.getAttribute('data-orig-onclick')); b.removeAttribute('data-orig-onclick'); }
b.removeAttribute('data-locked');
}
function unlockScaleBtn(b) {
b.disabled = false; b.style.opacity=''; b.style.cursor='';
if(b.getAttribute('data-orig-onclick')) { b.setAttribute('onclick', b.getAttribute('data-orig-onclick')); b.removeAttribute('data-orig-onclick'); }
b.removeAttribute('data-locked');
}
function unlockAllDesc(domainKey, subKey) {
const card = document.getElementById('dcard-'+domainKey);
if(!card) return;
Array.from(card.querySelectorAll('.desc-btn')).filter(b =>
(b.getAttribute('onclick')||'').includes("'"+subKey+"'") ||
(b.getAttribute('data-orig-onclick')||'').includes("'"+subKey+"'")
).forEach(b => unlockDescBtn(b));
}
function unlockAllScale(domainKey, subKey) {
const card = document.getElementById('dcard-'+domainKey);
if(!card) return;
Array.from(card.querySelectorAll('.scale-desc-btn')).filter(b =>
(b.getAttribute('onclick')||'').includes("'"+subKey+"'") ||
(b.getAttribute('data-orig-onclick')||'').includes("'"+subKey+"'")
).forEach(b => unlockScaleBtn(b));
}
function handleLockedClick(e, btn) {
e.stopPropagation(); e.preventDefault();
const reason = btn.getAttribute('data-locked') || 'Inconsistent with another selection';
if(confirm('This option may be inconsistent:\n\n"' + reason + '"\n\nOverride and select anyway?')) {
unlockDescBtn(btn); unlockScaleBtn(btn);
btn.click();
}
}
function showCrossNote(domainKey, subKey, reason) {
const card = document.getElementById('dcard-'+domainKey);
if(!card) return;
const btns = Array.from(card.querySelectorAll('.desc-btn,.scale-desc-btn')).filter(b =>
(b.getAttribute('onclick')||'').includes("'"+subKey+"'")
);
const ref = btns[0];
if(!ref) return;
const note = document.createElement('div');
note.style.cssText = 'font-size:.72rem;color:#f59e0b;background:#f59e0b12;border:1px solid #f59e0b33;border-radius:6px;padding:.35rem .75rem;margin:.3rem 0;';
note.textContent = '↺ ' + reason;
ref.closest('.subdomain').appendChild(note);
setTimeout(() => note.remove(), 4000);
}
function forceYesNo(domainKey, subKey, val, reason) {
const card = document.getElementById('dcard-'+domainKey);
if(!card) return;
const btn = Array.from(card.querySelectorAll('.yn-btn')).find(b =>
b.getAttribute('data-val')===val && (b.getAttribute('onclick')||'').includes("'"+subKey+"'")
);
if(btn && !btn.classList.contains('active')) { setYesNo(domainKey, subKey, val, btn); showCrossNote(domainKey, subKey, reason); }
// Lock the other
const other = Array.from(card.querySelectorAll('.yn-btn')).find(b =>
b.getAttribute('data-val')!=val && (b.getAttribute('onclick')||'').includes("'"+subKey+"'")
);
if(other) { other.disabled=true; other.style.opacity='0.22'; other.style.cursor='not-allowed'; other.setAttribute('data-locked', reason); }
}
function runCrossChecks(domainKey, subKey, score) {
// ═══ MOBILITY — anchor for transfers, postural, moving around, personal care, community ═══
if(domainKey==='sensory' && subKey==='mobility') {
unlockAllDesc('sensory','transfers');
unlockAllDesc('sensory','postural');
unlockAllDesc('independence','movingAround');
unlockAllScale('independence','personalCare');
unlockAllScale('destinations','communityAccess');
// Get selected text to distinguish options with same score
const card = document.getElementById('dcard-sensory');
const selectedBtn = card ? Array.from(card.querySelectorAll('.desc-btn.selected')).find(b =>
(b.getAttribute('onclick')||'').includes("'mobility'")) : null;
const selectedText = selectedBtn ? selectedBtn.textContent : '';
if(selectedText.includes('Fully ambulant')) {
lockDescRange('sensory','transfers',1,1,'Fully ambulant — no transfer needs');
lockDescRange('sensory','postural',1,2,'Fully ambulant — minimal postural support at most');
lockDescRange('independence','movingAround',1,2,'Fully ambulant — independent movement expected');
}
else if(selectedText.includes('Ambulant with support') || selectedText.includes('Walking frame')) {
lockDescRange('sensory','transfers',1,3,'Ambulant with aids — one-person assistance maximum');
lockDescRange('sensory','postural',1,3,'Ambulant — specialist seating maximum');
}
else if(selectedText.includes('self propelling') || selectedText.includes('Powered wheelchair — independent')) {
lockDescRange('sensory','postural',2,5,'Wheelchair user — some postural consideration required');
}
else if(selectedText.includes('needs pushing') || selectedText.includes('needs assistance')) {
lockDescRange('sensory','transfers',2,5,'Requires pushing — transfer support needed');
lockDescRange('sensory','postural',2,5,'Pushed wheelchair — postural support required');
lockDescRange('independence','movingAround',3,5,'Requires pushing — adult escort required');
}
else if(selectedText.includes('Fixed specialist')) {
lockDescRange('sensory','transfers',3,5,'Fixed seating — two-person assistance minimum');
lockDescRange('sensory','postural',4,5,'Fixed seating — full postural management required');
lockDescRange('independence','movingAround',4,5,'Fixed seating — 1:1 escort minimum');
lockScaleRange('independence','personalCare',3,5,'Fixed seating indicates significant personal care needs');
}
else if(selectedText.includes('ACHEEVA')) {
lockDescRange('sensory','transfers',5,5,'ACHEEVA bed — hoist essential, no other option is safe');
lockDescRange('sensory','postural',4,5,'ACHEEVA bed requires specialist postural management');
lockDescRange('independence','movingAround',5,5,'ACHEEVA bed — cannot access corridors without full support');
lockScaleRange('independence','personalCare',4,5,'ACHEEVA bed — full personal care support required');
lockDescRange('independence','staffRatio',4,6,'ACHEEVA bed — minimum 2:1 staffing required');
}
}
// ═══ STAFFING RATIO — drives safety awareness, community access ═══
if(domainKey==='independence' && subKey==='staffRatio') {
unlockAllDesc('independence','safetyAwareness');
unlockAllScale('destinations','communityAccess');
if(score===1) {
lockDescRange('independence','safetyAwareness',1,3,'Whole class support suggests reasonable safety awareness');
} else if(score===5||score===6) {
lockDescRange('independence','safetyAwareness',3,5,'2:1 ratio indicates significant safety awareness needs');
}
}
// ═══ EMOTIONAL WELLBEING — drives support in place ═══
if(domainKey==='semh' && subKey==='emotionalWellbeing') {
unlockAllDesc('semh','semhSupport');
if(score===1) {
lockDescRange('semh','semhSupport',1,2,'Good emotional wellbeing does not require intensive specialist support');
} else if(score===4||score===5) {
lockDescRange('semh','semhSupport',3,5,'Significant mental health needs require at least specialist involvement');
}
}
// ═══ REGULATION ↔ ANXIETY — neither can be extreme while other is minimal ═══
if(domainKey==='semh' && subKey==='regulation' && score===5) {
unlockAllScale('semh','anxiety');
lockScaleRange('semh','anxiety',2,5,'Intensive regulation needs — anxiety cannot be minimal');
}
if(domainKey==='semh' && subKey==='anxiety' && score===5) {
unlockAllScale('semh','regulation');
lockScaleRange('semh','regulation',2,5,'Intensive anxiety — regulation cannot be minimal');
}
// ═══ PERSONAL CARE → TRANSFERS floor ═══
if(domainKey==='independence' && subKey==='personalCare' && score===5) {
lockDescRange('sensory','transfers',3,5,'Full personal care assistance requires at least one-person transfer support');
}
// ═══ EPILEPSY complex → MEDICATION must be yes ═══
if(domainKey==='medical' && subKey==='epilepsy' && score>=4) {
forceYesNo('medical','medication','yes','Complex epilepsy requires medication management during the school day');
}
// ═══ PEG FEEDING → PERSONAL CARE minimum D ═══
if(domainKey==='medical' && subKey==='feeding' && score===5) {
unlockAllScale('independence','personalCare');
lockScaleRange('independence','personalCare',4,5,'PEG feeding requires high-level personal care support');
}
// ═══ TAKING CONTROL ↔ INDEPENDENCE destinations ═══
if(domainKey==='destinations' && subKey==='takingControl') {
unlockAllScale('destinations','independence');
if(score===1) {
lockScaleRange('destinations','independence',1,3,'Strong self-advocacy suggests realistic independence aspiration');
} else if(score===5) {
lockScaleRange('destinations','independence',3,5,'Full adult facilitation for decisions — supported living minimum');
}
}
}
// ── TRANSITION ──
function setTransition(tk, type, score, btn) {
if(!transitionState[tk]) transitionState[tk] = {current:0, goal:0, flags:[], notes:''};
transitionState[tk][type] = score;
// Visual update — deselect siblings in same grid
btn.closest('.desc-grid').querySelectorAll('.desc-btn').forEach(b => {
b.classList.remove('selected'); b.style.borderColor='';
});
btn.classList.add('selected');
btn.style.borderColor = type === 'current' ? '#34d399' : '#f5c842';
// Use current score to drive domain score (goal is aspirational, current drives the wheel)
const dk = tk.split('.')[0];
subScores[tk] = transitionState[tk].current || 0;
updateDomainScore(dk);
}
function setTransitionNotes(tk, val) {
if(!transitionState[tk]) transitionState[tk] = {current:0, goal:0, flags:[], notes:''};
transitionState[tk].notes = val;
}
// ── SCALE BUTTONS ──
function setScale(domainKey, subKey, score, btn) {
const sk = domainKey+'.'+subKey;
subScores[sk] = score;
const def = DOMAIN_DEFS.find(d=>d.key===domainKey);
const parent = btn.closest('.desc-grid') || btn.closest('.scale-row');
if(parent) {
parent.querySelectorAll('button').forEach(b => {
b.classList.remove('selected');
b.style.borderColor = '';
});
btn.classList.add('selected');
btn.style.borderColor = def.color;
}
updateDomainScore(domainKey);
runCrossChecks(domainKey, subKey, score);
}
// ── ENGAGEMENT MODEL ──
function setEngagement(domainKey, subKey, val, btn) {
const engScores = {emerging:1, developing:3, established:5};
subScores[domainKey+'.'+subKey] = engScores[val];
const def = DOMAIN_DEFS.find(d=>d.key===domainKey);
btn.closest('.eng-btns').querySelectorAll('.eng-btn').forEach(b => {
b.classList.toggle('active', b.dataset.val === val);
b.style.background = b.dataset.val === val ? def.color : '';
b.style.color = b.dataset.val === val ? '#0e1016' : '';
b.style.borderColor = b.dataset.val === val ? def.color : '';
});
updateDomainScore(domainKey);
}
// ── COGNITION ROUTE ──
function setCogRoute(route) {
cogRoute = route;
document.querySelectorAll('.route-btn').forEach(b => {
b.classList.toggle('selected', b.dataset.route === route);
});
document.getElementById('cogRouteA').style.display = route==='A' ? 'block' : 'none';
document.getElementById('cogRouteB').style.display = route==='B' ? 'block' : 'none';
// Engagement Model — auto-set minimum score of D
if(route === 'B') {
const warning = document.getElementById('engModelWarning');
if(warning) warning.style.display = 'block';
subScores['cog.ncEnglish'] = 0;
subScores['cog.ncMaths'] = 0;
} else {
const warning = document.getElementById('engModelWarning');
if(warning) warning.style.display = 'none';
}
updateDomainScore('cog');
}
// ── NC CALCULATION ──
const YEAR_GROUPS_BY_KS = {
'KS1': ['Year 1','Year 2'],
'KS2': ['Year 3','Year 4','Year 5','Year 6'],
'KS3': ['Year 7','Year 8','Year 9'],
'KS4': ['Year 10','Year 11'],
'KS5': ['Year 12','Year 13','Year 14'],
};
const ALL_YEAR_GROUPS = ['Year 1','Year 2','Year 3','Year 4','Year 5','Year 6','Year 7','Year 8','Year 9','Year 10','Year 11','Year 12','Year 13','Year 14'];
const NC_LEVELS = ['Year 1','Year 2','Year 3','Year 4','Year 5','Year 6','Below age expected levels'];
function calcNCGapScore(yearGroup, ncLevel) {
if(!yearGroup || !ncLevel) return 0;
if(ncLevel === 'Below age expected levels') return 5;
const ygNum = parseInt(yearGroup.replace('Year ',''));
const ncNum = parseInt(ncLevel.replace('Year ',''));
const gap = ygNum - ncNum;
if(gap <= 1) return 1;
if(gap <= 3) return 2;
if(gap <= 5) return 3;
if(gap <= 7) return 4;
return 5;
}
function calcNCScore() {
const yg = ncData.yearGroup;
const eng = ncData.ncEnglish;
const mth = ncData.ncMaths;
const engScore = calcNCGapScore(yg, eng);
const mthScore = calcNCGapScore(yg, mth);
if(!engScore && !mthScore) return 0;
if(!engScore) return mthScore;
if(!mthScore) return engScore;
// Weighted — highest gap gets 0.65, other gets 0.35
const high = Math.max(engScore, mthScore);
const low = Math.min(engScore, mthScore);
const weighted = high * 0.65 + low * 0.35;
// Hard rules — if either subject is E, minimum D overall
if(high === 5) return Math.max(4, Math.round(weighted));
return Math.min(5, Math.max(1, Math.round(weighted)));
}
function gapLabel(yearGroup, ncLevel) {
if(!yearGroup || !ncLevel) return '';
if(ncLevel === 'Below age expected levels') return 'Working below age expected levels — Level E';
const sc = calcNCGapScore(yearGroup, ncLevel);
const letters = ['A','B','C','D','E'];
return `Working at ${ncLevel} level — Level ${letters[sc-1]}`;
}
function selectKS(ks) {
document.querySelectorAll('#ksStageRow button').forEach(b => {
b.classList.toggle('selected', b.getAttribute('data-ks') === ks);
});
const validYears = YEAR_GROUPS_BY_KS[ks] || [];
document.querySelectorAll('#yearGroupGrid .sel-btn').forEach(b => {
const inKS = validYears.includes(b.getAttribute('data-year'));
b.style.display = inKS ? '' : 'none';
if(!inKS && b.classList.contains('selected')) {
b.classList.remove('selected');
ncData.yearGroup = null;
updateNCDisplay();
}
});
}
function selectYearGroup(year, btn) {
ncData.yearGroup = year;
document.querySelectorAll('#yearGroupGrid .sel-btn').forEach(b => b.classList.remove('selected'));
btn.classList.add('selected');
updateNCDisplay();
}
function updateNCDisplay() {
const engEl = document.getElementById('ncEngDisplay');
const mthEl = document.getElementById('ncMthDisplay');
const totalEl = document.getElementById('ncGapDisplay');
const yg = ncData.yearGroup;
if(engEl) {
const eng = ncData.ncEnglish;
engEl.textContent = eng && yg ? 'English: ' + gapLabel(yg, eng) : 'Select English level';
engEl.classList.toggle('scored', !!(eng && yg));
}
if(mthEl) {
const mth = ncData.ncMaths;
mthEl.textContent = mth && yg ? 'Maths: ' + gapLabel(yg, mth) : 'Select Maths level';
mthEl.classList.toggle('scored', !!(mth && yg));
}
const sc = calcNCScore();
subScores['cog.ncEnglish'] = calcNCGapScore(yg, ncData.ncEnglish);
subScores['cog.ncMaths'] = calcNCGapScore(yg, ncData.ncMaths);
if(totalEl) {
if(sc > 0) {
const letters = ['A','B','C','D','E'];
const labels = ['Emerging','Developing','Established','Complex','Specialist'];
totalEl.textContent = `Overall: Level ${letters[sc-1]} — ${labels[sc-1]}`;
totalEl.classList.add('scored');
} else {
totalEl.textContent = 'Select year group and NC levels above';
totalEl.classList.remove('scored');
}
}
updateDomainScore('cog');
}
// ── YES/NO ──
function setYesNo(domainKey, subKey, val, btn) {
yesNoState[domainKey+'.'+subKey] = val;
subScores[domainKey+'.'+subKey] = val === 'yes' ? 3 : 0;
const def = DOMAIN_DEFS.find(d=>d.key===domainKey);
btn.closest('.yesno-btns').querySelectorAll('.yn-btn').forEach(b => {
b.classList.toggle('active', b.dataset.val === val);
b.style.background = b.dataset.val === val ? (val==='yes' ? def.color : '#374151') : '';
b.style.color = b.dataset.val === val ? '#0e1016' : '';
b.style.borderColor = b.dataset.val === val ? (val==='yes' ? def.color : '#374151') : '';
});
updateDomainScore(domainKey);
runCrossChecks(domainKey, subKey, val==='yes' ? 3 : 0);
}
// ── BUILD DOMAIN CARDS ──
function buildDomainCards() {
const container = document.getElementById('domainCards');
DOMAIN_DEFS.forEach(def => {
const card = document.createElement('div');
card.className = 'domain-card';
card.id = 'dcard-'+def.key;
let bodyHTML = '';
def.subdomains.forEach(sub => {
if(sub.type === 'route') {
bodyHTML += `
Assessment route
⚠ Engagement Model selected — Cognition score automatically set to a minimum of D (High). This pupil is working below pre-key stage standards.
';
return;
}
const high = scored.filter(d=>scores[d.key]>=4);
const mod = scored.filter(d=>scores[d.key]===3);
let overview = `${name} has been profiled across ${scored.length} domain${scored.length!==1?'s':''}. `;
if(high.length>0) overview += `The areas of highest need are ${high.map(d=>d.label).join(', ')}. `;
if(mod.length>0) overview += `Moderate support is indicated in ${mod.map(d=>d.label).join(', ')}. `;
overview += `The support wheel provides an at-a-glance visual summary of ${name}'s profile.`;
const domains = scored.map(d => {
const sc = scores[d.key];
const levelLabel = 'ABCDE'[sc-1] + ' – ' + ['Emerging','Developing','Established','Complex','Specialist'][sc-1]+' support';
return `
${d.label}${levelLabel}
${generateDomainNarrative(d.key, name)}
`;
}).join('');
el.innerHTML = `
Overview
${overview}
Support Profile
${domains}
`;
}
function generateDomainNarrative(domainKey, name) {
const def = DOMAIN_DEFS.find(d=>d.key===domainKey);
const sc = scores[domainKey];
const level = ['minimal','low','moderate','high','intensive'][sc-1];
const selected = {};
def.subdomains.forEach(sub => {
const sk = domainKey+'.'+sub.key;
if(subScores[sk]>0) {
// Find selected descriptor label
if(sub.type==='descriptor') {
const btn = document.querySelector(`#dcard-${domainKey} .desc-btn.selected[onclick*="'${sub.key}'"]`);
if(btn) selected[sub.key] = btn.textContent;
}
}
});
const narratives = {
comm: () => {
const how = selected.howComm || '';
const und = selected.understanding || '';
const howClean = how ? how.charAt(0).toLowerCase() + how.slice(1) : '';
const undClean = und ? und.charAt(0).toLowerCase() + und.slice(1) : '';
const supportNote = {
1: 'Good universal communication practice is sufficient.',
2: 'Visual supports and clear, consistent language help significantly.',
3: `${name} benefits from an individual communication system used consistently by all adults.`,
4: `${name} needs a familiar adult to facilitate and support communication at all times.`,
5: `Specialist SALT input and a fully bespoke communication system are essential.`,
}[sc] || '';
return `${how ? `${name} ${howClean}.` : ''} ${und ? `When it comes to understanding, ${name} ${undClean.replace(/^[A-Za-z]/, c => c.toLowerCase())}.` : ''} ${supportNote} A consistent, total communication approach across all settings and adults is important.`.trim();
},
cog: () => {
if(cogRoute==='B') return `${name} is assessed using the Engagement Model. This reflects that subject-specific study is not yet the right fit — what matters most is rich, sensory, relationship-based learning across the five areas of engagement. Provision should be highly personalised and responsive to ${name}'s individual interests and responses.`;
const yg = ncData.yearGroup || '';
const engStr = ncData.ncEnglish ? `English at ${ncData.ncEnglish} level` : '';
const mathStr = ncData.ncMaths ? `Maths at ${ncData.ncMaths} level` : '';
const levels = [engStr, mathStr].filter(Boolean).join(' and ');
const gapSentence = yg && levels ? ` Currently in ${yg}, ${name} is working at ${levels}.` : '';
const scaffoldNote = {
1: `${name} works with good independence and needs minimal adult input.`,
2: `${name} benefits from differentiated resources and regular check-ins to stay on track.`,
3: `${name} needs adult scaffolding throughout learning activities to make progress.`,
4: `${name} requires a fully personalised curriculum with adapted materials and close adult support.`,
5: `${name} is working on a pre-formal curriculum — learning is sensory and experiential.`,
}[sc] || '';
return `${gapSentence} ${scaffoldNote} Planning and resources should be tailored to ${name}'s actual working levels, not year group expectations.`.trim();
},
semh: () => {
const ew = selected.emotionalWellbeing || '';
const sp = selected.semhSupport || '';
const ewClean = ew ? ew.charAt(0).toLowerCase() + ew.slice(1) : '';
const spClean = sp ? sp.charAt(0).toLowerCase() + sp.slice(1) : '';
const approachNote = {
1: `Positive relationships and a warm, consistent environment are the foundation.`,
2: `Pastoral check-ins and a trusted key adult make a real difference.`,
3: `${name} benefits most from calm, predictable routines and a small number of trusted adults.`,
4: `${name} needs planned, consistent co-regulation support and a clear crisis response plan.`,
5: `${name} requires an intensive, coordinated approach involving specialist services and careful daily planning.`,
}[sc] || '';
return `${ew ? `In terms of emotional wellbeing, ${name} is ${ewClean}.` : ''} ${sp ? `${name} is currently receiving ${spClean}.` : ''} ${approachNote} Consistency between adults and between home and school is essential for ${name}'s wellbeing.`.trim();
},
sensory: () => {
const mob = selected.mobility || '';
const mobClean = mob ? mob.charAt(0).toLowerCase() + mob.slice(1) : '';
const physNote = {
1: `No physical adaptations are needed.`,
2: `Minor adaptations and monitoring support ${name} well.`,
3: `${name} uses specialist equipment and benefits from a planned approach to movement and positioning.`,
4: `${name}'s physical needs require careful daily management, adapted equipment and regular review.`,
5: `${name} has the most complex physical needs — a full postural management programme, specialist equipment and detailed handling plans are essential.`,
}[sc] || '';
return `${mob ? `${name} ${mobClean}.` : ''} ${physNote} All staff working with ${name} should be familiar with any manual handling, equipment or movement plans in place.`.trim();
},
medical: () => {
const ep = selected.epilepsy || '';
const feed = selected.feeding || '';
const hasEp = ep && ep !== 'No epilepsy';
const hasFeed = feed && feed !== 'Independent — no support needed';
const medNote = {
1: `No significant health needs at this time.`,
2: `${name}'s health needs are well-managed with straightforward support in place.`,
3: `${name} has health needs that require planned adult support during the school day.`,
4: `${name}'s medical needs are significant — clear protocols, trained staff and daily management are essential.`,
5: `${name} has complex, high-priority health needs that require specialist knowledge and continuous monitoring.`,
}[sc] || '';
return `${hasEp ? `${name} has a diagnosis of epilepsy — ${ep.toLowerCase()}.` : ''} ${hasFeed ? `Regarding feeding, ${feed.toLowerCase()}.` : ''} ${medNote} All relevant healthcare plans should be accessible to every adult working with ${name} and reviewed regularly.`.trim();
},
destinations: () => {
const def = DOMAIN_DEFS.find(d=>d.key==='destinations');
const scored = def.subdomains.filter(sub => {
const ts = transitionState['destinations.'+sub.key];
return ts && ts.current > 0;
});
if(!scored.length) return `Transition planning for ${name} is underway. The goal is building a clear picture of what a good adult life looks like — across independence, community, self-direction and meaningful activity.`;
const intro = `Looking ahead, ${name}'s transition picture shows ${level} overall need across the four areas. `;
const sentences = scored.map(sub => {
const ts = transitionState['destinations.'+sub.key];
const desc = sub.currentDescs[ts.current-1] || '';
const notes = ts.notes ? ` ${ts.notes}` : '';
const openers = {
independence: 'When it comes to independence and daily living',
communityAccess: 'For getting out and about in the community',
takingControl: 'In terms of having a say and making choices',
takingPart: 'Around occupation, activity and purpose',
};
const opener = openers[sub.key] || sub.label;
return `${opener}: ${desc.charAt(0).toLowerCase()}${desc.slice(1)}.${notes}`;
});
return intro + sentences.join(' ');
},
independence: () => {
const ratio = selected.staffRatio || '';
const safety = selected.safetyAwareness || '';
const ratioClean = ratio ? ratio.charAt(0).toLowerCase() + ratio.slice(1) : '';
const safetyClean = safety ? safety.charAt(0).toLowerCase() + safety.slice(1) : '';
const indNote = {
1: `${name} is largely independent and needs minimal adult involvement in day-to-day tasks.`,
2: `${name} manages well with light adult support at key moments.`,
3: `${name} needs regular adult involvement throughout the day to stay safe and on track.`,
4: `${name} requires consistent 1:1 support throughout the school day.`,
5: `${name} needs 2:1 support at all times — staffing, risk assessments and protocols must reflect this.`,
}[sc] || '';
return `${ratio ? `${name} ${ratioClean}.` : ''} ${safety ? `Around safety, ${name} ${safetyClean}.` : ''} ${indNote} Staffing arrangements and any community access planning should always reflect ${name}'s current level of need.`.trim();
},
behaviour: () => {
const how = selected.howDistress || '';
const triggers = selected.triggers || '';
const warning = selected.earlyWarning || '';
const deesc = selected.deEscalation || '';
const recovery = selected.recovery || '';
const supportNote = {
1: `All behaviour is understood as communication. ${name} is well-supported by warm relationships, predictable routines and a calm environment — no specialist intervention is currently needed.`,
2: `All behaviour is understood as communication. ${name} benefits from adults who know their early signs and are ready to flex demands and offer support before anxiety builds.`,
3: `All behaviour is understood as communication. ${name} has an individual regulation plan — named adults, specific strategies and environmental adjustments are in place. Every adult working with ${name} must read and follow this consistently.`,
4: `All behaviour is understood as communication. ${name} needs a full Positive Behaviour Support plan applied consistently by all adults. The focus is always on understanding what ${name} is communicating, reducing anxiety at source, and supporting regulation — not managing behaviour.`,
5: `All behaviour is understood as communication. ${name} has a specialist response plan including a written physical intervention protocol. The approach must be compassionate, rights-based and focused entirely on ${name}'s safety and dignity. Multi-agency oversight is essential.`,
}[sc] || '';
return `${how ? `For ${name}, ${how.charAt(0).toLowerCase()+how.slice(1)}.` : ''} ${triggers && triggers !== 'No consistent triggers identified — generally responds well to everyday demands' ? `${triggers}.` : ''} ${warning && warning !== 'No significant pre-escalation pattern — moves between calm and resolved with little transition' ? `Early warning signs: ${warning.charAt(0).toLowerCase()+warning.slice(1)}.` : ''} ${deesc ? `When anxiety is high: ${deesc.charAt(0).toLowerCase()+deesc.slice(1)}.` : ''} ${recovery ? `Returning to calm: ${recovery.charAt(0).toLowerCase()+recovery.slice(1)}.` : ''} ${supportNote}`.trim().replace(/\s+/g,' ');
},
};
return (narratives[domainKey] && narratives[domainKey]()) || `${name} needs support in this area — speak to their key worker for more detail.`;
}
function silentClear() {
currentName=''; selectedSetting=''; selectedKS=''; selectedNeed='';
selectedPathway=''; selectedClass='';
photoDataUrl='';
document.getElementById('pupilName').value='';
document.getElementById('preferredName').value='';
document.getElementById('teacherName').value='';
document.getElementById('completionDate').value='';
document.getElementById('additionalInfo').value='';
const pp=document.getElementById('photoPreview'); pp.style.display='none'; pp.src='';
document.getElementById('photoPlaceholder').style.display='flex';
document.querySelectorAll('.sel-btn').forEach(b=>b.classList.remove('selected'));
document.querySelectorAll('.desc-btn').forEach(b=>{ b.classList.remove('selected'); b.style.borderColor=''; });
document.querySelectorAll('.scale-btn').forEach(b=>{ b.style.background=''; b.style.color=''; b.style.borderColor=''; });
document.querySelectorAll('.eng-btn').forEach(b=>{ b.style.background=''; b.style.color=''; b.style.borderColor=''; });
document.querySelectorAll('.yn-btn').forEach(b=>{ b.style.background=''; b.style.color=''; b.style.borderColor=''; });
document.querySelectorAll('.route-btn').forEach(b=>b.classList.toggle('selected',b.dataset.route==='A'));
DOMAIN_DEFS.forEach(d=>{
scores[d.key]=0;
d.subdomains.forEach(s=>{ subScores[d.key+'.'+s.key]=0; });
});
Object.keys(yesNoState).forEach(k=>delete yesNoState[k]);
Object.keys(transitionState).forEach(k=>delete transitionState[k]);
ncData={yearGroup:null,ncEnglish:null,ncMaths:null};
cogRoute='A';
const ncEl=document.getElementById('ncGapDisplay');
if(ncEl){ncEl.textContent='Select year group and NC level above';ncEl.classList.remove('scored');}
document.querySelectorAll('.domain-score-badge').forEach(b=>{b.textContent='—';b.classList.remove('scored');b.style.background='';b.style.color='';b.style.border='';b.style.borderColor='';b.style.borderColor='';b.style.border='';b.style.backgroundColor='';b.style.color='';b.removeAttribute('style');});
setCogRoute('A');
drawWheel();
updateSummaryHeader();
renderSummary();
}
function confirmClear() {
const hasData = Object.values(scores).some(v=>v>0) || currentName;
if(hasData && !confirm('Clear all scores and pupil details?')) return;
silentClear();
}
// ── PDF EXPORT ──
function exportPDF() {
drawWheelOnCtx(ctx, true, 'snapshot');
const wheelDataUrl = wheelCanvas.toDataURL('image/png');
drawWheelOnCtx(ctx, false, wheelType);
drawWheelOnCtx(sctx, false, wheelType);
const fullName = document.getElementById('pupilName').value || currentName || 'Pupil';
const preferredName = document.getElementById('preferredName').value;
const teacher = document.getElementById('teacherName').value;
const dateRaw = document.getElementById('completionDate').value;
const dateDisplay = dateRaw ? new Date(dateRaw).toLocaleDateString('en-GB',{day:'numeric',month:'long',year:'numeric'}) : '';
const additionalInfo = document.getElementById('additionalInfo').value.trim();
const scored = DOMAIN_DEFS.filter(d=>scores[d.key]>0);
const name = preferredName || fullName;
const domainRows = scored.map(d => {
const sc = scores[d.key];
const bgMap = {1:'#f0fdf4',2:'#f0fdf4',3:'#fefce8',4:'#fff7ed',5:'#fef2f2'};
const tcMap = {1:'#166534',2:'#166534',3:'#854d0e',4:'#9a3412',5:'#991b1b'};
const narrative = generateDomainNarrative(d.key, name).replace(//g,'>');
return `
${d.label}Level ${'ABCDE'[sc-1]} — ${'Emerging,Developing,Established,Complex,Specialist'.split(',')[sc-1]} support
${narrative}
`;
}).join('');
const refTables = `
Support Level Key
A – Minimal
Need present but well-managed. Low impact on daily school life.
B – Low
Some support at key points. Generally self-managing with prompting.
C – Moderate
Regular adult support required. Planned strategies in place.
`;
guideContainer.appendChild(card);
});
// Support levels guide
const slContainer = document.getElementById('supportLevelsGuide');
const slDescs = [
{lbl:'A – Emerging', color:'#4ade80', desc:'Needs are present but well-managed with good universal provision.'},
{lbl:'B – Developing', color:'#a3e635', desc:'Some targeted support at key points. Building independence with prompting.'},
{lbl:'C – Established', color:'#f59e0b', desc:'Regular planned support in place. Working toward greater independence.'},
{lbl:'D – Complex', color:'#f97316', desc:'Complex needs requiring significant planned support throughout the day.'},
{lbl:'E – Specialist', color:'#ef4444', desc:'Specialist sustained support required. Highly individualised provision.'},
];
slDescs.forEach(s => {
const el = document.createElement('div');
el.style.cssText = 'display:flex;gap:10px;align-items:flex-start;padding:.5rem 0;border-bottom:1px solid var(--border);';
el.innerHTML = `${s.lbl}${s.desc}`;
slContainer.appendChild(el);
});
// ── FAQ ──
const FAQ = [
{q:"What is Snapshot?", a:"Snapshot is a professional SEND profiling and transition planning tool. It gives everyone who works with a young person a clear, consistent picture of where they are now, where they're heading, and what needs to happen to get them there — mapped across eight domains aligned to the SEND Code of Practice."},
{q:"What are the eight domains?", a:"Communication & Interaction, Cognition & Learning, Social Emotional & Mental Health, Sensory & Physical, Health, Life Skills & Independence, Regulation & Anxiety Response, and Destinations — directly mapped to the four areas of SEND, with Regulation & Anxiety Response grounded in Positive Behaviour Support and Zones of Regulation frameworks, and Destinations built around the CofP's preparation for adulthood principle."},
{q:"What do levels A–E mean?", a:"A (Minimal) through to E (Intensive) — describing the level of support required. The score is calculated automatically from the sub-domain questions within each domain."},
{q:"What is the Engagement Model?", a:"The Engagement Model is the statutory assessment framework for pupils working below the level of the National Curriculum and not engaged in subject-specific study. Select it in the Cognition domain when appropriate."},
{q:"How are domain scores calculated?", a:"Each domain contains sub-domain questions (descriptor selects, A-E scales, yes/no). The domain score is automatically calculated as a weighted average of the sub-domain scores."},
{q:"Who should complete the snapshot?", a:"The class teacher or key worker who knows the pupil best. It is good practice to involve colleagues who work closely with the pupil to ensure scores reflect a shared understanding."},
{q:"Can it be shared with families?", a:"Yes — it is designed to be accessible and readable. Always give families the opportunity to discuss the content and share their own perspective."},
{q:"Is it the same as an EHCP?", a:"No. The EHCP is the statutory document setting out needs, outcomes and provision in detail. Snapshot is a practical quick-reference summary that sits alongside it."},
{q:"How do I add a photo?", a:"Go to the Summary tab and tap the photo circle to upload an image. It appears on the PDF export. Ensure appropriate consent is in place."},
{q:"Can schools add their own pathways?", a:"The school-specific fields (pathways, classes, destinations) are customisable per school. Contact us at snapshotschools.co.uk to discuss your school's setup."},
];
const faqEl = document.getElementById('faqAccordion');
faqEl.style.cssText = 'display:grid;grid-template-columns:1fr 1fr;gap:.75rem;';
FAQ.forEach(item => {
const card = document.createElement('div');
card.style.cssText = 'background:var(--surface);border:1px solid var(--border);border-radius:10px;overflow:hidden;cursor:pointer;';
card.innerHTML = `
${item.q}▼
${item.a}
`;
card.onclick = () => {
const body = card.querySelector('.faq-body');
const chev = card.querySelector('.faq-chev');
const open = body.style.display !== 'none';
body.style.display = open ? 'none' : 'block';
chev.style.transform = open ? '' : 'rotate(180deg)';
};
faqEl.appendChild(card);
});
// ── DEMO DATA ──
const DEMO_BOY = "data:image/png;base64,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";
const DEMO_GIRL = "data:image/png;base64,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";
const DEMO_RYAN = "data:image/png;base64,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";
function toggleDemo(who) {
const btns = {
jamie: document.getElementById('demoBtnJamie'),
sarah: document.getElementById('demoBtnSarah'),
ryan: document.getElementById('demoBtnRyan'),
aisha: document.getElementById('demoBtnAisha'),
liam: document.getElementById('demoBtnLiam'),
priya: document.getElementById('demoBtnPriya'),
};
if(demoActive && demoWho===who) {
silentClear();
Object.entries(btns).forEach(([k,b])=>{ b.textContent='▶ '+k[0].toUpperCase()+k.slice(1); b.style.opacity='.6'; b.style.color='var(--accent)'; });
demoActive=false; demoWho=''; return;
}
if(demoActive) silentClear();
const profiles = {
jamie:{name:'James Mitchell',pref:'Jamie',teacher:'Mr Flanagan',date:'2026-03-14',setting:'Special School',ks:'KS4',need:'Cognition & Learning',pathway:'Pathway One',cls:'7GCK',photo:DEMO_BOY,
additionalInfo:'Jamie responds well to visual timetables and structured routines. He benefits from pre-teaching of vocabulary before new topics and requires tasks broken into small steps with regular check-ins. He has a good relationship with his key worker and responds positively to praise. His parents are closely involved and attend all review meetings. He enjoys football and uses this as a motivator.',
descs:{
'comm.howComm':2,'comm.understanding':2,
'semh.emotionalWellbeing':1,'semh.semhSupport':1,
'sensory.mobility':1,'sensory.transfers':1,'sensory.postural':1,
'medical.epilepsy':1,'medical.feeding':1,
'independence.staffRatio':2,'independence.movingAround':2,'independence.safetyAwareness':2,'independence.communityAccess':2,
},
scales:{
'comm.commSupport':2,
'semh.regulation':2,'semh.anxiety':2,'semh.socialComm':2,
'sensory.fatigue':1,'sensory.sensoryProcessing':2,
'independence.personalCare':1,
},
transitions:{
'destinations.independence':{current:2,notes:'Jamie manages his personal routines well with light prompting. He is building skills in food preparation and budgeting with support.'},
'destinations.communityAccess':{current:2,notes:'Accesses community with 1:1 support. Has used public transport twice with adult support — this is a key development target.'},
'destinations.takingControl':{current:2,notes:'Makes choices with guidance. Developing self-advocacy — attends his own review meetings and contributes to his EHCP outcomes.'},
'destinations.takingPart':{current:2,notes:'Engaged in structured activities. Exploring supported employment options at a local garden centre as part of his transition plan.'},
},
yesnos:{'medical.medication':'no','medical.ehcpPlan':'yes'},
nc:{yearGroup:'Year 9',ncEnglish:'Year 6',ncMaths:'Year 7'}, cogRouteVal:'A',
learningSupport:2
},
sarah:{name:'Sarah Mitchell',pref:'Sarah',teacher:'Mr Flanagan',date:'2026-03-14',setting:'Special School',ks:'KS3',need:'Sensory & Physical',pathway:'Pathway Four',cls:'8ELD',photo:DEMO_GIRL,
additionalInfo:'Sarah requires two members of staff for all transfers and personal care. She has a full manual handling plan and a postural management programme reviewed by her physiotherapist termly. Her IHP covers seizure management, PEG feeding protocols and positioning requirements. Sarah uses an eye-gaze device for communication — staff should allow extended processing time. She responds well to familiar faces and calm, predictable environments. Family are central to her care planning.',
descs:{
'comm.howComm':4,'comm.understanding':3,
'semh.emotionalWellbeing':2,'semh.semhSupport':2,
'sensory.mobility':9,'sensory.transfers':5,'sensory.postural':4,
'medical.epilepsy':4,'medical.feeding':5,
'independence.staffRatio':5,'independence.movingAround':5,'independence.safetyAwareness':2,'independence.communityAccess':4,
},
scales:{
'comm.commSupport':5,
'semh.regulation':2,'semh.anxiety':2,'semh.socialComm':3,
'sensory.fatigue':5,'sensory.sensoryProcessing':4,
'independence.personalCare':5,
},
transitions:{
'destinations.independence':{current:5,notes:'Sarah requires full adult support for all daily living activities. The focus is on comfort, dignity and quality of life within a specialist residential or supported living environment.'},
'destinations.communityAccess':{current:4,notes:'Community access requires significant advance planning, specialist transport and appropriate staffing. Sarah benefits from familiar community environments with low sensory demand.'},
'destinations.takingControl':{current:4,notes:'Sarah communicates preferences through her AAC device and eye gaze. Staff should always offer real choices and respect her responses. Supported decision-making is central to her care.'},
'destinations.takingPart':{current:5,notes:'Sarah engages in sensory and relationship-based activities. Participation is about connection, enjoyment and comfort — structured activity goals are not appropriate at this stage.'},
},
yesnos:{'medical.medication':'yes','medical.ehcpPlan':'yes'},
nc:{yearGroup:'Year 8',ncEnglish:'Year 3',ncMaths:'Year 2'}, cogRouteVal:'A',
learningSupport:4
},
ryan:{name:'Ryan Thomas',pref:'Ryan',teacher:'Mr Flanagan',date:'2026-03-14',setting:'Special School',ks:'KS4',need:'SEMH',pathway:'Pathway Five',cls:'9MED',photo:DEMO_RYAN,
additionalInfo:'Ryan has an active de-escalation plan which all staff must read before working with him. He responds well to low-key, non-confrontational approaches and needs time and space to regulate before being re-engaged in learning. CAMHS are involved fortnightly. Ryan has identified a small number of trusted adults — continuity of key worker is essential. He has expressed a strong interest in music and gaming, which are used as engagement tools. His parents are separated and communication should go through his mother.',
descs:{
'comm.howComm':2,'comm.understanding':2,
'semh.emotionalWellbeing':4,'semh.semhSupport':4,
'sensory.mobility':1,'sensory.transfers':1,'sensory.postural':1,
'medical.epilepsy':1,'medical.feeding':1,
'independence.staffRatio':4,'independence.movingAround':3,'independence.safetyAwareness':4,'independence.communityAccess':4,
},
scales:{
'comm.commSupport':3,
'semh.regulation':5,'semh.anxiety':5,'semh.socialComm':4,
'sensory.fatigue':2,'sensory.sensoryProcessing':4,
'independence.personalCare':2,
},
transitions:{
'destinations.independence':{current:3,notes:'Ryan is physically capable of independent living with light support. The primary barriers are emotional regulation and safety awareness — both are active targets in his transition plan.'},
'destinations.communityAccess':{current:4,notes:'Community access is possible with 1:1 support and careful planning. Ryan can become overwhelmed in busy environments. Gradual exposure and a clear exit strategy are essential.'},
'destinations.takingControl':{current:3,notes:'Ryan can express preferences clearly when regulated. Building self-advocacy skills is a key focus — he is beginning to identify his own triggers and contribute to his support plan.'},
'destinations.takingPart':{current:3,notes:'Ryan engages with structured creative activities — music production and digital media. These are being developed as potential vocational pathways with support from a specialist transitions worker.'},
},
yesnos:{'medical.medication':'yes','medical.ehcpPlan':'yes'},
nc:{yearGroup:'Year 9',ncEnglish:'Year 4',ncMaths:'Year 2'}, cogRouteVal:'A',
learningSupport:3
},
aisha:{name:'Aisha Rahman',pref:'Aisha',teacher:'Miss Patel',date:'2026-03-14',setting:'Special School',ks:'KS2',need:'Sensory & Physical',pathway:'Pathway Four',cls:'7GCK',photo:DEMO_GIRL,
additionalInfo:'Aisha has profound and multiple learning difficulties. She requires total support across all areas of daily life. She is most responsive in the morning and with familiar adults in calm, low-stimulus environments. Aisha shows clear pleasure responses to music and gentle sensory activities — these are her primary engagement tools. Her mum is closely involved and visits fortnightly. All positioning, handling and personal care must follow her postural management programme. IHP covers PEG feeding, suction and seizure protocol.',
descs:{
'comm.howComm':5,'comm.understanding':5,
'semh.emotionalWellbeing':2,'semh.semhSupport':2,
'sensory.mobility':9,'sensory.transfers':5,'sensory.postural':4,
'medical.epilepsy':4,'medical.feeding':5,
'independence.staffRatio':6,'independence.movingAround':5,'independence.safetyAwareness':3,'independence.communityAccess':5,
},
scales:{
'comm.commSupport':5,
'semh.regulation':3,'semh.anxiety':2,'semh.socialComm':4,
'sensory.fatigue':5,'sensory.sensoryProcessing':5,
'independence.personalCare':5,
},
engagements:{
exploration:'developing',
realisation:'emerging',
anticipation:'developing',
persistence:'emerging',
initiation:'emerging',
},
transitions:{
'destinations.independence':{current:5,notes:'Aisha requires full adult support across all daily living. The focus is entirely on comfort, dignity, sensory wellbeing and quality of life.'},
'destinations.communityAccess':{current:5,notes:'Community access requires specialist transport, full medical support and careful environmental planning. Short, familiar outings are possible with the right preparation.'},
'destinations.takingControl':{current:5,notes:'Aisha communicates through pleasure and distress responses. All adults must observe and respect these signals as her means of expressing preference. Supported decision-making through consistent observation is the goal.'},
'destinations.takingPart':{current:5,notes:'Participation is sensory and relational — music, tactile activities, familiar voices. The aspiration is specialist residential provision with rich daily sensory and social programming.'},
},
yesnos:{'medical.medication':'yes','medical.ehcpPlan':'yes'},
nc:{yearGroup:null,ncEnglish:null,ncMaths:null}, cogRouteVal:'B',
},
liam:{name:'Liam Okafor',pref:'Liam',teacher:'Mr Singh',date:'2026-03-14',setting:'Special School',ks:'KS3',need:'Communication & Interaction',pathway:'Pathway Three',cls:'8ELD',photo:DEMO_BOY,
additionalInfo:'Liam has a diagnosis of autism with associated learning difficulties and is assessed on the Engagement Model. He has no formal communication system currently in place — SALT assessment is pending. Liam shows strong object permanence and responds well to predictable, object-based routines. He can become very distressed by unexpected change and requires an individual transition plan for any change in routine. He engages positively with water-based sensory activities. Staff should avoid direct eye contact during times of distress. A communication passport is in development.',
descs:{
'comm.howComm':5,'comm.understanding':4,
'semh.emotionalWellbeing':3,'semh.semhSupport':3,
'sensory.mobility':1,'sensory.transfers':1,'sensory.postural':1,
'medical.epilepsy':1,'medical.feeding':2,
'independence.staffRatio':4,'independence.movingAround':3,'independence.safetyAwareness':4,'independence.communityAccess':4,
},
scales:{
'comm.commSupport':5,
'semh.regulation':4,'semh.anxiety':5,'semh.socialComm':5,
'sensory.fatigue':3,'sensory.sensoryProcessing':5,
'independence.personalCare':3,
},
engagements:{
exploration:'established',
realisation:'developing',
anticipation:'established',
persistence:'developing',
initiation:'emerging',
},
transitions:{
'destinations.independence':{current:4,notes:'Liam manages some personal routines with prompting and structure. The development of a consistent daily living programme is a key EHCP outcome for this year.'},
'destinations.communityAccess':{current:4,notes:'Community access is highly unpredictable. Liam has accessed familiar low-demand environments successfully. All community visits require individual risk assessment and a dedicated familiar adult.'},
'destinations.takingControl':{current:5,notes:'Self-advocacy skills are at the very earliest stages. Liam communicates preference through approach and avoidance. Object-based choice-making is being introduced systematically.'},
'destinations.takingPart':{current:4,notes:'Liam engages in structured sensory and object-based activities with familiar adults. The goal is building a repertoire of preferred activities that can form the basis of his adult day.'},
},
yesnos:{'medical.medication':'no','medical.ehcpPlan':'yes'},
nc:{yearGroup:null,ncEnglish:null,ncMaths:null}, cogRouteVal:'B',
},
priya:{name:'Priya Sharma',pref:'Priya',teacher:'Mrs Ahmed',date:'2026-03-14',setting:'Resourced Provision',ks:'KS4',need:'Communication & Interaction',pathway:'Pathway Two',cls:'9MED',photo:DEMO_GIRL,
additionalInfo:'Priya has a diagnosis of autism and ADHD. She is highly academic but struggles significantly with social communication, sensory processing and executive function. She is placed in a resourced provision attached to a mainstream school and accesses some mainstream lessons with support. Priya is highly anxious about transitions and unstructured time. She has a strong interest in science and engineering and these are used as motivators throughout her timetable. She is self-aware about her diagnosis and engages well with strategies when they are explained to her. Peer relationships are an active target.',
descs:{
'comm.howComm':1,'comm.understanding':1,
'semh.emotionalWellbeing':3,'semh.semhSupport':3,
'sensory.mobility':1,'sensory.transfers':1,'sensory.postural':1,
'medical.epilepsy':1,'medical.feeding':1,
'independence.staffRatio':2,'independence.movingAround':2,'independence.safetyAwareness':2,'independence.communityAccess':2,
},
scales:{
'comm.commSupport':2,
'semh.regulation':3,'semh.anxiety':4,'semh.socialComm':4,
'sensory.fatigue':2,'sensory.sensoryProcessing':4,
'independence.personalCare':1,
},
transitions:{
'destinations.independence':{current:2,notes:'Priya is capable of strong independence in familiar, structured environments. Executive function difficulties mean she needs support with planning and organisation rather than practical daily living skills.'},
'destinations.communityAccess':{current:2,notes:'Priya accesses the community with light support. She is building confidence with public transport. Busy or unpredictable environments remain a challenge.'},
'destinations.takingControl':{current:2,notes:'Priya is a strong self-advocate when supported. She attends all her review meetings and contributes meaningfully to her EHCP. Building confidence in unfamiliar contexts is the next step.'},
'destinations.takingPart':{current:1,notes:'Priya is on track for further education. She has expressed an interest in engineering and has attended two taster days at the local college. A supported transition to an FE STEM course is the clear aspiration.'},
},
yesnos:{'medical.medication':'yes','medical.ehcpPlan':'yes'},
nc:{yearGroup:'Year 10',ncEnglish:'Year 9',ncMaths:'Year 10'}, cogRouteVal:'A',
learningSupport:1
},
};
const p = profiles[who];
document.getElementById('pupilName').value = p.name;
document.getElementById('preferredName').value = p.pref;
document.getElementById('teacherName').value = p.teacher;
document.getElementById('completionDate').value = p.date;
if(p.additionalInfo) document.getElementById('additionalInfo').value = p.additionalInfo;
currentName = p.name;
// Set sel grids
const setGrid = (gridId, val) => {
document.querySelectorAll('#'+gridId+' .sel-btn').forEach(b=>{
b.classList.toggle('selected', b.textContent===val);
});
};
selectedSetting=p.setting; setGrid('settingGrid',p.setting);
selectedKS=p.ks; setGrid('ksGrid',p.ks);
selectedNeed=p.need; setGrid('primaryNeedGrid',p.need);
selectedPathway=p.pathway; setGrid('pathwayGrid',p.pathway);
selectedClass=p.cls; setGrid('classGrid',p.cls);
// Photo
photoDataUrl=p.photo;
const img=document.getElementById('photoPreview'); img.src=photoDataUrl; img.style.display='block';
document.getElementById('photoPlaceholder').style.display='none';
// Cognition route
cogRoute=p.cogRouteVal; setCogRoute(cogRoute);
ncData={yearGroup:p.nc.yearGroup, ncEnglish:p.nc.ncEnglish||null, ncMaths:p.nc.ncMaths||null};
// Select the right KS stage and year group
if(p.nc.yearGroup) {
const ks = Object.keys(YEAR_GROUPS_BY_KS).find(k => YEAR_GROUPS_BY_KS[k].includes(p.nc.yearGroup));
if(ks) setTimeout(() => selectKS(ks), 50);
const yBtn = document.querySelector(`#yearGroupGrid .sel-btn[data-year="${p.nc.yearGroup}"]`);
if(yBtn) setTimeout(() => { yBtn.classList.add('selected'); }, 60);
}
// NC levels
['ncEnglish','ncMaths'].forEach(key => {
const val = ncData[key];
if(!val) return;
const stateKey = key === 'ncEnglish' ? 'ncEnglish' : 'ncMaths';
document.querySelectorAll('#dcard-cog .sel-btn').forEach(b => {
if(b.textContent === val && !b.getAttribute('data-year')) {
b.closest('.sel-grid').querySelectorAll('.sel-btn').forEach(sb=>sb.classList.remove('selected'));
b.classList.add('selected');
}
});
});
updateNCDisplay();
if(p.learningSupport) {
const lsBtn = document.querySelector('#dcard-cog .scale-desc-btn[data-score="'+p.learningSupport+'"]');
if(lsBtn) setScale('cog','learningSupport',p.learningSupport,lsBtn);
}
// Descriptors
Object.entries(p.descs).forEach(([sk, score]) => {
const [dk, subk] = sk.split('.');
const card = document.querySelector('#dcard-'+dk);
if(!card) return;
const btns = card.querySelectorAll('.desc-btn');
btns.forEach(btn => {
if(btn.getAttribute('onclick')&&btn.getAttribute('onclick').includes("'"+subk+"'")){};
});
// Find the desc-grid for this subkey and select right score
const subDef = DOMAIN_DEFS.find(d=>d.key===dk)?.subdomains.find(s=>s.key===subk);
if(subDef&&subDef.options) {
const matchingBtns = Array.from(card.querySelectorAll('.desc-btn')).filter(b=>b.getAttribute('onclick')&&b.getAttribute('onclick').includes("'"+subk+"'"));
// Find one that matches score
const target = matchingBtns.find(b=>{
const m = b.getAttribute('onclick').match(/,(\d+),/);
return m && parseInt(m[1])===score;
});
if(target) {
target.closest('.desc-grid').querySelectorAll('.desc-btn').forEach(b=>{b.classList.remove('selected');b.style.borderColor='';});
target.classList.add('selected');
const def=DOMAIN_DEFS.find(d=>d.key===dk);
target.style.borderColor=def.color;
subScores[sk]=score;
updateDomainScore(dk);
}
}
});
// Scales
Object.entries(p.scales).forEach(([sk, score]) => {
const [dk, subk] = sk.split('.');
const card = document.querySelector('#dcard-'+dk);
if(!card) return;
const btn = Array.from(card.querySelectorAll('.scale-desc-btn')).find(b=>{
return b.getAttribute('onclick')&&b.getAttribute('onclick').includes("'"+subk+"'")&&b.getAttribute('data-score')===''+score;
});
if(btn) setScale(dk,subk,score,btn);
});
// Yes/No
Object.entries(p.yesnos).forEach(([sk, val]) => {
const [dk, subk] = sk.split('.');
const card = document.querySelector('#dcard-'+dk);
if(!card) return;
const btn = Array.from(card.querySelectorAll('.yn-btn')).find(b=>b.getAttribute('data-val')===val&&b.getAttribute('onclick')&&b.getAttribute('onclick').includes("'"+subk+"'"));
if(btn) setYesNo(dk,subk,val,btn);
});
// Engagements (route B only)
if(p.engagements) {
Object.entries(p.engagements).forEach(([subk, val]) => {
const card = document.querySelector('#dcard-cog');
if(!card) return;
const btn = Array.from(card.querySelectorAll('.eng-btn')).find(b =>
b.getAttribute('data-val')===val && b.getAttribute('onclick') && b.getAttribute('onclick').includes("'"+subk+"'")
);
if(btn) setEngagement('cog', subk, val, btn);
});
}
// Transitions (destinations domain)
if(p.transitions) {
Object.entries(p.transitions).forEach(([tk, ts]) => {
if(!transitionState[tk]) transitionState[tk] = {current:0, goal:0, flags:[], notes:''};
transitionState[tk].current = ts.current;
transitionState[tk].notes = ts.notes || '';
subScores[tk] = ts.current;
// Select the button visually
const el = document.getElementById('tsub-'+tk);
if(el) {
const btns = el.querySelectorAll('.desc-btn[data-type="current"]');
btns.forEach(b => { b.classList.remove('selected'); b.style.borderColor=''; });
const target = Array.from(btns).find(b=>parseInt(b.getAttribute('data-score'))===ts.current);
if(target) { target.classList.add('selected'); target.style.borderColor='#34d399'; }
// Set notes textarea
const ta = el.querySelector('textarea[data-tk]');
if(ta && ts.notes) ta.value = ts.notes;
}
updateDomainScore('destinations');
});
}
// Leave domain cards closed — user can open as needed
// Update buttons
Object.entries(btns).forEach(([k,b])=>{
const lbl=k[0].toUpperCase()+k.slice(1);
if(k===who){b.textContent='✕ '+lbl;b.style.opacity='1';b.style.color='#f87171';}
else{b.textContent='▶ '+lbl;b.style.opacity='.6';b.style.color='var(--accent)';}
});
demoActive=true; demoWho=who;
updateSummaryHeader(); renderSummary();
}
// ── SUPABASE ──
const SUPABASE_URL = 'https://ewcankwtogiaimjrszws.supabase.co';
const SUPABASE_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImV3Y2Fua3d0b2dpYWltanJzendzIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzM1Nzg4MDIsImV4cCI6MjA4OTE1NDgwMn0.YiXEAwTa1qS10Hnw_QnaOhD3--VYG-3i4Cy_VpRKhpI';
// Wait for ESM module to load
function getSupabase() {
return window._supabaseClient;
}
// Poll until available then init auth
function initAuth() {
const sb = getSupabase();
if(!sb) { setTimeout(initAuth, 100); return; }
sb.auth.getSession().then(({ data: { session } }) => {
if(session) handleUser(session.user);
else document.getElementById('authScreen').classList.remove('hidden');
});
sb.auth.onAuthStateChange((_event, session) => {
if(session) handleUser(session.user);
else {
currentUser = null;
document.getElementById('authScreen').classList.remove('hidden');
}
});
}
const supabase = new Proxy({}, {
get(_, prop) {
const sb = window._supabaseClient;
if(!sb) return () => Promise.resolve({ data: null, error: { message: 'Connecting...' } });
return typeof sb[prop] === 'function' ? sb[prop].bind(sb) : sb[prop];
}
});
let currentUser = null;
let currentPupilId = null;
let drawerOpen = false;
// ── AUTH STATE ──
// Auth listeners moved to initAuth()
function handleUser(user) {
currentUser = user;
document.getElementById('authScreen').classList.add('hidden');
document.getElementById('userEmail').textContent = user.email;
loadPupilList();
}
// ── AUTH FUNCTIONS ──
function showRegister() {
document.getElementById('loginForm').style.display = 'none';
document.getElementById('registerForm').style.display = 'block';
}
function showLogin() {
document.getElementById('registerForm').style.display = 'none';
document.getElementById('loginForm').style.display = 'block';
}
async function doLogin() {
const email = document.getElementById('authEmail').value.trim();
const pass = document.getElementById('authPassword').value;
const err = document.getElementById('authError');
err.textContent = '';
if(!email || !pass) { err.textContent = 'Please enter your email and password.'; return; }
const { error } = await supabase.auth.signInWithPassword({ email, password: pass });
if(error) err.textContent = 'Incorrect email or password.';
}
async function doRegister() {
const school = document.getElementById('regSchool').value.trim();
const email = document.getElementById('regEmail').value.trim();
const pass = document.getElementById('regPassword').value;
const err = document.getElementById('regError');
const btn = document.querySelector('#registerForm .auth-btn');
err.textContent = '';
err.style.color = '#f87171';
if(!school || !email || !pass) { err.textContent = 'Please fill in all fields.'; return; }
if(pass.length < 6) { err.textContent = 'Password must be at least 6 characters.'; return; }
if(!email.includes('@')) { err.textContent = 'Please enter a valid email address.'; return; }
btn.textContent = 'Creating account...';
try {
const { data, error } = await supabase.auth.signUp({ email, password: pass,
options: { data: { school_name: school } }
});
if(error) { err.textContent = error.message; btn.textContent = 'Create Account'; return; }
if(data.user && data.session) {
// Logged in immediately — email confirmation is off
btn.textContent = 'Create Account';
} else if(data.user && !data.session) {
// Email confirmation still on
err.style.color = '#4ade80';
err.textContent = 'Check your email to confirm your account, then sign in.';
btn.textContent = 'Create Account';
setTimeout(() => showLogin(), 3000);
}
} catch(e) {
console.error('Register error:', e);
err.textContent = 'Error: ' + (e.message || JSON.stringify(e));
btn.textContent = 'Create Account';
}
}
async function doLogout() {
await supabase.auth.signOut();
silentClear();
currentPupilId = null;
toggleDrawer(false);
}
// ── SAVE / LOAD ──
function getProfileState() {
return {
name: document.getElementById('pupilName').value || '',
preferredName: document.getElementById('preferredName').value || '',
teacherName: document.getElementById('teacherName').value || '',
completionDate: document.getElementById('completionDate').value || '',
additionalInfo: document.getElementById('additionalInfo').value || '',
selectedSetting, selectedKS, selectedNeed, selectedPathway, selectedClass,
scores: {...scores},
subScores: {...subScores},
ncData: {...ncData},
cogRoute,
yesNoState: {...yesNoState},
transitionState: {...transitionState},
photoDataUrl: photoDataUrl || '',
updatedAt: new Date().toISOString()
};
}
async function saveProfile() {
if(!currentUser) return;
const state = getProfileState();
if(!state.name) { alert('Please enter a pupil name before saving.'); return; }
const btn = document.getElementById('saveBtn');
btn.textContent = 'Saving...';
try {
if(currentPupilId) {
const { error } = await supabase.from('pupils').update({ name: state.name, data: state, updated_at: new Date().toISOString() }).eq('id', currentPupilId);
if(error) throw error;
} else {
const { data, error } = await supabase.from('pupils').insert({ school_id: currentUser.id, name: state.name, data: state }).select().single();
if(error) throw error;
currentPupilId = data.id;
}
btn.textContent = 'Save';
const ind = document.getElementById('saveIndicator');
ind.style.display = 'inline';
setTimeout(() => ind.style.display = 'none', 2500);
loadPupilList();
} catch(e) {
btn.textContent = 'Save';
alert('Save failed: ' + e.message);
}
}
async function loadPupilList() {
if(!currentUser) return;
const list = document.getElementById('pupilList');
list.innerHTML = '