Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 12s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 50s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 12s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 1s
A first-choice offer rate sitting on the y-max ceiling (100%) was drawn flush against the top of the plot area, clipping the point marker. Add 8px top layout padding and clip:false so ceiling values render in full, without introducing a misleading >100% tick. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
75 lines
3.9 KiB
HTML
75 lines
3.9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Admissions trend — Chart.js render check</title>
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
|
|
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=Playfair+Display:wght@600&display=swap" rel="stylesheet">
|
|
<style>
|
|
:root{
|
|
--bg-primary:#faf7f2;--bg-secondary:#f3ede4;--bg-card:#fff;
|
|
--text-primary:#1a1612;--text-secondary:#5c564d;--text-muted:#6d685f;
|
|
--accent-coral:#e07256;--border:#e5dfd5;--shadow:0 2px 8px rgba(26,22,18,.06);
|
|
}
|
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
body{font-family:'DM Sans',sans-serif;background:var(--bg-primary);color:var(--text-primary);padding:40px 20px}
|
|
.wrap{max-width:900px;margin:0 auto}
|
|
.card{background:#fff;border:1px solid var(--border);border-radius:16px;box-shadow:var(--shadow);padding:28px}
|
|
.head{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap;margin-bottom:1.25rem}
|
|
.title{font-family:'Playfair Display',serif;font-weight:600;font-size:22px}
|
|
.seg{display:inline-flex;background:var(--bg-secondary);border-radius:999px;padding:3px;gap:2px}
|
|
.seg button{border:none;background:none;cursor:pointer;font:inherit;font-size:13px;font-weight:600;color:var(--text-muted);padding:6px 14px;border-radius:999px}
|
|
.seg button[aria-pressed="true"]{background:#fff;color:var(--text-primary);box-shadow:var(--shadow)}
|
|
.cap{font-size:13px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--text-muted);margin-bottom:.5rem}
|
|
.chartWrap{width:100%;height:200px}
|
|
.summary{font-size:16px;color:var(--text-secondary);margin-top:1.25rem;padding-top:1.1rem;border-top:1px solid var(--border)}
|
|
.summary strong{color:var(--text-primary)}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="wrap">
|
|
<div class="card">
|
|
<div class="head">
|
|
<div class="title">How Hard to Get Into This School</div>
|
|
<div class="seg"><button aria-pressed="false">This year</button><button aria-pressed="true">13-year trend</button></div>
|
|
</div>
|
|
<div class="cap">First-choice offer rate</div>
|
|
<div class="chartWrap"><canvas id="c"></canvas></div>
|
|
<p class="summary">This year (2026/27), <strong>30</strong> families put it first for <strong>30</strong> places — 101 applications in total.</p>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
const labels = ['2014/15','2015/16','2016/17','2017/18','2018/19','2019/20','2020/21','2021/22','2022/23','2023/24','2024/25','2025/26','2026/27'];
|
|
const values = [64,74,63,59,45,69,66,93,100,100,90,64,80];
|
|
const lastIdx = values.length-1;
|
|
const lo=Math.min(...values),hi=Math.max(...values);
|
|
const padded=Math.max(5,Math.round((hi-lo)*0.25));
|
|
const yMin=Math.max(0,Math.floor((lo-padded)/5)*5);
|
|
const yMax=Math.min(100,Math.ceil((hi+padded)/5)*5);
|
|
new Chart(document.getElementById('c'),{
|
|
type:'line',
|
|
data:{labels,datasets:[{
|
|
label:'First-choice offer rate',data:values,clip:false,
|
|
borderColor:'#e07256',backgroundColor:'rgba(224,114,86,0.10)',
|
|
borderWidth:2.5,tension:0.3,fill:true,
|
|
pointRadius:values.map((_,i)=>i===lastIdx?5:3),
|
|
pointBackgroundColor:'#e07256',pointBorderColor:'#fff',
|
|
pointBorderWidth:values.map((_,i)=>i===lastIdx?2:0),pointHoverRadius:6,
|
|
}]},
|
|
options:{
|
|
responsive:true,maintainAspectRatio:false,
|
|
layout:{padding:{top:8}},
|
|
interaction:{mode:'index',intersect:false},
|
|
plugins:{legend:{display:false},title:{display:false},
|
|
tooltip:{backgroundColor:'rgba(26,22,18,0.92)',padding:10,callbacks:{label:ctx=>`First-choice offers: ${Math.round(ctx.parsed.y)}%`}}},
|
|
scales:{
|
|
y:{min:yMin,max:yMax,grid:{color:'rgba(0,0,0,0.05)'},ticks:{font:{size:11},maxTicksLimit:5,callback:v=>`${v}%`}},
|
|
x:{grid:{display:false},ticks:{font:{size:11},autoSkip:true,maxRotation:0,autoSkipPadding:16}},
|
|
},
|
|
},
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|