x
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
<div class="tw:p-6 tw:max-w-7xl tw:mx-auto tw:space-y-8"> <!-- Introductory callout --> <div class="tw-callout"> <p class="tw:mb-1 tw:text-sm tw:font-mono"> <strong>CHART:</strong> two tiers, chosen by what the data does (DR-2026-14)<br> <strong>TIER 1:</strong> .tw-chart-bars — CSS comparison bars, no dependency<br> <strong>TIER 2:</strong> data-controller="chart" — Chart.js, lazy-loaded, the only sanctioned path </p> <p class="tw:mb-0 tw:text-sm"> Compare a handful of labelled magnitudes → Tier 1. Change over time, multiple series, axes → Tier 2. One headline number → a <strong>Stat Tile</strong>, not a chart. A share of a whole → the usage donut. Series colours are <strong>computed, not chosen</strong> — see the palette section below. </p> </div> <!-- Tier 1 --> <div class="tw:border-t tw:pt-6"> <h2 class="tw-h4 tw:mb-4">Tier 1 — CSS comparison bars</h2> <div class="tw-callout tw:mb-4"> <p class="tw:mb-0 tw:text-sm"> <strong>Bars:</strong> pure CSS, no JavaScript. Width comes from <code>tw:[--chart-value:64%]</code> — an arbitrary-property utility, never an inline style. Values use tabular figures so digits line up down the column. Consolidates the bar treatments hand-rolled across 17 prototype files. </p> </div> <div class="tw:grid tw:grid-cols-1 tw:lg:grid-cols-2 tw:gap-6"> <div class="tw-card"> <div class="tw-card-body"> <h3 class="tw-card-title">Where enquiries come from</h3> <p class="tw:text-muted tw:text-sm tw:mb-4">Single series — no legend needed, the title names it.</p> <div class="tw-chart-bars"> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">Open days</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:76%]"></span></span> <span class="tw-chart-bar-value">76%</span> </div> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">School website</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:52%]"></span></span> <span class="tw-chart-bar-value">52%</span> </div> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">Word of mouth</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:38%]"></span></span> <span class="tw-chart-bar-value">38%</span> </div> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">Local authority</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:24%]"></span></span> <span class="tw-chart-bar-value">24%</span> </div> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">Other</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-other tw:[--chart-value:11%]"></span></span> <span class="tw-chart-bar-value">11%</span> </div> </div> </div> </div> <div class="tw-card"> <div class="tw-card-body"> <h3 class="tw-card-title">Applications by stage</h3> <p class="tw:text-muted tw:text-sm tw:mb-4">Multiple series — the legend is mandatory from two.</p> <div class="tw-chart-bars tw-chart-bars-sm"> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">Year 7</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:82%]"></span></span> <span class="tw-chart-bar-value">164</span> </div> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">Year 12</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-2 tw:[--chart-value:61%]"></span></span> <span class="tw-chart-bar-value">122</span> </div> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">In-year</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-3 tw:[--chart-value:34%]"></span></span> <span class="tw-chart-bar-value">68</span> </div> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">Nursery</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-4 tw:[--chart-value:19%]"></span></span> <span class="tw-chart-bar-value">38</span> </div> </div> <div class="tw-chart-legend"> <span class="tw-chart-legend-item"><span class="tw-chart-legend-swatch tw-chart-series-1"></span>Year 7</span> <span class="tw-chart-legend-item"><span class="tw-chart-legend-swatch tw-chart-series-2"></span>Year 12</span> <span class="tw-chart-legend-item"><span class="tw-chart-legend-swatch tw-chart-series-3"></span>In-year</span> <span class="tw-chart-legend-item"><span class="tw-chart-legend-swatch tw-chart-series-4"></span>Nursery</span> </div> </div> </div> </div> <div class="tw:mt-4 tw:text-sm tw:text-gray-600"> <code><div class="tw-chart-bar"><span class="tw-chart-bar-label">Open days</span><span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:76%]"></span></span><span class="tw-chart-bar-value">76%</span></div></code> </div> </div> <!-- Size + layout variants --> <div class="tw:border-t tw:pt-6"> <h2 class="tw-h4 tw:mb-4">Sizes and stacked labels</h2> <div class="tw:grid tw:grid-cols-1 tw:lg:grid-cols-3 tw:gap-6"> <div class="tw-card"> <div class="tw-card-body"> <p class="tw:text-sm tw:font-medium tw:mb-3">Small</p> <div class="tw-chart-bars tw-chart-bars-sm"> <div class="tw-chart-bar"><span class="tw-chart-bar-label">Submitted</span><span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:70%]"></span></span><span class="tw-chart-bar-value">70%</span></div> <div class="tw-chart-bar"><span class="tw-chart-bar-label">In review</span><span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:45%]"></span></span><span class="tw-chart-bar-value">45%</span></div> </div> </div> </div> <div class="tw-card"> <div class="tw-card-body"> <p class="tw:text-sm tw:font-medium tw:mb-3">Large</p> <div class="tw-chart-bars tw-chart-bars-lg"> <div class="tw-chart-bar"><span class="tw-chart-bar-label">Submitted</span><span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:70%]"></span></span><span class="tw-chart-bar-value">70%</span></div> <div class="tw-chart-bar"><span class="tw-chart-bar-label">In review</span><span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:45%]"></span></span><span class="tw-chart-bar-value">45%</span></div> </div> </div> </div> <div class="tw-card"> <div class="tw-card-body"> <p class="tw:text-sm tw:font-medium tw:mb-3">Stacked labels — long names, narrow card</p> <div class="tw-chart-bars tw-chart-bars-stacked-labels"> <div class="tw-chart-bar"><span class="tw-chart-bar-label">St Mary's Catholic Primary</span><span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:64%]"></span></span><span class="tw-chart-bar-value">32</span></div> <div class="tw-chart-bar"><span class="tw-chart-bar-label">Brookfield Community School</span><span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:41%]"></span></span><span class="tw-chart-bar-value">21</span></div> </div> </div> </div> </div> </div> <!-- Tier 2 --> <div class="tw:border-t tw:pt-6"> <h2 class="tw-h4 tw:mb-4">Tier 2 — the chart controller (Chart.js)</h2> <div class="tw-callout tw:mb-4"> <p class="tw:mb-0 tw:text-sm"> <strong>Plotted data:</strong> change over time, multiple series, axes. The <strong>only sanctioned path to Chart.js</strong> — no prototype imports it directly. Lazy-loaded on first reveal, so screens without charts pay nothing; colours resolve from <code>--tw-color-*</code> at runtime, so a token change repaints every chart. <strong>Omit <code>color</code> on a dataset and the ruled order is applied automatically</strong>, and the legend turns itself on from two series. </p> </div> <div class="tw:grid tw:grid-cols-1 tw:lg:grid-cols-2 tw:gap-6"> <div class="tw-card"> <div class="tw-card-body"> <h3 class="tw-card-title">Applications received</h3> <p class="tw:text-muted tw:text-sm tw:mb-3">Two series, smoothed, no explicit colours.</p> <div class="tw:h-64" data-controller="chart" data-chart-type-value="line" data-chart-smooth-value="true" data-chart-axis-value="true" data-chart-labels-value='["Sep","Oct","Nov","Dec","Jan","Feb"]' data-chart-datasets-value='[{"label":"2026/27","data":[12,19,34,52,63,71]},{"label":"2025/26","data":[9,17,28,44,58,64]}]'> <canvas data-chart-target="canvas" role="img" aria-label="Applications received per month: 2026/27 rising from 12 in September to 71 in February, against 2025/26 rising from 9 to 64"></canvas> </div> </div> </div> <div class="tw-card"> <div class="tw-card-body"> <h3 class="tw-card-title">Offers by stage</h3> <p class="tw:text-muted tw:text-sm tw:mb-3">Stacked bars, y axis shown.</p> <div class="tw:h-64" data-controller="chart" data-chart-type-value="bar" data-chart-stacked-value="true" data-chart-axis-value="true" data-chart-labels-value='["Year 7","Year 12","In-year","Nursery"]' data-chart-datasets-value='[{"label":"Accepted","data":[96,74,31,22]},{"label":"Awaiting","data":[42,33,24,11]},{"label":"Declined","data":[26,15,13,5]}]'> <canvas data-chart-target="canvas" role="img" aria-label="Offers by intake and response: Year 7 96 accepted, 42 awaiting, 26 declined; Year 12 74, 33, 15; In-year 31, 24, 13; Nursery 22, 11, 5"></canvas> </div> </div> </div> </div> <div class="tw:mt-4 tw:text-sm tw:text-gray-600"> <code><div data-controller="chart" data-chart-type-value="line" data-chart-labels-value='["Sep","Oct"]' data-chart-datasets-value='[{"label":"2026/27","data":[12,19]}]'><canvas data-chart-target="canvas" role="img" aria-label="…"></canvas></div></code> </div> </div> <!-- Palette --> <div class="tw:border-t tw:pt-6"> <h2 class="tw-h4 tw:mb-4">Series palette — computed, not chosen</h2> <div class="tw-callout tw:mb-4"> <p class="tw:mb-0 tw:text-sm"> The obvious approach — brand tokens at their <code>-500</code> steps in token order — <strong>fails</strong>: <code>orange-500</code>↔<code>green-500</code> separate by only ΔE 4.0 for deutan viewers, and both fall below 3:1 contrast. Two consequences: the brand navy <code>primary-500</code> is unusable as a series colour (too dark), and the series green is <code>green-700</code>, never the base lime. </p> </div> <div class="tw:flex tw:flex-wrap tw:gap-6"> <div class="tw:text-center"><span class="tw:block tw:w-20 tw:h-12 tw:rounded-md tw-chart-series-1"></span><code class="tw:text-xs">blue-600</code></div> <div class="tw:text-center"><span class="tw:block tw:w-20 tw:h-12 tw:rounded-md tw-chart-series-2"></span><code class="tw:text-xs">orange-700</code></div> <div class="tw:text-center"><span class="tw:block tw:w-20 tw:h-12 tw:rounded-md tw-chart-series-3"></span><code class="tw:text-xs">magenta-700</code></div> <div class="tw:text-center"><span class="tw:block tw:w-20 tw:h-12 tw:rounded-md tw-chart-series-4"></span><code class="tw:text-xs">green-700</code></div> <div class="tw:text-center"><span class="tw:block tw:w-20 tw:h-12 tw:rounded-md tw-chart-series-5"></span><code class="tw:text-xs">primary-400</code></div> <div class="tw:text-center"><span class="tw:block tw:w-20 tw:h-12 tw:rounded-md tw-chart-series-other"></span><code class="tw:text-xs">other</code></div> </div> <div class="tw-callout tw:mt-4"> <p class="tw:mb-0 tw:text-sm"> <strong>Colour alone carries identity to two series.</strong> <code>blue-600</code> + <code>orange-700</code> measure ΔE 33.3 apart. From three, the legend and direct labels <em>are</em> the identity channel — not an accessibility garnish. Assign in fixed order, never cycled; beyond five, fold the tail into <code>.tw-chart-series-other</code> or use small multiples. A sixth hue is never generated. </p> </div> </div></div>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
<div class="tw:p-6 tw:max-w-7xl tw:mx-auto tw:space-y-8"> <!-- Introductory callout --> <div class="tw-callout"> <p class="tw:mb-1 tw:text-sm tw:font-mono"> <strong>CHART:</strong> two tiers, chosen by what the data does (DR-2026-14)<br> <strong>TIER 1:</strong> .tw-chart-bars — CSS comparison bars, no dependency<br> <strong>TIER 2:</strong> data-controller="chart" — Chart.js, lazy-loaded, the only sanctioned path </p> <p class="tw:mb-0 tw:text-sm"> Compare a handful of labelled magnitudes → Tier 1. Change over time, multiple series, axes → Tier 2. One headline number → a <strong>Stat Tile</strong>, not a chart. A share of a whole → the usage donut. Series colours are <strong>computed, not chosen</strong> — see the palette section below. </p> </div> <!-- Tier 1 --> <div class="tw:border-t tw:pt-6"> <h2 class="tw-h4 tw:mb-4">Tier 1 — CSS comparison bars</h2> <div class="tw-callout tw:mb-4"> <p class="tw:mb-0 tw:text-sm"> <strong>Bars:</strong> pure CSS, no JavaScript. Width comes from <code>tw:[--chart-value:64%]</code> — an arbitrary-property utility, never an inline style. Values use tabular figures so digits line up down the column. Consolidates the bar treatments hand-rolled across 17 prototype files. </p> </div> <div class="tw:grid tw:grid-cols-1 tw:lg:grid-cols-2 tw:gap-6"> <div class="tw-card"><div class="tw-card-body"> <h3 class="tw-card-title">Where enquiries come from</h3> <p class="tw:text-muted tw:text-sm tw:mb-4">Single series — no legend needed, the title names it.</p> <div class="tw-chart-bars"> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">Open days</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:76%]"></span></span> <span class="tw-chart-bar-value">76%</span> </div> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">School website</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:52%]"></span></span> <span class="tw-chart-bar-value">52%</span> </div> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">Word of mouth</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:38%]"></span></span> <span class="tw-chart-bar-value">38%</span> </div> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">Local authority</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:24%]"></span></span> <span class="tw-chart-bar-value">24%</span> </div> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">Other</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-other tw:[--chart-value:11%]"></span></span> <span class="tw-chart-bar-value">11%</span> </div> </div> </div></div> <div class="tw-card"><div class="tw-card-body"> <h3 class="tw-card-title">Applications by stage</h3> <p class="tw:text-muted tw:text-sm tw:mb-4">Multiple series — the legend is mandatory from two.</p> <div class="tw-chart-bars tw-chart-bars-sm"> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">Year 7</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:82%]"></span></span> <span class="tw-chart-bar-value">164</span> </div> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">Year 12</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-2 tw:[--chart-value:61%]"></span></span> <span class="tw-chart-bar-value">122</span> </div> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">In-year</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-3 tw:[--chart-value:34%]"></span></span> <span class="tw-chart-bar-value">68</span> </div> <div class="tw-chart-bar"> <span class="tw-chart-bar-label">Nursery</span> <span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-4 tw:[--chart-value:19%]"></span></span> <span class="tw-chart-bar-value">38</span> </div> </div> <div class="tw-chart-legend"> <span class="tw-chart-legend-item"><span class="tw-chart-legend-swatch tw-chart-series-1"></span>Year 7</span> <span class="tw-chart-legend-item"><span class="tw-chart-legend-swatch tw-chart-series-2"></span>Year 12</span> <span class="tw-chart-legend-item"><span class="tw-chart-legend-swatch tw-chart-series-3"></span>In-year</span> <span class="tw-chart-legend-item"><span class="tw-chart-legend-swatch tw-chart-series-4"></span>Nursery</span> </div> </div></div> </div> <div class="tw:mt-4 tw:text-sm tw:text-gray-600"> <code><div class="tw-chart-bar"><span class="tw-chart-bar-label">Open days</span><span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:76%]"></span></span><span class="tw-chart-bar-value">76%</span></div></code> </div> </div> <!-- Size + layout variants --> <div class="tw:border-t tw:pt-6"> <h2 class="tw-h4 tw:mb-4">Sizes and stacked labels</h2> <div class="tw:grid tw:grid-cols-1 tw:lg:grid-cols-3 tw:gap-6"> <div class="tw-card"><div class="tw-card-body"> <p class="tw:text-sm tw:font-medium tw:mb-3">Small</p> <div class="tw-chart-bars tw-chart-bars-sm"> <div class="tw-chart-bar"><span class="tw-chart-bar-label">Submitted</span><span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:70%]"></span></span><span class="tw-chart-bar-value">70%</span></div> <div class="tw-chart-bar"><span class="tw-chart-bar-label">In review</span><span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:45%]"></span></span><span class="tw-chart-bar-value">45%</span></div> </div> </div></div> <div class="tw-card"><div class="tw-card-body"> <p class="tw:text-sm tw:font-medium tw:mb-3">Large</p> <div class="tw-chart-bars tw-chart-bars-lg"> <div class="tw-chart-bar"><span class="tw-chart-bar-label">Submitted</span><span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:70%]"></span></span><span class="tw-chart-bar-value">70%</span></div> <div class="tw-chart-bar"><span class="tw-chart-bar-label">In review</span><span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:45%]"></span></span><span class="tw-chart-bar-value">45%</span></div> </div> </div></div> <div class="tw-card"><div class="tw-card-body"> <p class="tw:text-sm tw:font-medium tw:mb-3">Stacked labels — long names, narrow card</p> <div class="tw-chart-bars tw-chart-bars-stacked-labels"> <div class="tw-chart-bar"><span class="tw-chart-bar-label">St Mary's Catholic Primary</span><span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:64%]"></span></span><span class="tw-chart-bar-value">32</span></div> <div class="tw-chart-bar"><span class="tw-chart-bar-label">Brookfield Community School</span><span class="tw-chart-bar-track"><span class="tw-chart-bar-fill tw-chart-series-1 tw:[--chart-value:41%]"></span></span><span class="tw-chart-bar-value">21</span></div> </div> </div></div> </div> </div> <!-- Tier 2 --> <div class="tw:border-t tw:pt-6"> <h2 class="tw-h4 tw:mb-4">Tier 2 — the chart controller (Chart.js)</h2> <div class="tw-callout tw:mb-4"> <p class="tw:mb-0 tw:text-sm"> <strong>Plotted data:</strong> change over time, multiple series, axes. The <strong>only sanctioned path to Chart.js</strong> — no prototype imports it directly. Lazy-loaded on first reveal, so screens without charts pay nothing; colours resolve from <code>--tw-color-*</code> at runtime, so a token change repaints every chart. <strong>Omit <code>color</code> on a dataset and the ruled order is applied automatically</strong>, and the legend turns itself on from two series. </p> </div> <div class="tw:grid tw:grid-cols-1 tw:lg:grid-cols-2 tw:gap-6"> <div class="tw-card"><div class="tw-card-body"> <h3 class="tw-card-title">Applications received</h3> <p class="tw:text-muted tw:text-sm tw:mb-3">Two series, smoothed, no explicit colours.</p> <div class="tw:h-64" data-controller="chart" data-chart-type-value="line" data-chart-smooth-value="true" data-chart-axis-value="true" data-chart-labels-value='["Sep","Oct","Nov","Dec","Jan","Feb"]' data-chart-datasets-value='[{"label":"2026/27","data":[12,19,34,52,63,71]},{"label":"2025/26","data":[9,17,28,44,58,64]}]'> <canvas data-chart-target="canvas" role="img" aria-label="Applications received per month: 2026/27 rising from 12 in September to 71 in February, against 2025/26 rising from 9 to 64"></canvas> </div> </div></div> <div class="tw-card"><div class="tw-card-body"> <h3 class="tw-card-title">Offers by stage</h3> <p class="tw:text-muted tw:text-sm tw:mb-3">Stacked bars, y axis shown.</p> <div class="tw:h-64" data-controller="chart" data-chart-type-value="bar" data-chart-stacked-value="true" data-chart-axis-value="true" data-chart-labels-value='["Year 7","Year 12","In-year","Nursery"]' data-chart-datasets-value='[{"label":"Accepted","data":[96,74,31,22]},{"label":"Awaiting","data":[42,33,24,11]},{"label":"Declined","data":[26,15,13,5]}]'> <canvas data-chart-target="canvas" role="img" aria-label="Offers by intake and response: Year 7 96 accepted, 42 awaiting, 26 declined; Year 12 74, 33, 15; In-year 31, 24, 13; Nursery 22, 11, 5"></canvas> </div> </div></div> </div> <div class="tw:mt-4 tw:text-sm tw:text-gray-600"> <code><div data-controller="chart" data-chart-type-value="line" data-chart-labels-value='["Sep","Oct"]' data-chart-datasets-value='[{"label":"2026/27","data":[12,19]}]'><canvas data-chart-target="canvas" role="img" aria-label="…"></canvas></div></code> </div> </div> <!-- Palette --> <div class="tw:border-t tw:pt-6"> <h2 class="tw-h4 tw:mb-4">Series palette — computed, not chosen</h2> <div class="tw-callout tw:mb-4"> <p class="tw:mb-0 tw:text-sm"> The obvious approach — brand tokens at their <code>-500</code> steps in token order — <strong>fails</strong>: <code>orange-500</code>↔<code>green-500</code> separate by only ΔE 4.0 for deutan viewers, and both fall below 3:1 contrast. Two consequences: the brand navy <code>primary-500</code> is unusable as a series colour (too dark), and the series green is <code>green-700</code>, never the base lime. </p> </div> <div class="tw:flex tw:flex-wrap tw:gap-6"> <div class="tw:text-center"><span class="tw:block tw:w-20 tw:h-12 tw:rounded-md tw-chart-series-1"></span><code class="tw:text-xs">blue-600</code></div> <div class="tw:text-center"><span class="tw:block tw:w-20 tw:h-12 tw:rounded-md tw-chart-series-2"></span><code class="tw:text-xs">orange-700</code></div> <div class="tw:text-center"><span class="tw:block tw:w-20 tw:h-12 tw:rounded-md tw-chart-series-3"></span><code class="tw:text-xs">magenta-700</code></div> <div class="tw:text-center"><span class="tw:block tw:w-20 tw:h-12 tw:rounded-md tw-chart-series-4"></span><code class="tw:text-xs">green-700</code></div> <div class="tw:text-center"><span class="tw:block tw:w-20 tw:h-12 tw:rounded-md tw-chart-series-5"></span><code class="tw:text-xs">primary-400</code></div> <div class="tw:text-center"><span class="tw:block tw:w-20 tw:h-12 tw:rounded-md tw-chart-series-other"></span><code class="tw:text-xs">other</code></div> </div> <div class="tw-callout tw:mt-4"> <p class="tw:mb-0 tw:text-sm"> <strong>Colour alone carries identity to two series.</strong> <code>blue-600</code> + <code>orange-700</code> measure ΔE 33.3 apart. From three, the legend and direct labels <em>are</em> the identity channel — not an accessibility garnish. Assign in fixed order, never cycled; beyond five, fold the tail into <code>.tw-chart-series-other</code> or use small multiples. A sixth hue is never generated. </p> </div> </div></div>No notes provided.
No params configured.