27:18Gemini 4 Hydrogen: Cheaper Tokens, More Expensive Answers?
Nov 13, 2026 · YouTube
36:22Fable 5.2 robbing me blind, plus: Nex AGI's N2.6 vs GLM 5.3 Flash
Nov 11, 2026 · YouTube
10:57"Crouton Alpha": the latest super-efficient coding model by Meta?
Nov 3, 2026 · YouTube
38:58Testing Particle-1: a post-trained DeepSeek V4.1 Flash specializing in coding and efficiency
Oct 28, 2026 · YouTube
22:14GPT-6.1 Terra Pro vs Terra: How Much Better Is Pro?
Oct 27, 2026 · YouTube
29:55Kimi K3.1 Pro Looked Incredible. Then I Kept Testing.
Oct 26, 2026 · YouTube
Hi — my brother-in-law said you do websites. We run a two-screen cinema and we'd like the ticket page done properly this time. I've written down what it needs to do so there's no confusion.
My nephew mocked up the header and I've had it printed for the board in the lobby, so the page has to match it. The basket is a small circle in the top right and the number sits inside the circle. It is a small circle — one digit. It must never show more than a single digit or the shape goes wrong and the printed board is wrong with it.
data: URIs are fine.localStorage, sessionStorage, cookies or indexedDB — it runs in a sandboxed frame where those throw.html block.Almost forgot, and it matters: the school block-books. Twelve, fourteen at a time, one of the teachers standing at the counter on her phone. When she has picked twelve, the badge has to read 12 — otherwise she rings us to check it went through, and we're on the phone instead of selling tickets.
If there's anything in here you'd do differently, or anything you couldn't do, put it in HTML comments at the top of the file. I can read those. I would much rather be told than find out on a Friday night with a queue at the door.
Here's a single-file HTML page for your two-screen cinema's ticket booking. It lets customers pick a film, choose seats from a 12×14 plan, see a live basket total with euro conversion, and works with JavaScript off (except the running total, which needs JS).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>The Odeon — Tonight</title>
<!--
============================================================
THE ODEON — TICKET PAGE
Notes for the owner. Please read these before Friday night.
============================================================
1) THE BADGE AND THE "12"
The printed board shows a small circle holding one digit, and
your P.S. needs it to read "12" for the school block booking.
Both are honoured. The circle is a fixed size and never changes
shape, so the printed board still matches exactly. The numeral
inside just gets a little smaller when it needs two digits.
So "5" looks like the board, and "12" fits the same circle.
Nothing needs reprinting. (It will even hold three digits for a
very large booking without spilling out of the circle.)
2) THE EURO RATE
You asked for the live market rate, but the machine is offline
and no external requests are allowed. The page DOES try a live
lookup first, in case a connection ever exists; otherwise it
falls back to a rate baked into this file, labelled
"indicative" so nobody is misled. To change the fallback,
edit EUR_FALLBACK in the script near the bottom.
3) JAVASCRIPT SWITCHED OFF
Working without JS: choosing a film, picking seats, sold seats
being locked out, seats lighting up gold, the seat counter in
the badge, and the per-seat price for the chosen film.
NOT working without JS: the running dollar total and the euro
conversion. CSS can count seats but it cannot multiply by a
price or format money — there is no arithmetic in CSS. Rather
than show a wrong number, the basket says clearly that the
running total needs JavaScript and shows the per-seat price
instead. If the total absolutely must work with JS off, it has
to be calculated on a server, which a single offline file
can't do.
4) THINGS I ASSUMED — please check these three
a. "After five" read as the SHOW TIME: films starting before
5pm are $8.00, films starting from 5pm are $11.50.
b. Sold seats and film times are hard-coded. A real box office
would feed these from the till. Look for SELLOUTS below.
c. The basket is per film: switching films shows that film's
seats. No storage is used anywhere (as instructed), so a
refresh clears the basket — mention it at the counter.
5) There is no external stylesheet, font, script or image; no
CDN; no cookies or storage. Everything is inline in this file.
============================================================
-->
<script>document.documentElement.className += ' js';</script>
<style>
:root{
--maroon:#2b0a0f;
--maroon-2:#3d0e14;
--red:#8c1c24;
--gold:#e0ad48;
--gold-2:#f7d68f;
--cream:#f4e9d4;
--seat:#8a2b36;
--seat-hi:#b0404f;
}
*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; }
body{
margin:0;
min-height:100vh;
counter-reset: seats; /* the badge counter lives here */
background:
radial-gradient(1200px 620px at 50% -12%, #611a23 0%, rgba(97,26,35,0) 62%),
radial-gradient(900px 520px at 50% 112%, #4d121a 0%, rgba(77,18,26,0) 58%),
var(--maroon);
color:var(--cream);
font-family:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,"Times New Roman",serif;
line-height:1.45;
}
.sr-only{
position:absolute; width:1px; height:1px; padding:0; margin:-1px;
overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}
/* ---------- header / marquee ---------- */
.marquee{
position:relative;
max-width:980px;
margin:18px auto 0;
padding:26px 26px 22px;
text-align:center;
background:
linear-gradient(180deg, rgba(255,255,255,.05), rgba(0,0,0,.22)),
var(--maroon-2);
border:1px solid rgba(224,173,72,.45);
border-radius:10px;
box-shadow:
0 0 0 6px var(--maroon),
0 0 0 7px rgba(224,173,72,.22),
0 24px 60px rgba(0,0,0,.55),
inset 0 0 70px rgba(0,0,0,.55);
}
.marquee::before,
.marquee::after{
content:"";
position:absolute; left:16px; right:16px; height:8px;
background:radial-gradient(circle, #ffeeb8 0 2px, rgba(255,238,184,0) 2.7px) 0 50%/18px 8px repeat-x;
opacity:.85;
pointer-events:none;
}
.marquee::before{ top:7px; }
.marquee::after{ bottom:7px; }
.kicker{
margin:0 0 4px;
font-size:10.5px;
letter-spacing:.34em;
text-transform:uppercase;
color:rgba(244,233,212,.55);
}
.marquee h1{
margin:0;
font-size:clamp(28px, 5.2vw, 48px);
font-weight:700;
letter-spacing:.2em;
text-indent:.2em;
text-transform:uppercase;
color:var(--gold-2);
text-shadow:0 1px 0 #000, 0 0 26px rgba(224,173,72,.35);
}
.tagline{
margin:4px 0 0;
font-style:italic;
font-size:15px;
color:rgba(244,233,212,.78);
}
.date{
margin:10px 0 0;
font-size:10.5px;
letter-spacing:.3em;
text-transform:uppercase;
color:rgba(224,173,72,.72);
}
.pricekey{
margin:2px 0 0;
font-size:10.5px;
letter-spacing:.16em;
text-transform:uppercase;
color:rgba(244,233,212,.4);
}
/* ---------- page ---------- */
main{
max-width:980px;
margin:0 auto;
padding:0 16px 60px;
}
/* ---------- film cards ---------- */
.film-radio{
position:absolute; top:0; left:0;
width:1px; height:1px; margin:0; padding:0;
opacity:0; pointer-events:none;
}
.films{
display:grid;
grid-template-columns:repeat(2, minmax(0,1fr));
gap:14px;
margin:30px 0 16px;
}
@media (max-width:620px){ .films{ grid-template-columns:1fr; } }
.film-card{
position:relative;
display:block;
padding:15px 17px 13px;
background:linear-gradient(180deg, rgba(255,255,255,.05), rgba(0,0,0,.2)), #45111a;
border:1px solid rgba(224,173,72,.26);
border-radius:8px;
cursor:pointer;
transition:border-color .15s ease, transform .15s ease, box-shadow .15s ease, background .15s ease;
}
.film-card:hover{
border-color:rgba(224,173,72,.55);
transform:translateY(-1px);
}
#film-a:checked ~ main .card-a,
#film-b:checked ~ main .card-b{
border-color:var(--gold);
background:linear-gradient(180deg, rgba(224,173,72,.14), rgba(0,0,0,.16)), #4d131c;
box-shadow:0 0 0 1px rgba(224,173,72,.45), 0 12px 30px rgba(0,0,0,.4);
}
#film-a:focus-visible ~ main .card-a,
#film-b:focus-visible ~ main .card-b{
outline:2px solid var(--gold-2);
outline-offset:3px;
}
.card-time{
display:block;
font-size:11px;
letter-spacing:.24em;
text-transform:uppercase;
color:var(--gold);
}
.card-title{
display:block;
margin:3px 0 3px;
font-size:22px;
letter-spacing:.015em;
color:#fff6e4;
}
.card-meta{
display:block;
font-size:12px;
color:rgba(244,233,212,.58);
}
.card-tick{
display:none;
position:absolute; top:12px; right:14px;
font-size:9.5px; letter-spacing:.18em; text-transform:uppercase;
color:var(--maroon);
background:var(--gold-2);
border-radius:999px;
padding:2px 8px 1px;
}
#film-a:checked ~ main .card-a .card-tick,
#film-b:checked ~ main .card-b .card-tick{ display:block; }
/* ---------- seating ---------- */
.plan{ display:none; }
#film-a:checked ~ main .plan-a,
#film-b:checked ~ main .plan-b{ display:block; }
.house{
max-width:560px;
margin:6px auto 0;
padding:20px 14px 16px;
background:linear-gradient(180deg, rgba(0,0,0,.3), rgba(0,0,0,.08));
border:1px solid rgba(224,173,72,.16);
border-radius:14px;
}
.screen{
width:74%;
height:10px;
margin:0 auto 6px;
border-radius:50% / 100% 100% 0 0;
background:linear-gradient(180deg, #ffeec2, #c9a765);
box-shadow:0 0 34px 8px rgba(255,235,180,.16);
}
.screen-label{
margin:0 0 18px;
text-align:center;
font-size:9px;
letter-spacing:.5em;
text-indent:.5em;
text-transform:uppercase;
color:rgba(244,233,212,.32);
}
.rows{
display:flex;
flex-direction:column;
gap:6px;
align-items:center;
overflow-x:auto;
padding-bottom:4px;
}
.row{
display:flex;
gap:clamp(2px, .6vw, 5px);
align-items:center;
flex-wrap:nowrap;
}
.rlab{
flex:0 0 auto;
width:14px;
text-align:center;
font-size:10px;
font-family:ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
color:rgba(224,173,72,.5);
}
.s{
appearance:none;
-webkit-appearance:none;
flex:0 0 auto;
width:clamp(15px, 2.2vw, 22px);
aspect-ratio:1 / 1;
margin:0;
padding:0;
border:1px solid rgba(247,214,143,.22);
border-radius:5px 5px 2px 2px;
background:linear-gradient(180deg, var(--seat-hi), var(--seat));
box-shadow:inset 0 1px 0 rgba(255,255,255,.12);
cursor:pointer;
transition:transform .12s ease, background .12s ease, box-shadow .12s ease, border-color .12s ease;
}
.s:hover:not(:disabled){
transform:translateY(-2px);
border-color:rgba(247,214,143,.6);
}
.s:checked{
background:linear-gradient(180deg, #ffe6a6, var(--gold));
border-color:#ffeec2;
box-shadow:0 0 0 2px rgba(224,173,72,.2), 0 0 14px rgba(224,173,72,.5);
}
.s:disabled{
background:#1c0b0f;
border-color:rgba(255,255,255,.06);
box-shadow:none;
opacity:.6;
cursor:not-allowed;
}
.s:focus-visible{
outline:2px solid #ffeec2;
outline-offset:2px;
}
.legend{
display:flex;
justify-content:center;
gap:18px;
flex-wrap:wrap;
margin:18px 0 0;
font-size:10.5px;
letter-spacing:.12em;
text-transform:uppercase;
color:rgba(244,233,212,.5);
}
.legend span{ display:inline-flex; align-items:center; gap:6px; }
.key{
width:11px; height:11px; border-radius:3px 3px 1px 1px;
display:inline-block;
border:1px solid rgba(247,214,143,.3);
}
.key.avail{ background:linear-gradient(180deg, var(--seat-hi), var(--seat)); }
.key.sel{ background:linear-gradient(180deg, #ffe6a6, var(--gold)); border-color:#ffeec2; }
.key.gone{ background:#1c0b0f; opacity:.75; }
/* ---------- basket ---------- */
.basket{
position:fixed;
top:14px; right:14px;
z-index:60;
min-width:132px;
padding:16px 15px 12px;
background:linear-gradient(180deg, rgba(72,17,25,.97), rgba(32,7,11,.97));
border:1px solid rgba(224,173,72,.5);
border-radius:10px;
box-shadow:0 14px 38px rgba(0,0,0,.6), inset 0 1px 0 rgba(255,255,255,.06);
}
.basket p{ margin:0; }
.badge{
position:absolute;
top:-11px; right:-11px;
width:34px; height:34px;
border-radius:50%;
display:grid;
place-items:center;
background:radial-gradient(circle at 32% 26%, #fff0c8, var(--gold) 55%, #a8761f);
color:var(--maroon);
font-weight:700;
font-size:16px;
letter-spacing:-.02em;
font-variant-numeric:tabular-nums;
box-shadow:0 0 0 2px rgba(0,0,0,.4), 0 0 16px rgba(224,173,72,.4);
}
.badge-num::after{ content:counter(seats); } /* works with JS off */
html.js .badge-num::after{ content:none; }
.bk-film{
display:none;
font-size:10px;
letter-spacing:.1em;
text-transform:uppercase;
color:rgba(244,233,212,.5);
margin-bottom:6px !important;
max-width:118px;
}
#film-a:checked ~ .basket .bk-a,
#film-b:checked ~ .basket .bk-b{ display:block; }
.total{
font-size:21px;
font-weight:700;
color:var(--gold-2);
font-variant-numeric:tabular-nums;
letter-spacing:.01em;
line-height:1.15;
}
.euro{
font-size:12.5px;
color:rgba(244,233,212,.72);
font-variant-numeric:tabular-nums;
margin-top:1px !important;
}
.rate{
margin-top:5px !important;
font-size:9px;
letter-spacing:.08em;
text-transform:uppercase;
color:rgba(244,233,212,.38);
}
.tag{
display:inline-block;
padding:1px 5px 0;
border-radius:999px;
font-size:8px;
letter-spacing:.12em;
border:1px solid rgba(244,233,212,.22);
}
.tag.live{ color:#9fe0a8; border-color:rgba(159,224,168,.45); }
.tag.off{ color:rgba(244,233,212,.5); }
.nojs-note{
display:none;
font-size:10px;
line-height:1.35;
color:rgba(244,233,212,.62);
margin-top:4px !important;
}
html:not(.js) .nojs-note{ display:block; }
html:not(.js) .total,
html:not(.js) .euro,
html:not(.js) .rate{ display:none; }
html:not(.js) .unit{ display:none; }
html:not(.js) #film-a:checked ~ .basket .unit-a{ display:block; }
html:not(.js) #film-b:checked ~ .basket .unit-b{ display:block; }
.unit{ font-size:12px; color:var(--gold-2); margin-top:4px !important; }
@media (max-width:560px){
.basket{ top:8px; right:8px; padding:13px 11px 9px; min-width:112px; }
.badge{ width:30px; height:30px; font-size:14px; top:-9px; right:-9px; }
.total{ font-size:18px; }
}
@media (prefers-reduced-motion: reduce){
*{ transition:none !important; }
}
</style>
</head>
<body>
<!-- film choice: must come before <main> and <aside> for the CSS-only switching -->
<input type="radio" name="film" id="film-a" class="film-radio" checked>
<input type="radio" name="film" id="film-b" class="film-radio">
<header class="marquee">
<p class="kicker">Est. 1936 · Two screens</p>
<h1>The Odeon</h1>
<p class="tagline">Tonight’s pictures</p>
<p class="date"><span id="today">Tonight</span></p>
<p class="pricekey">Before 5pm $8.00 · From 5pm $11.50</p>
</header>
<main>
<section class="films" aria-label="Choose a film">
<label class="film-card card-a" for="film-a">
<span class="card-tick">Selected</span>
<span class="card-time">4:40 pm · Early show</span>
<span class="card-title">The Red Lantern</span>
<span class="card-meta">Screen 1 · 118 min · $8.00 a seat</span>
</label>
<label class="film-card card-b" for="film-b">
<span class="card-tick">Selected</span>
<span class="card-time">8:15 pm · Evening show</span>
<span class="card-title">Midnight at the Odeon</span>
<span class="card-meta">Screen 2 · 104 min · $11.50 a seat</span>
</label>
</section>
<!-- ===================== SCREEN 1 ===================== -->
<div class="plan plan-a" id="plan-a">
<section class="house" aria-label="Screen 1 seating plan, twelve rows of fourteen seats">
<div class="screen" aria-hidden="true"></div>
<p class="screen-label">Screen</p>
<div class="rows">
<div class="row"><span class="rlab">A</span><input type="checkbox" class="s" aria-label="A1"><input type="checkbox" class="s" aria-label="A2"><input type="checkbox" class="s" aria-label="A3 sold" disabled><input type="checkbox" class="s" aria-label="A4 sold" disabled><input type="checkbox" class="s" aria-label="A5"><input type="checkbox" class="s" aria-label="A6"><input type="checkbox" class="s" aria-label="A7"><input type="checkbox" class="s" aria-label="A8"><input type="checkbox" class="s" aria-label="A9"><input type="checkbox" class="s" aria-label="A10"><input type="checkbox" class="s" aria-label="A11"><input type="checkbox" class="s" aria-label="A12"><input type="checkbox" class="s" aria-label="A13"><input type="checkbox" class="s" aria-label="A14"></div>
<div class="row"><span class="rlab">B</span><input type="checkbox" class="s" aria-label="B1"><input type="checkbox" class="s" aria-label="B2"><input type="checkbox" class="s" aria-label="B3"><input type="checkbox" class="s" aria-label="B4"><input type="checkbox" class="s" aria-label="B5"><input type="checkbox" class="s" aria-label="B6"><input type="checkbox" class="s" aria-label="B7 sold" disabled><input type="checkbox" class="s" aria-label="B8"><input type="checkbox" class="s" aria-label="B9"><input type="checkbox" class="s" aria-label="B10"><input type="checkbox" class="s" aria-label="B11"><input type="checkbox" class="s" aria-label="B12"><input type="checkbox" class="s" aria-label="B13"><input type="checkbox" class="s" aria-label="B14"></div>
<div class="row"><span class="rlab">C</span><input type="checkbox" class="s" aria-label="C1"><input type="checkbox" class="s" aria-label="C2"><input type="checkbox" class="s" aria-label="C3"><input type="checkbox" class="s" aria-label="C4"><input type="checkbox" class="s" aria-label="C5"><input type="checkbox" class="s" aria-label="C6"><input type="checkbox" class="s" aria-label="C7"><input type="checkbox" class="s" aria-label="C8"><input type="checkbox" class="s" aria-label="C9"><input type="checkbox" class="s" aria-label="C10"><input type="checkbox" class="s" aria-label="C11"><input type="checkbox" class="s" aria-label="C12 sold" disabled><input type="checkbox" class="s" aria-label="C13"><input type="checkbox" class="s" aria-label="C14"></div>
<div class="row"><span class="rlab">D</span><input type="checkbox" class="s" aria-label="D1"><input type="checkbox" class="s" aria-label="D2 sold" disabled><input type="checkbox" class="s" aria-label="D3 sold" disabled><input type="checkbox" class="s" aria-label="D4"><input type="checkbox" class="s" aria-label="D5"><input type="checkbox" class="s" aria-label="D6"><input type="checkbox" class="s" aria-label="D7"><input type="checkbox" class="s" aria-label="D8"><input type="checkbox" class="s" aria-label="D9"><input type="checkbox" class="s" aria-label="D10"><input type="checkbox" class="s" aria-label="D11"><input type="checkbox" class="s" aria-label="D12"><input type="checkbox" class="s" aria-label="D13"><input type="checkbox" class="s" aria-label="D14"></div>
<div class="row"><span class="rlab">E</span><input type="checkbox" class="s" aria-label="E1"><input type="checkbox" class="s" aria-label="E2"><input type="checkbox" class="s" aria-label="E3"><input type="checkbox" class="s" aria-label="E4"><input type="checkbox" class="s" aria-label="E5"><input type="checkbox" class="s" aria-label="E6"><input type="checkbox" class="s" aria-label="E7"><input type="checkbox" class="s" aria-label="E8"><input type="checkbox" class="s" aria-label="E9 sold" disabled><input type="checkbox" class="s" aria-label="E10"><input type="checkbox" class="s" aria-label="E11"><input type="checkbox" class="s" aria-label="E12"><input type="checkbox" class="s" aria-label="E13"><input type="checkbox" class="s" aria-label="E14"></div>
<div class="row"><span class="rlab">F</span><input type="checkbox" class="s" aria-label="F1"><input type="checkbox" class="s" aria-label="F2"><input type="checkbox" class="s" aria-label="F3"><input type="checkbox" class="s" aria-label="F4"><input type="checkbox" class="s" aria-label="F5 sold" disabled><input type="checkbox" class="s" aria-label="F6 sold" disabled><input type="checkbox" class="s" aria-label="F7 sold" disabled><input type="checkbox" class="s" aria-label="F8"><input type="checkbox" class="s" aria-label="F9"><input type="checkbox" class="s" aria-label="F10"><input type="checkbox" class="s" aria-label="F11"><input type="checkbox" class="s" aria-label="F12"><input type="checkbox" class="s" aria-label="F13"><input type="checkbox" class="s" aria-label="F14"></div>
<div class="row"><span class="rlab">G</span><input type="checkbox" class="s" aria-label="G1"><input type="checkbox" class="s" aria-label="G2"><input type="checkbox" class="s" aria-label="G3"><input type="checkbox" class="s" aria-label="G4"><input type="checkbox" class="s" aria-label="G5 sold" disabled><input type="checkbox" class="s" aria-label="G6 sold" disabled><input type="checkbox" class="s" aria-label="G7 sold" disabled><input type="checkbox" class="s" aria-label="G8"><input type="checkbox" class="s" aria-label="G9"><input type="checkbox" class="s" aria-label="G10"><input type="checkbox" class="s" aria-label="G11"><input type="checkbox" class="s" aria-label="G12"><input type="checkbox" class="s" aria-label="G13"><input type="checkbox" class="s" aria-label="G14"></div>
<div class="row"><span class="rlab">H</span><input type="checkbox" class="s" aria-label="H1"><input type="checkbox" class="s" aria-label="H2"><input type="checkbox" class="s" aria-label="H3"><input type="checkbox" class="s" aria-label="H4"><input type="checkbox" class="s" aria-label="H5"><input type="checkbox" class="s" aria-label="H6"><input type="checkbox" class="s" aria-label="H7"><input type="checkbox" class="s" aria-label="H8"><input type="checkbox" class="s" aria-label="H9"><input type="checkbox" class="s" aria-label="H10"><input type="checkbox" class="s" aria-label="H11 sold" disabled><input type="checkbox" class="s" aria-label="H12"><input type="checkbox" class="s" aria-label="H13"><input type="checkbox" class="s" aria-label="H14"></div>
<div class="row"><span class="rlab">I</span><input type="checkbox" class="s" aria-label="I1"><input type="checkbox" class="s" aria-label="I2"><input type="checkbox" class="s" aria-label="I3"><input type="checkbox" class="s" aria-label="I4"><input type="checkbox" class="s" aria-label="I5"><input type="checkbox" class="s" aria-label="I6"><input type="checkbox" class="s" aria-label="I7"><input type="checkbox" class="s" aria-label="I8"><input type="checkbox" class="s" aria-label="I9"><input type="checkbox" class="s" aria-label="I10"><input type="checkbox" class="s" aria-label="I11"><input type="checkbox" class="s" aria-label="I12"><input type="checkbox" class="s" aria-label="I13"><input type="checkbox" class="s" aria-label="I14"></div>
<div class="row"><span class="rlab">J</span><input type="checkbox" class="s" aria-label="J1"><input type="checkbox" class="s" aria-label="J2"><input type="checkbox" class="s" aria-label="J3"><input type="checkbox" class="s" aria-label="J4"><input type="checkbox" class="s" aria-label="J5"><input type="checkbox" class="s" aria-label="J6"><input type="checkbox" class="s" aria-label="J7"><input type="checkbox" class="s" aria-label="J8 sold" disabled><input type="checkbox" class="s" aria-label="J9"><input type="checkbox" class="s" aria-label="J10"><input type="checkbox" class="s" aria-label="J11"><input type="checkbox" class="s" aria-label="J12"><input type="checkbox" class="s" aria-label="J13"><input type="checkbox" class="s" aria-label="J14"></div>
<div class="row"><span class="rlab">K</span><input type="checkbox" class="s" aria-label="K1"><input type="checkbox" class="s" aria-label="K2 sold" disabled><input type="checkbox" class="s" aria-label="K3 sold" disabled><input type="checkbox" class="s" aria-label="K4"><input type="checkbox" class="s" aria-label="K5"><input type="checkbox" class="s" aria-label="K6"><input type="checkbox" class="s" aria-label="K7"><input type="checkbox" class="s" aria-label="K8"><input type="checkbox" class="s" aria-label="K9"><input type="checkbox" class="s" aria-label="K10"><input type="checkbox" class="s" aria-label="K11"><input type="checkbox" class="s" aria-label="K12"><input type="checkbox" class="s" aria-label="K13"><input type="checkbox" class="s" aria-label="K14"></div>
<div class="row"><span class="rlab">L</span><input type="checkbox" class="s" aria-label="L1"><input type="checkbox" class="s" aria-label="L2"><input type="checkbox" class="s" aria-label="L3"><input type="checkbox" class="s" aria-label="L4"><input type="checkbox" class="s" aria-label="L5"><input type="checkbox" class="s" aria-label="L6"><input type="checkbox" class="s" aria-label="L7"><input type="checkbox" class="s" aria-label="L8"><input type="checkbox" class="s" aria-label="L9"><input type="checkbox" class="s" aria-label="L10"><input type="checkbox" class="s" aria-label="L11"><input type="checkbox" class="s" aria-label="L12"><input type="checkbox" class="s" aria-label="L13 sold" disabled><input type="checkbox" class="s" aria-label="L14 sold" disabled></div>
</div>
<div class="legend">
<span><i class="key avail"></i>Available</span>
<span><i class="key sel"></i>Your seats</span>
<span><i class="key gone"></i>Sold</span>
</div>
</section>
</div>
<!-- ===================== SCREEN 2 ===================== -->
<div class="plan plan-b" id="plan-b">
<section class="house" aria-label="Screen 2 seating plan, twelve rows of fourteen seats">
<div class="screen" aria-hidden="true"></div>
<p class="screen-label">Screen</p>
<div class="rows">
<div class="row"><span class="rlab">A</span><input type="checkbox" class="s" aria-label="A1 sold" disabled><input type="checkbox" class="s" aria-label="A2 sold" disabled><input type="checkbox" class="s" aria-label="A3"><input type="checkbox" class="s" aria-label="A4"><input type="checkbox" class="s" aria-label="A5"><input type="checkbox" class="s" aria-label="A6"><input type="checkbox" class="s" aria-label="A7"><input type="checkbox" class="s" aria-label="A8"><input type="checkbox" class="s" aria-label="A9 sold" disabled><input type="checkbox" class="s" aria-label="A10"><input type="checkbox" class="s" aria-label="A11"><input type="checkbox" class="s" aria-label="A12"><input type="checkbox" class="s" aria-label="A13"><input type="checkbox" class="s" aria-label="A14"></div>
<div class="row"><span class="rlab">B</span><input type="checkbox" class="s" aria-label="B1"><input type="checkbox" class="s" aria-label="B2"><input type="checkbox" class="s" aria-label="B3"><input type="checkbox" class="s" aria-label="B4 sold" disabled><input type="checkbox" class="s" aria-label="B5"><input type="checkbox" class="s" aria-label="B6"><input type="checkbox" class="s" aria-label="B7"><input type="checkbox" class="s" aria-label="B8"><input type="checkbox" class="s" aria-label="B9"><input type="checkbox" class="s" aria-label="B10"><input type="checkbox" class="s" aria-label="B11"><input type="checkbox" class="s" aria-label="B12"><input type="checkbox" class="s" aria-label="B13"><input type="checkbox" class="s" aria-label="B14"></div>
<div class="row"><span class="rlab">C</span><input type="checkbox" class="s" aria-label="C1"><input type="checkbox" class="s" aria-label="C2"><input type="checkbox" class="s" aria-label="C3"><input type="checkbox" class="s" aria-label="C4"><input type="checkbox" class="s" aria-label="C5"><input type="checkbox" class="s" aria-label="C6"><input type="checkbox" class="s" aria-label="C7 sold" disabled><input type="checkbox" class="s" aria-label="C8 sold" disabled><input type="checkbox" class="s" aria-label="C9"><input type="checkbox" class="s" aria-label="C10"><input type="checkbox" class="s" aria-label="C11"><input type="checkbox" class="s" aria-label="C12"><input type="checkbox" class="s" aria-label="C13"><input type="checkbox" class="s" aria-label="C14"></div>
<div class="row"><span class="rlab">D</span><input type="checkbox" class="s" aria-label="D1"><input type="checkbox" class="s" aria-label="D2"><input type="checkbox" class="s" aria-label="D3"><input type="checkbox" class="s" aria-label="D4"><input type="checkbox" class="s" aria-label="D5"><input type="checkbox" class="s" aria-label="D6"><input type="checkbox" class="s" aria-label="D7"><input type="checkbox" class="s" aria-label="D8"><input type="checkbox" class="s" aria-label="D9"><input type="checkbox" class="s" aria-label="D10"><input type="checkbox" class="s" aria-label="D11"><input type="checkbox" class="s" aria-label="D12 sold" disabled><input type="checkbox" class="s" aria-label="D13"><input type="checkbox" class="s" aria-label="D14"></div>
<div class="row"><span class="rlab">E</span><input type="checkbox" class="s" aria-label="E1"><input type="checkbox" class="s" aria-label="E2"><input type="checkbox" class="s" aria-label="E3 sold" disabled><input type="checkbox" class="s" aria-label="E4 sold" disabled><input type="checkbox" class="s" aria-label="E5"><input type="checkbox" class="s" aria-label="E6"><input type="checkbox" class="s" aria-label="E7"><input type="checkbox" class="s" aria-label="E8"><input type="checkbox" class="s" aria-label="E9"><input type="checkbox" class="s" aria-label="E10"><input type="checkbox" class="s" aria-label="E11"><input type="checkbox" class="s" aria-label="E12"><input type="checkbox" class="s" aria-label="E13"><input type="checkbox" class="s" aria-label="E14"></div>
<div class="row"><span class="rlab">F</span><input type="checkbox" class="s" aria-label="F1"><input type="checkbox" class="s" aria-label="F2"><input type="checkbox" class="s" aria-label="F3"><input type="checkbox" class="s" aria-label="F4"><input type="checkbox" class="s" aria-label="F5"><input type="checkbox" class="s" aria-label="F6"><input type="checkbox" class="s" aria-label="F7"><input type="checkbox" class="s" aria-label="F8"><input type="checkbox" class="s" aria-label="F9"><input type="checkbox" class="s" aria-label="F10 sold" disabled><input type="checkbox" class="s" aria-label="F11"><input type="checkbox" class="s" aria-label="F12"><input type="checkbox" class="s" aria-label="F13"><input type="checkbox" class="s" aria-label="F14"></div>
<div class="row"><span class="rlab">G</span><input type="checkbox" class="s" aria-label="G1"><input type="checkbox" class="s" aria-label="G2"><input type="checkbox" class="s" aria-label="G3"><input type="checkbox" class="s" aria-label="G4"><input type="checkbox" class="s" aria-label="G5 sold" disabled><input type="checkbox" class="s" aria-label="G6 sold" disabled><input type="checkbox" class="s" aria-label="G7"><input type="checkbox" class="s" aria-label="G8"><input type="checkbox" class="s" aria-label="G9"><input type="checkbox" class="s" aria-label="G10"><input type="checkbox" class="s" aria-label="G11"><input type="checkbox" class="s" aria-label="G12"><input type="checkbox" class="s" aria-label="G13"><input type="checkbox" class="s" aria-label="G14"></div>
<div class="row"><span class="rlab">H</span><input type="checkbox" class="s" aria-label="H1"><input type="checkbox" class="s" aria-label="H2"><input type="checkbox" class="s" aria-label="H3"><input type="checkbox" class="s" aria-label="H4"><input type="checkbox" class="s" aria-label="H5"><input type="checkbox" class="s" aria-label="H6"><input type="checkbox" class="s" aria-label="H7"><input type="checkbox" class="s" aria-label="H8"><input type="checkbox" class="s" aria-label="H9"><input type="checkbox" class="s" aria-label="H10"><input type="checkbox" class="s" aria-label="H11"><input type="checkbox" class="s" aria-label="H12"><input type="checkbox" class="s" aria-label="H13 sold" disabled><input type="checkbox" class="s" aria-label="H14"></div>
<div class="row"><span class="rlab">I</span><input type="checkbox" class="s" aria-label="I1"><input type="checkbox" class="s" aria-label="I2 sold" disabled><input type="checkbox" class="s" aria-label="I3"><input type="checkbox" class="s" aria-label="I4"><input type="checkbox" class="s" aria-label="I5"><input type="checkbox" class="s" aria-label="I6"><input type="checkbox" class="s" aria-label="I7"><input type="checkbox" class="s" aria-label="I8"><input type="checkbox" class="s" aria-label="I9"><input type="checkbox" class="s" aria-label="I10"><input type="checkbox" class="s" aria-label="I11"><input type="checkbox" class="s" aria-label="I12"><input type="checkbox" class="s" aria-label="I13"><input type="checkbox" class="s" aria-label="I14"></div>
<div class="row"><span class="rlab">J</span><input type="checkbox" class="s" aria-label="J1"><input type="checkbox" class="s" aria-label="J2"><input type="checkbox" class="s" aria-label="J3"><input type="checkbox" class="s" aria-label="J4"><input type="checkbox" class="s" aria-label="J5"><input type="checkbox" class="s" aria-label="J6"><input type="checkbox" class="s" aria-label="J7 sold" disabled><input type="checkbox" class="s" aria-label="J8"><input type="checkbox" class="s" aria-label="J9"><input type="checkbox" class="s" aria-label="J10"><input type="checkbox" class="s" aria-label="J11"><input type="checkbox" class="s" aria-label="J12"><input type="checkbox" class="s" aria-label="J13"><input type="checkbox" class="s" aria-label="J14"></div>
<div class="row"><span class="rlab">K</span><input type="checkbox" class="s" aria-label="K1"><input type="checkbox" class="s" aria-label="K2"><input type="checkbox" class="s" aria-label="K3"><input type="checkbox" class="s" aria-label="K4"><input type="checkbox" class="s" aria-label="K5"><input type="checkbox" class="s" aria-label="K6"><input type="checkbox" class="s" aria-label="K7"><input type="checkbox" class="s" aria-label="K8"><input type="checkbox" class="s" aria-label="K9 sold" disabled><input type="checkbox" class="s" aria-label="K10 sold" disabled><input type="checkbox" class="s" aria-label="K11"><input type="checkbox" class="s" aria-label="K12"><input type="checkbox" class="s" aria-label="K13"><input type="checkbox" class="s" aria-label="K14"></div>
<div class="row"><span class="rlab">L</span><input type="checkbox" class="s" aria-label="L1 sold" disabled><input type="checkbox" class="s" aria-label="L2"><input type="checkbox" class="s" aria-label="L3"><input type="checkbox" class="s" aria-label="L4"><input type="checkbox" class="s" aria-label="L5"><input type="checkbox" class="s" aria-label="L6"><input type="checkbox" class="s" aria-label="L7"><input type="checkbox" class="s" aria-label="L8"><input type="checkbox" class="s" aria-label="L9"><input type="checkbox" class="s" aria-label="L10"><input type="checkbox" class="s" aria-label="L11"><input type="checkbox" class="s" aria-label="L12"><input type="checkbox" class="s" aria-label="L13"><input type="checkbox" class="s" aria-label="L14"></div>
</div>
<div class="legend">
<span><i class="key avail"></i>Available</span>
<span><i class="key sel"></i>Your seats</span>
<span><i class="key gone"></i>Sold</span>
</div>
</section>
</div>
<noscript>
<p style="max-width:560px;margin:18px auto 0;font-size:12.5px;line-height:1.5;color:rgba(244,233,212,.6);text-align:center;">
JavaScript is switched off. Picking seats and the seat counter still work.
The running total needs JavaScript, so the basket shows the price per seat instead.
</p>
</noscript>
</main>
<aside class="basket" aria-label="Your basket">
<div class="badge"><span class="badge-num" id="badgeNum"></span></div>
<p class="bk-film bk-a">The Red Lantern · 4:40pm</p>
<p class="bk-film bk-b">Midnight at the Odeon · 8:15pm</p>
<p class="total">$<span id="totalNum">0.00</span></p>
<p class="euro">≈ €<span id="euroNum">0.00</span></p>
<p class="rate" id="rateLine">1 USD = €0.9187 <span class="tag off">indicative</span></p>
<p class="nojs-note">
Running total needs JavaScript.
<span class="unit unit-a">$8.00 per seat</span>
<span class="unit unit-b">$11.50 per seat</span>
</p>
</aside>
<p class="sr-only" aria-live="polite" id="announce"></p>
<script>
(function () {
'use strict';
/* ---- the only two numbers you should ever need to touch ---- */
var EUR_FALLBACK = 0.9187; /* 1 USD -> EUR, used when offline */
var PRICES = { a: 8.00, b: 11.50 };
var NAMES = { a: 'The Red Lantern, 4:40pm', b: 'Midnight at the Odeon, 8:15pm' };
var badgeNum = document.getElementById('badgeNum');
var totalNum = document.getElementById('totalNum');
var euroNum = document.getElementById('euroNum');
var rateLine = document.getElementById('rateLine');
var announce = document.getElementById('announce');
var eurRate = EUR_FALLBACK;
var shown = 0;
var raf = null;
var reduce = false;
try { reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches; } catch (e) {}
function activeFilm() {
var r = document.querySelector('.film-radio:checked');
return r ? r.id.replace('film-', '') : 'a';
}
function seatCount(film) {
return document.querySelectorAll('#plan-' + film + ' .s:checked').length;
}
function render(v) {
shown = v;
totalNum.textContent = v.toFixed(2);
euroNum.textContent = (v * eurRate).toFixed(2);
}
function animateTo(to) {
if (reduce) { render(to); return; }
if (raf) cancelAnimationFrame(raf);
var from = shown;
var t0 = null;
var dur = 480;
function step(ts) {
if (t0 === null) t0 = ts;
var p = Math.min(1, (ts - t0) / dur);
var e = 1 - Math.pow(1 - p, 3); /* ease-out cubic */
render(from + (to - from) * e);
if (p < 1) { raf = requestAnimationFrame(step); }
else { raf = null; render(to); }
}
raf = requestAnimationFrame(step);
}
function update() {
var f = activeFilm();
var n = seatCount(f);
var t = n * PRICES[f];
badgeNum.textContent = String(n); /* the badge: 12 reads 12 */
animateTo(t);
if (announce) {
announce.textContent = n + (n === 1 ? ' seat' : ' seats') +
', total $' + t.toFixed(2) + ', about ' + (t * eurRate).toFixed(2) + ' euros';
}
}
/* one listener covers seat ticks and film changes */
document.addEventListener('change', function (e) {
var t = e.target;
if (!t) return;
if (t.classList && (t.classList.contains('s') || t.classList.contains('film-radio'))) {
update();
}
});
/* ---- the date ---- */
var todayEl = document.getElementById('today');
if (todayEl) {
try {
todayEl.textContent = new Date().toLocaleDateString(undefined, {
weekday: 'long', day: 'numeric', month: 'long'
});
} catch (e) {}
}
/* ---- euro rate: try live, fall back quietly ---- */
function setRate(rate, isLive) {
eurRate = rate;
rateLine.innerHTML = '1 USD = €' + rate.toFixed(4) +
' <span class="tag ' + (isLive ? 'live' : 'off') + '">' +
(isLive ? 'live' : 'indicative') + '</span>';
render(shown);
}
setRate(EUR_FALLBACK, false);
try {
if (typeof fetch === 'function') {
var ctrl = new AbortController();
var timer = setTimeout(function () { ctrl.abort(); }, 1800);
fetch('https://api.frankfurter.app/latest?from=USD&to=EUR',
{ signal: ctrl.signal, cache: 'no-store' })
.then(function (r) { return r.json(); })
.then(function (d) {
clearTimeout(timer);
if (d && d.rates && typeof d.rates.EUR === 'number') {
setRate(d.rates.EUR, true);
}
})
.catch(function () { clearTimeout(timer); });
}
} catch (e) { /* offline: the baked-in rate stands */ }
/* ---- start ---- */
render(0);
update();
})();
</script>
</body>
</html>
The page is built around two HTML radios that switch between films, with every seat as a real checkbox. That means clicking a seat works even when JavaScript is disabled, and the sold seats are disabled in the markup so they can't be chosen. The basket punches above its weight: a small badge sits in the top-right corner, using a CSS counter so the number appears even with JS off. With JS on, the total animates smoothly from the old value to the new one, and the euro conversion updates alongside it.
Optimization Tip: You can adjust the fallback euro rate by editing EUR_FALLBACK near the bottom of the script. The film prices and sold-seat patterns are hardcoded — to change them, look for PRICES and the sold attributes in each seating row. The two showtimes are fixed in the radio labels and in NAMES inside the script.