Previews

No matching results.

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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
<div class="tw:p-6 tw:max-w-7xl tw:mx-auto tw:space-y-8">
<div class="callout">
<p class="tw:mb-1 tw:text-sm tw:font-mono">
<strong>CAROUSEL:</strong> Scroll-snap photo carousel for school/provider galleries<br>
<strong>VARIANTS:</strong> Track (arrows + dots) | Grid + Lightbox | Single image (controls hidden)
</p>
<p class="tw:mb-0 tw:text-sm">
CSS scroll-snap drives the motion — <code>carousel_controller.js</code> only computes
arrow/dot <code>scrollTo</code> targets and syncs active-slide state via an
IntersectionObserver (no scroll-event polling, no third-party carousel library).
Arrows disable at the ends rather than wrapping around (see the component doc's
"Ends behavior" section). Images below are inline SVG placeholders (no external
network calls) — swap for real `<img src="...">` in production use.
</p>
</div>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">Track carousel — school gallery (5 photos)</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Arrows + dots:</strong> click an arrow, click a dot, or focus the track and
use Left/Right. The active dot gets <code>aria-current="true"</code>; arrows disable
(native <code>disabled</code>) at the first/last photo. An sr-only status region
announces "Photo N of M: caption" on every change.
</p>
</div>
<div class="tw:max-w-xl" data-controller="carousel">
<div class="carousel">
<div class="carousel-track" data-carousel-target="track" tabindex="0"
role="region" aria-roledescription="carousel" aria-label="Greenford High School photo gallery"
data-action="keydown->carousel#keydown">
<div class="carousel-slide" data-carousel-target="slide">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23B08968'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='white' text-anchor='middle'%3EMain Building%3C/text%3E%3C/svg%3E"
alt="Main Building — the school's entrance and reception" width="400" height="225">
<div class="carousel-caption">Main Building</div>
</div>
<div class="carousel-slide" data-carousel-target="slide">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%238FB8DE'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='%23253A6A' text-anchor='middle'%3EScience Laboratory%3C/text%3E%3C/svg%3E"
alt="Science Laboratory — equipped for Key Stage 4 and A-Level practicals" width="400" height="225">
<div class="carousel-caption">Science Laboratory</div>
</div>
<div class="carousel-slide" data-carousel-target="slide">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%236B8E4E'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='white' text-anchor='middle'%3ESports Hall%3C/text%3E%3C/svg%3E"
alt="Sports Hall — indoor courts for PE and after-school clubs" width="400" height="225">
<div class="carousel-caption">Sports Hall</div>
</div>
<div class="carousel-slide" data-carousel-target="slide">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23A47551'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='white' text-anchor='middle'%3ELibrary and Study Centre%3C/text%3E%3C/svg%3E"
alt="Library and Study Centre — quiet study areas and group rooms" width="400" height="225">
<div class="carousel-caption">Library and Study Centre</div>
</div>
<div class="carousel-slide" data-carousel-target="slide">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23C9A66B'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='%23253A6A' text-anchor='middle'%3EDining Hall%3C/text%3E%3C/svg%3E"
alt="Dining Hall — seating for 200 students across two lunch sittings" width="400" height="225">
<div class="carousel-caption">Dining Hall</div>
</div>
</div>
<button type="button" class="carousel-arrow-prev" aria-label="Previous photo"
data-carousel-target="prev" data-action="click->carousel#prev">
<i class="fa-solid fa-chevron-left" aria-hidden="true"></i>
</button>
<button type="button" class="carousel-arrow-next" aria-label="Next photo"
data-carousel-target="next" data-action="click->carousel#next">
<i class="fa-solid fa-chevron-right" aria-hidden="true"></i>
</button>
</div>
<div class="carousel-dots" data-carousel-target="dots" role="group" aria-label="Photo navigation">
<button type="button" class="carousel-dot" aria-label="Go to photo 1"
data-carousel-target="dot" data-action="click->carousel#goToDot"></button>
<button type="button" class="carousel-dot" aria-label="Go to photo 2"
data-carousel-target="dot" data-action="click->carousel#goToDot"></button>
<button type="button" class="carousel-dot" aria-label="Go to photo 3"
data-carousel-target="dot" data-action="click->carousel#goToDot"></button>
<button type="button" class="carousel-dot" aria-label="Go to photo 4"
data-carousel-target="dot" data-action="click->carousel#goToDot"></button>
<button type="button" class="carousel-dot" aria-label="Go to photo 5"
data-carousel-target="dot" data-action="click->carousel#goToDot"></button>
</div>
<span class="tw:sr-only" aria-live="polite" data-carousel-target="status"></span>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><div data-controller="carousel"><div class="carousel"><div class="carousel-track" data-carousel-target="track" tabindex="0" data-action="keydown->carousel#keydown"><div class="carousel-slide" data-carousel-target="slide"><img src="..." alt="..."><div class="carousel-caption">Main Building</div></div>...</div><button class="carousel-arrow-prev" data-carousel-target="prev" data-action="click->carousel#prev">...</button><button class="carousel-arrow-next" data-carousel-target="next" data-action="click->carousel#next">...</button></div><div class="carousel-dots" data-carousel-target="dots"><button class="carousel-dot" data-carousel-target="dot" data-action="click->carousel#goToDot"></button>...</div></div></code>
</div>
</div>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">Grid + Lightbox</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Grid variant:</strong> a plain thumbnail grid — no scroll-snap track, no
<code>carousel_controller.js</code>. Each thumbnail is its own independent
<code>data-controller="popup"</code> instance; clicking it opens a
<code>.carousel-lightbox</code> (a dark, minimal-chrome <code>.popup-panel</code>
modifier) with the enlarged photo. Escape and backdrop-click close it — the popup
contract handles both, unchanged.
</p>
</div>
<div class="carousel-grid tw:max-w-2xl">
<div data-controller="popup">
<button type="button" class="carousel-grid-item" data-action="click->popup#show"
aria-label="View enlarged photo: Main Building">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23B08968'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='white' text-anchor='middle'%3EMain Building%3C/text%3E%3C/svg%3E"
alt="Main Building — the school's entrance and reception">
</button>
<div class="popup-overlay" data-popup-target="overlay" data-action="click->popup#handleOverlayClick"></div>
<div class="popup-panel popup-lg carousel-lightbox" data-popup-target="panel"
role="dialog" aria-modal="true" aria-labelledby="carousel-lightbox-title-1">
<div class="popup-header">
<h2 class="popup-header-title" id="carousel-lightbox-title-1">Main Building</h2>
<button class="popup-close" type="button" aria-label="Close" data-action="click->popup#close">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<div class="popup-body">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23B08968'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='white' text-anchor='middle'%3EMain Building%3C/text%3E%3C/svg%3E"
alt="Main Building — the school's entrance and reception">
</div>
</div>
</div>
<div data-controller="popup">
<button type="button" class="carousel-grid-item" data-action="click->popup#show"
aria-label="View enlarged photo: Science Laboratory">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%238FB8DE'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='%23253A6A' text-anchor='middle'%3EScience Laboratory%3C/text%3E%3C/svg%3E"
alt="Science Laboratory — equipped for Key Stage 4 and A-Level practicals">
</button>
<div class="popup-overlay" data-popup-target="overlay" data-action="click->popup#handleOverlayClick"></div>
<div class="popup-panel popup-lg carousel-lightbox" data-popup-target="panel"
role="dialog" aria-modal="true" aria-labelledby="carousel-lightbox-title-2">
<div class="popup-header">
<h2 class="popup-header-title" id="carousel-lightbox-title-2">Science Laboratory</h2>
<button class="popup-close" type="button" aria-label="Close" data-action="click->popup#close">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<div class="popup-body">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%238FB8DE'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='%23253A6A' text-anchor='middle'%3EScience Laboratory%3C/text%3E%3C/svg%3E"
alt="Science Laboratory — equipped for Key Stage 4 and A-Level practicals">
</div>
</div>
</div>
<div data-controller="popup">
<button type="button" class="carousel-grid-item" data-action="click->popup#show"
aria-label="View enlarged photo: Sports Hall">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%236B8E4E'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='white' text-anchor='middle'%3ESports Hall%3C/text%3E%3C/svg%3E"
alt="Sports Hall — indoor courts for PE and after-school clubs">
</button>
<div class="popup-overlay" data-popup-target="overlay" data-action="click->popup#handleOverlayClick"></div>
<div class="popup-panel popup-lg carousel-lightbox" data-popup-target="panel"
role="dialog" aria-modal="true" aria-labelledby="carousel-lightbox-title-3">
<div class="popup-header">
<h2 class="popup-header-title" id="carousel-lightbox-title-3">Sports Hall</h2>
<button class="popup-close" type="button" aria-label="Close" data-action="click->popup#close">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<div class="popup-body">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%236B8E4E'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='white' text-anchor='middle'%3ESports Hall%3C/text%3E%3C/svg%3E"
alt="Sports Hall — indoor courts for PE and after-school clubs">
</div>
</div>
</div>
<div data-controller="popup">
<button type="button" class="carousel-grid-item" data-action="click->popup#show"
aria-label="View enlarged photo: Library and Study Centre">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23A47551'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='26' fill='white' text-anchor='middle'%3ELibrary%3C/text%3E%3C/svg%3E"
alt="Library and Study Centre — quiet study areas and group rooms">
</button>
<div class="popup-overlay" data-popup-target="overlay" data-action="click->popup#handleOverlayClick"></div>
<div class="popup-panel popup-lg carousel-lightbox" data-popup-target="panel"
role="dialog" aria-modal="true" aria-labelledby="carousel-lightbox-title-4">
<div class="popup-header">
<h2 class="popup-header-title" id="carousel-lightbox-title-4">Library and Study Centre</h2>
<button class="popup-close" type="button" aria-label="Close" data-action="click->popup#close">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<div class="popup-body">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23A47551'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='26' fill='white' text-anchor='middle'%3ELibrary%3C/text%3E%3C/svg%3E"
alt="Library and Study Centre — quiet study areas and group rooms">
</div>
</div>
</div>
<div data-controller="popup">
<button type="button" class="carousel-grid-item" data-action="click->popup#show"
aria-label="View enlarged photo: Dining Hall">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23C9A66B'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='%23253A6A' text-anchor='middle'%3EDining Hall%3C/text%3E%3C/svg%3E"
alt="Dining Hall — seating for 200 students across two lunch sittings">
</button>
<div class="popup-overlay" data-popup-target="overlay" data-action="click->popup#handleOverlayClick"></div>
<div class="popup-panel popup-lg carousel-lightbox" data-popup-target="panel"
role="dialog" aria-modal="true" aria-labelledby="carousel-lightbox-title-5">
<div class="popup-header">
<h2 class="popup-header-title" id="carousel-lightbox-title-5">Dining Hall</h2>
<button class="popup-close" type="button" aria-label="Close" data-action="click->popup#close">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<div class="popup-body">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23C9A66B'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='%23253A6A' text-anchor='middle'%3EDining Hall%3C/text%3E%3C/svg%3E"
alt="Dining Hall — seating for 200 students across two lunch sittings">
</div>
</div>
</div>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><div data-controller="popup"><button class="carousel-grid-item" data-action="click->popup#show"><img src="..." alt="..."></button><div class="popup-overlay" data-popup-target="overlay" data-action="click->popup#handleOverlayClick"></div><div class="popup-panel popup-lg carousel-lightbox" data-popup-target="panel" role="dialog" aria-modal="true">...<div class="popup-body"><img src="..." alt="..."></div></div></div></code>
</div>
</div>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">Single image — controls hidden</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>One slide, nothing to navigate to:</strong> with a single
<code>.carousel-slide</code>, <code>carousel_controller.js</code> hides the arrows
and the dots row on connect (native <code>hidden</code> attribute) instead of
showing disabled-forever controls.
</p>
</div>
<div class="tw:max-w-xl" data-controller="carousel">
<div class="carousel">
<div class="carousel-track" data-carousel-target="track" tabindex="0"
role="region" aria-roledescription="carousel" aria-label="Open Day photo"
data-action="keydown->carousel#keydown">
<div class="carousel-slide" data-carousel-target="slide">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%2335A7E7'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='white' text-anchor='middle'%3EOpen Day 2026%3C/text%3E%3C/svg%3E"
alt="Open Day 2026 — students and families touring the campus" width="400" height="225">
<div class="carousel-caption">Open Day 2026</div>
</div>
</div>
<button type="button" class="carousel-arrow-prev" aria-label="Previous photo"
data-carousel-target="prev" data-action="click->carousel#prev">
<i class="fa-solid fa-chevron-left" aria-hidden="true"></i>
</button>
<button type="button" class="carousel-arrow-next" aria-label="Next photo"
data-carousel-target="next" data-action="click->carousel#next">
<i class="fa-solid fa-chevron-right" aria-hidden="true"></i>
</button>
</div>
<div class="carousel-dots" data-carousel-target="dots" role="group" aria-label="Photo navigation">
<button type="button" class="carousel-dot" aria-label="Go to photo 1"
data-carousel-target="dot" data-action="click->carousel#goToDot"></button>
</div>
<span class="tw:sr-only" aria-live="polite" data-carousel-target="status"></span>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><!-- one .carousel-slide inside .carousel-track — arrows/dots hidden on connect() --></code>
</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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
<div class="tw:p-6 tw:max-w-7xl tw:mx-auto tw:space-y-8">
<%# Introductory callout %>
<div class="callout">
<p class="tw:mb-1 tw:text-sm tw:font-mono">
<strong>CAROUSEL:</strong> Scroll-snap photo carousel for school/provider galleries<br>
<strong>VARIANTS:</strong> Track (arrows + dots) | Grid + Lightbox | Single image (controls hidden)
</p>
<p class="tw:mb-0 tw:text-sm">
CSS scroll-snap drives the motion — <code>carousel_controller.js</code> only computes
arrow/dot <code>scrollTo</code> targets and syncs active-slide state via an
IntersectionObserver (no scroll-event polling, no third-party carousel library).
Arrows disable at the ends rather than wrapping around (see the component doc's
"Ends behavior" section). Images below are inline SVG placeholders (no external
network calls) — swap for real `<img src="...">` in production use.
</p>
</div>
<%# Track carousel — school gallery %>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">Track carousel — school gallery (5 photos)</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Arrows + dots:</strong> click an arrow, click a dot, or focus the track and
use Left/Right. The active dot gets <code>aria-current="true"</code>; arrows disable
(native <code>disabled</code>) at the first/last photo. An sr-only status region
announces "Photo N of M: caption" on every change.
</p>
</div>
<div class="tw:max-w-xl" data-controller="carousel">
<div class="carousel">
<div class="carousel-track" data-carousel-target="track" tabindex="0"
role="region" aria-roledescription="carousel" aria-label="Greenford High School photo gallery"
data-action="keydown->carousel#keydown">
<div class="carousel-slide" data-carousel-target="slide">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23B08968'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='white' text-anchor='middle'%3EMain Building%3C/text%3E%3C/svg%3E"
alt="Main Building — the school's entrance and reception" width="400" height="225">
<div class="carousel-caption">Main Building</div>
</div>
<div class="carousel-slide" data-carousel-target="slide">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%238FB8DE'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='%23253A6A' text-anchor='middle'%3EScience Laboratory%3C/text%3E%3C/svg%3E"
alt="Science Laboratory — equipped for Key Stage 4 and A-Level practicals" width="400" height="225">
<div class="carousel-caption">Science Laboratory</div>
</div>
<div class="carousel-slide" data-carousel-target="slide">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%236B8E4E'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='white' text-anchor='middle'%3ESports Hall%3C/text%3E%3C/svg%3E"
alt="Sports Hall — indoor courts for PE and after-school clubs" width="400" height="225">
<div class="carousel-caption">Sports Hall</div>
</div>
<div class="carousel-slide" data-carousel-target="slide">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23A47551'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='white' text-anchor='middle'%3ELibrary and Study Centre%3C/text%3E%3C/svg%3E"
alt="Library and Study Centre — quiet study areas and group rooms" width="400" height="225">
<div class="carousel-caption">Library and Study Centre</div>
</div>
<div class="carousel-slide" data-carousel-target="slide">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23C9A66B'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='%23253A6A' text-anchor='middle'%3EDining Hall%3C/text%3E%3C/svg%3E"
alt="Dining Hall — seating for 200 students across two lunch sittings" width="400" height="225">
<div class="carousel-caption">Dining Hall</div>
</div>
</div>
<button type="button" class="carousel-arrow-prev" aria-label="Previous photo"
data-carousel-target="prev" data-action="click->carousel#prev">
<i class="fa-solid fa-chevron-left" aria-hidden="true"></i>
</button>
<button type="button" class="carousel-arrow-next" aria-label="Next photo"
data-carousel-target="next" data-action="click->carousel#next">
<i class="fa-solid fa-chevron-right" aria-hidden="true"></i>
</button>
</div>
<div class="carousel-dots" data-carousel-target="dots" role="group" aria-label="Photo navigation">
<button type="button" class="carousel-dot" aria-label="Go to photo 1"
data-carousel-target="dot" data-action="click->carousel#goToDot"></button>
<button type="button" class="carousel-dot" aria-label="Go to photo 2"
data-carousel-target="dot" data-action="click->carousel#goToDot"></button>
<button type="button" class="carousel-dot" aria-label="Go to photo 3"
data-carousel-target="dot" data-action="click->carousel#goToDot"></button>
<button type="button" class="carousel-dot" aria-label="Go to photo 4"
data-carousel-target="dot" data-action="click->carousel#goToDot"></button>
<button type="button" class="carousel-dot" aria-label="Go to photo 5"
data-carousel-target="dot" data-action="click->carousel#goToDot"></button>
</div>
<span class="tw:sr-only" aria-live="polite" data-carousel-target="status"></span>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><div data-controller="carousel"><div class="carousel"><div class="carousel-track" data-carousel-target="track" tabindex="0" data-action="keydown->carousel#keydown"><div class="carousel-slide" data-carousel-target="slide"><img src="..." alt="..."><div class="carousel-caption">Main Building</div></div>...</div><button class="carousel-arrow-prev" data-carousel-target="prev" data-action="click->carousel#prev">...</button><button class="carousel-arrow-next" data-carousel-target="next" data-action="click->carousel#next">...</button></div><div class="carousel-dots" data-carousel-target="dots"><button class="carousel-dot" data-carousel-target="dot" data-action="click->carousel#goToDot"></button>...</div></div></code>
</div>
</div>
<%# Grid + Lightbox %>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">Grid + Lightbox</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>Grid variant:</strong> a plain thumbnail grid — no scroll-snap track, no
<code>carousel_controller.js</code>. Each thumbnail is its own independent
<code>data-controller="popup"</code> instance; clicking it opens a
<code>.carousel-lightbox</code> (a dark, minimal-chrome <code>.popup-panel</code>
modifier) with the enlarged photo. Escape and backdrop-click close it — the popup
contract handles both, unchanged.
</p>
</div>
<div class="carousel-grid tw:max-w-2xl">
<div data-controller="popup">
<button type="button" class="carousel-grid-item" data-action="click->popup#show"
aria-label="View enlarged photo: Main Building">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23B08968'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='white' text-anchor='middle'%3EMain Building%3C/text%3E%3C/svg%3E"
alt="Main Building — the school's entrance and reception">
</button>
<div class="popup-overlay" data-popup-target="overlay" data-action="click->popup#handleOverlayClick"></div>
<div class="popup-panel popup-lg carousel-lightbox" data-popup-target="panel"
role="dialog" aria-modal="true" aria-labelledby="carousel-lightbox-title-1">
<div class="popup-header">
<h2 class="popup-header-title" id="carousel-lightbox-title-1">Main Building</h2>
<button class="popup-close" type="button" aria-label="Close" data-action="click->popup#close">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<div class="popup-body">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23B08968'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='white' text-anchor='middle'%3EMain Building%3C/text%3E%3C/svg%3E"
alt="Main Building — the school's entrance and reception">
</div>
</div>
</div>
<div data-controller="popup">
<button type="button" class="carousel-grid-item" data-action="click->popup#show"
aria-label="View enlarged photo: Science Laboratory">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%238FB8DE'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='%23253A6A' text-anchor='middle'%3EScience Laboratory%3C/text%3E%3C/svg%3E"
alt="Science Laboratory — equipped for Key Stage 4 and A-Level practicals">
</button>
<div class="popup-overlay" data-popup-target="overlay" data-action="click->popup#handleOverlayClick"></div>
<div class="popup-panel popup-lg carousel-lightbox" data-popup-target="panel"
role="dialog" aria-modal="true" aria-labelledby="carousel-lightbox-title-2">
<div class="popup-header">
<h2 class="popup-header-title" id="carousel-lightbox-title-2">Science Laboratory</h2>
<button class="popup-close" type="button" aria-label="Close" data-action="click->popup#close">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<div class="popup-body">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%238FB8DE'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='%23253A6A' text-anchor='middle'%3EScience Laboratory%3C/text%3E%3C/svg%3E"
alt="Science Laboratory — equipped for Key Stage 4 and A-Level practicals">
</div>
</div>
</div>
<div data-controller="popup">
<button type="button" class="carousel-grid-item" data-action="click->popup#show"
aria-label="View enlarged photo: Sports Hall">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%236B8E4E'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='white' text-anchor='middle'%3ESports Hall%3C/text%3E%3C/svg%3E"
alt="Sports Hall — indoor courts for PE and after-school clubs">
</button>
<div class="popup-overlay" data-popup-target="overlay" data-action="click->popup#handleOverlayClick"></div>
<div class="popup-panel popup-lg carousel-lightbox" data-popup-target="panel"
role="dialog" aria-modal="true" aria-labelledby="carousel-lightbox-title-3">
<div class="popup-header">
<h2 class="popup-header-title" id="carousel-lightbox-title-3">Sports Hall</h2>
<button class="popup-close" type="button" aria-label="Close" data-action="click->popup#close">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<div class="popup-body">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%236B8E4E'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='white' text-anchor='middle'%3ESports Hall%3C/text%3E%3C/svg%3E"
alt="Sports Hall — indoor courts for PE and after-school clubs">
</div>
</div>
</div>
<div data-controller="popup">
<button type="button" class="carousel-grid-item" data-action="click->popup#show"
aria-label="View enlarged photo: Library and Study Centre">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23A47551'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='26' fill='white' text-anchor='middle'%3ELibrary%3C/text%3E%3C/svg%3E"
alt="Library and Study Centre — quiet study areas and group rooms">
</button>
<div class="popup-overlay" data-popup-target="overlay" data-action="click->popup#handleOverlayClick"></div>
<div class="popup-panel popup-lg carousel-lightbox" data-popup-target="panel"
role="dialog" aria-modal="true" aria-labelledby="carousel-lightbox-title-4">
<div class="popup-header">
<h2 class="popup-header-title" id="carousel-lightbox-title-4">Library and Study Centre</h2>
<button class="popup-close" type="button" aria-label="Close" data-action="click->popup#close">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<div class="popup-body">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23A47551'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='26' fill='white' text-anchor='middle'%3ELibrary%3C/text%3E%3C/svg%3E"
alt="Library and Study Centre — quiet study areas and group rooms">
</div>
</div>
</div>
<div data-controller="popup">
<button type="button" class="carousel-grid-item" data-action="click->popup#show"
aria-label="View enlarged photo: Dining Hall">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23C9A66B'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='%23253A6A' text-anchor='middle'%3EDining Hall%3C/text%3E%3C/svg%3E"
alt="Dining Hall — seating for 200 students across two lunch sittings">
</button>
<div class="popup-overlay" data-popup-target="overlay" data-action="click->popup#handleOverlayClick"></div>
<div class="popup-panel popup-lg carousel-lightbox" data-popup-target="panel"
role="dialog" aria-modal="true" aria-labelledby="carousel-lightbox-title-5">
<div class="popup-header">
<h2 class="popup-header-title" id="carousel-lightbox-title-5">Dining Hall</h2>
<button class="popup-close" type="button" aria-label="Close" data-action="click->popup#close">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<div class="popup-body">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%23C9A66B'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='%23253A6A' text-anchor='middle'%3EDining Hall%3C/text%3E%3C/svg%3E"
alt="Dining Hall — seating for 200 students across two lunch sittings">
</div>
</div>
</div>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><div data-controller="popup"><button class="carousel-grid-item" data-action="click->popup#show"><img src="..." alt="..."></button><div class="popup-overlay" data-popup-target="overlay" data-action="click->popup#handleOverlayClick"></div><div class="popup-panel popup-lg carousel-lightbox" data-popup-target="panel" role="dialog" aria-modal="true">...<div class="popup-body"><img src="..." alt="..."></div></div></div></code>
</div>
</div>
<%# Single image — controls hidden %>
<div class="tw:border-t tw:pt-6">
<h2 class="h4 tw:mb-4">Single image — controls hidden</h2>
<div class="callout tw:mb-4">
<p class="tw:mb-0 tw:text-sm">
<strong>One slide, nothing to navigate to:</strong> with a single
<code>.carousel-slide</code>, <code>carousel_controller.js</code> hides the arrows
and the dots row on connect (native <code>hidden</code> attribute) instead of
showing disabled-forever controls.
</p>
</div>
<div class="tw:max-w-xl" data-controller="carousel">
<div class="carousel">
<div class="carousel-track" data-carousel-target="track" tabindex="0"
role="region" aria-roledescription="carousel" aria-label="Open Day photo"
data-action="keydown->carousel#keydown">
<div class="carousel-slide" data-carousel-target="slide">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='225'%3E%3Crect width='400' height='225' fill='%2335A7E7'/%3E%3Ctext x='200' y='118' font-family='sans-serif' font-size='22' fill='white' text-anchor='middle'%3EOpen Day 2026%3C/text%3E%3C/svg%3E"
alt="Open Day 2026 — students and families touring the campus" width="400" height="225">
<div class="carousel-caption">Open Day 2026</div>
</div>
</div>
<button type="button" class="carousel-arrow-prev" aria-label="Previous photo"
data-carousel-target="prev" data-action="click->carousel#prev">
<i class="fa-solid fa-chevron-left" aria-hidden="true"></i>
</button>
<button type="button" class="carousel-arrow-next" aria-label="Next photo"
data-carousel-target="next" data-action="click->carousel#next">
<i class="fa-solid fa-chevron-right" aria-hidden="true"></i>
</button>
</div>
<div class="carousel-dots" data-carousel-target="dots" role="group" aria-label="Photo navigation">
<button type="button" class="carousel-dot" aria-label="Go to photo 1"
data-carousel-target="dot" data-action="click->carousel#goToDot"></button>
</div>
<span class="tw:sr-only" aria-live="polite" data-carousel-target="status"></span>
</div>
<div class="tw:mt-4 tw:text-sm tw:text-gray-600">
<code><!-- one .carousel-slide inside .carousel-track — arrows/dots hidden on connect() --></code>
</div>
</div>
</div>