/* ═══════════════════════════════════════════════════════════════════════════
   HEARD. — the homepage as a film.
   A certificate card and a colossal title burn in cinema black until the red
   full stop becomes a camera aperture and the entire warm-white page floods
   out through the dot. Every scene after is one enormous word annotated in
   tiny biro. The film closes back in the dark, FIN is struck into BEGIN.

   Scenes: 1 COLOSSUS · 2 MEASUREMENT · 3 PROPER ENGLISH · 4 THE CAST ·
           5 THE BILL · 6 FIN→BEGIN.
   The intro overlay lives in site/index.html (static, so it plays at 0ms
   while the 940KB bundle is still parsing — the film covers the load).

   Scrub choreography is driven by --p (0→1 per section), written by one rAF
   scroll handler in home.behaviour.js — a single code path for every browser
   rather than a scroll-timeline primary with a hand-written fallback.
   ═══════════════════════════════════════════════════════════════════════ */

:root{
  --house-black:#0B0B0E;
  --bone:#F3EDE2;
  --bone-dim:#D9CFBB;
  --paper:#FAF7F0;
  --paper-tint:#F1EBDF;
  --ink:#17160F;
  --red:#E23B2E;
  --biro:#2B4ED4;
  --grey-line:#B9B2A4;
  --grey-text:#7A756B;
  --tungsten:rgba(255,217,160,.14);
  --red-lit:#FF6A5E;   /* the red, lifted for small text on house-black */

  --f-display:'Archivo',system-ui,sans-serif;
  --f-voice:'Fraunces',Georgia,serif;
  --f-mono:'IBM Plex Mono',ui-monospace,monospace;
  --f-ipa:'Gentium Book Plus','Noto Sans',serif;

  /* Registration of the aperture: the dot's centre, hand-tuned per breakpoint
     and refined once by JS. Read by the intro overlay's mask in index.html. */
  --dot-x:50vw; --dot-y:46vh;
}

.eewj-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
:where(.heard) :where(a,button,[tabindex]):focus-visible{
  outline:3px solid var(--red);outline-offset:3px;border-radius:4px}

/* ── THE FILM'S GROUND ─────────────────────────────────────────────────── */
.heard{background:var(--paper);color:var(--ink);font-family:var(--f-voice);
  overflow:clip;
  /* The rim of the aperture: a 2px red hem across the very top. */
  border-top:2px solid var(--red)}
.heard *{min-width:0}
/* Film grain on paper: the generated 128px tile at 3%. Painted once, never
   animated. */
.heard::before{content:"";position:fixed;inset:0;z-index:60;pointer-events:none;
  background:url(/img/grain.png);opacity:.05;mix-blend-mode:multiply}

.heard .mono{font-family:var(--f-mono);letter-spacing:.02em}
.heard .marker{font-family:var(--f-mono);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--grey-text)}

/* Biro annotations: the student's pen. */
.anno{font-family:var(--f-mono);font-size:11px;letter-spacing:.02em;
  color:var(--biro);max-width:24ch;line-height:1.5}
.anno .lead{display:block;width:56px;height:1px;background:var(--biro);
  opacity:.6;margin-bottom:6px}

/* One-shot reveals: wiped in by an IO class, never risen-and-faded. */
.wipe{clip-path:inset(0 100% 0 0)}
.lit .wipe,.wipe.on{clip-path:inset(0 0 0 0);
  transition:clip-path .6s cubic-bezier(.16,1,.3,1) calc(var(--n,0)*90ms)}

/* ── SCENE 1 — THE COLOSSUS, on a grid ─────────────────────────────────────
   Two columns: the sentence and the actor. The word is a real heading with
   its red full stop inline — nothing absolute, nothing clipped, nothing that
   can drift at an unanticipated viewport. */
.sc1{position:relative;background:var(--paper)}
.sc1-inner{display:grid;grid-template-columns:minmax(0,1.08fr) minmax(0,.92fr);
  align-items:end;column-gap:clamp(16px,3vw,48px);
  min-height:calc(100svh - var(--head-h,72px));
  padding:clamp(18px,3.5vh,44px) clamp(20px,4vw,64px) 0}
.sc1-copy{display:flex;flex-direction:column;align-items:flex-start;
  gap:clamp(16px,2.8vh,32px);align-self:center;
  padding:clamp(20px,4vh,48px) 0 clamp(28px,6vh,64px);
  position:relative;z-index:2}
.sc1-kick{margin:0;font:italic 400 clamp(1.4rem,2.5vw,2.5rem)/1.3 var(--f-voice);
  color:var(--ink)}
.sc1-word{margin:0;font-family:var(--f-display);
  font-variation-settings:'wdth' 120,'wght' 850;
  font-size:min(14vw,16rem);line-height:.88;letter-spacing:-.02em;
  color:var(--ink);white-space:nowrap;width:max-content}
.sc1-word .dt{color:var(--red);font-weight:inherit}
.sc1-sub{margin:0;max-width:44ch;font-family:var(--f-voice);
  font-size:clamp(1.1rem,1.6vw,1.55rem);line-height:1.62;color:var(--ink)}
.sc1-facts{margin:0;display:flex;flex-wrap:wrap;gap:6px 0;
  font-family:var(--f-mono);font-size:clamp(11px,.85vw,14px);
  letter-spacing:.06em;text-transform:uppercase;color:var(--biro)}
.sc1-facts span{display:inline-flex;align-items:center}
.sc1-facts span + span::before{content:"·";margin:0 10px;color:var(--grey-line)}
.sc1-cta{display:flex;flex-wrap:wrap;gap:14px 22px;align-items:center;
  margin-top:clamp(4px,1vh,10px)}
.sc1-stage{position:relative;align-self:end;min-width:0}
.sc1-james{display:block;margin:0 auto;width:auto;
  height:clamp(360px,78svh,820px);max-width:100%;object-fit:contain;
  object-position:bottom;filter:grayscale(1) contrast(1.03);
  animation:breathe 7s ease-in-out infinite alternate}
@keyframes breathe{from{transform:translateY(0)}to{transform:translateY(-6px)}}
.sc1[data-fx] .sc1-james{transform:translateY(calc(var(--p,0) * -7vh))}
@keyframes hero-in{from{opacity:0;transform:translateY(14px)}
  to{opacity:1;transform:none}}
@keyframes hero-wipe{from{clip-path:inset(0 100% 0 0)}
  to{clip-path:inset(0 0 0 0)}}
html.iris .sc1-kick{animation:hero-in .6s var(--e,ease) 1.15s both}
html.iris .sc1-word{animation:hero-wipe .9s cubic-bezier(.16,1,.3,1) 1.3s both}
html.iris .sc1-sub{animation:hero-in .6s ease 1.75s both}
html.iris .sc1-facts{animation:hero-in .6s ease 1.95s both}
html.iris .sc1-cta{animation:hero-in .6s ease 2.1s both}
html.no-intro .sc1-kick,html.no-intro .sc1-sub,
html.no-intro .sc1-facts,html.no-intro .sc1-cta{
  animation:hero-in .6s ease .15s both}
html.no-intro .sc1-word{animation:hero-wipe .9s cubic-bezier(.16,1,.3,1) .25s both}
html.encore.iris .sc1-kick,html.encore.iris .sc1-sub,
html.encore.iris .sc1-facts,html.encore.iris .sc1-cta{animation-delay:.5s}
html.encore.iris .sc1-word{animation-delay:.6s}
.pill{display:inline-flex;align-items:center;gap:10px;background:var(--red);
  color:#fff;text-decoration:none;font-family:var(--f-mono);font-weight:700;
  font-size:.92rem;letter-spacing:.04em;text-transform:uppercase;
  padding:16px 28px;border-radius:999px;min-height:44px;
  transition:transform .12s ease,box-shadow .12s ease}
.pill:hover,.pill:focus-visible{transform:translateY(-2px);
  box-shadow:0 8px 22px -8px var(--red)}
.ghost{font-family:var(--f-mono);font-size:.85rem;color:var(--ink);
  text-decoration:underline;text-underline-offset:4px}
.cert-roundel{display:none;position:absolute;right:20px;top:14px;z-index:6;
  transform:rotate(-4deg);border:2px double var(--red);border-radius:8px;
  padding:10px 14px;color:var(--red);opacity:.7;font-family:var(--f-mono);
  font-size:10px;letter-spacing:.12em;text-transform:uppercase;text-align:center}
@media(max-width:860px){
  .sc1-inner{grid-template-columns:1fr;align-items:start;
    padding:18px 18px 0}
  .sc1-copy{padding-bottom:0;gap:14px}
  .sc1-word{font-size:min(19vw,7.5rem)}
  .sc1-james{height:min(44svh,420px)}
  .sc1-cta .pill{width:100%;justify-content:center}
}

/* ── SCENE 2 — THE SCREEN, full bleed ──────────────────────────────────────
   A full-viewport dark frame. Each establishing shot belongs to its line:
   the projector opens WHAT TO EXPECT, the classroom carries the two lesson
   lines, the library carries the last two. The booking CTA lives INSIDE the
   frame, outside the aria-hidden reel, so it never hides from anyone. */
.sc2{background:var(--house-black);padding:0}
.tscreen{position:relative;height:100svh;overflow:hidden}
.tscreen::before{content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  background:url(/img/grain.png);opacity:.07;mix-blend-mode:overlay}
.tscreen::after{content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  background:radial-gradient(transparent 52%,rgba(0,0,0,.6))}
.reel{position:absolute;inset:0}
.plate{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  z-index:1;opacity:0;filter:grayscale(1) brightness(.34) contrast(1.06);
  animation-duration:14s;animation-timing-function:linear;
  animation-iteration-count:infinite;animation-fill-mode:both;
  animation-play-state:paused}
.lit .plate{animation-play-state:running}
.plate.pa{animation-name:plate-a}
.plate.pb{animation-name:plate-b}
.plate.pc{animation-name:plate-c}
@keyframes plate-a{0%{opacity:0;transform:scale(1.04)}1.5%{opacity:.9}
  18.5%{opacity:.9;transform:scale(1.1)}20%{opacity:0}100%{opacity:0}}
@keyframes plate-b{0%{opacity:0}20%{opacity:0;transform:scale(1.04)}21.5%{opacity:.9}
  58.5%{opacity:.9;transform:scale(1.12)}60%{opacity:0}100%{opacity:0}}
@keyframes plate-c{0%{opacity:0}60%{opacity:0;transform:scale(1.04)}61.5%{opacity:.9}
  98.5%{opacity:.9;transform:scale(1.12)}100%{opacity:0}}
.tcard{position:absolute;inset:0;display:flex;flex-direction:column;gap:16px;
  align-items:center;justify-content:center;text-align:center;
  padding:0 clamp(20px,7vw,120px);opacity:0;z-index:2;
  animation:tslot 14s linear infinite both paused;
  animation-delay:calc(var(--slot,0) * 2.8s)}
.lit .tcard{animation-play-state:running}
@keyframes tslot{
  0%{opacity:0;transform:scale(1)}
  1.2%{opacity:1;transform:scale(1)}
  18.6%{opacity:1;transform:scale(1.045)}
  20%{opacity:0;transform:scale(1.045)}
  100%{opacity:0;transform:scale(1)}}
.tcard p{margin:0;font-family:var(--f-display);
  font-variation-settings:'wdth' 120,'wght' 850;
  font-size:clamp(1.9rem,5.6vw,5.6rem);line-height:1.06;letter-spacing:-.01em;
  color:var(--bone);max-width:20ch;text-wrap:balance;
  text-shadow:0 4px 40px rgba(0,0,0,.6)}
.tcard b{color:var(--red-lit);font-weight:inherit}
.tcard.tsm p{font-family:var(--f-mono);font-variation-settings:normal;
  font-size:clamp(1rem,2.2vw,1.7rem);letter-spacing:.34em;color:var(--bone-dim)}
.tcard .tsub{font-family:var(--f-mono);font-variation-settings:normal;
  font-size:clamp(.75rem,1.3vw,1rem);letter-spacing:.18em;
  text-transform:uppercase;color:var(--bone-dim)}
.tunder{position:absolute;left:clamp(20px,4vw,64px);
  bottom:calc(clamp(20px,5vh,52px) + env(safe-area-inset-bottom));z-index:4;
  display:flex;flex-wrap:wrap;gap:14px 24px;align-items:center}
.ghost-lite{color:var(--bone);text-decoration-color:rgba(243,237,226,.5)}
@media(max-width:767px){
  .tscreen{height:82svh}
  .tcard p{font-size:8vw}
}

/* ── SCENE 3 — LEARN PROPER ENGLISH (the snake) ────────────────────────────
   Three words weave around the pinned Englishman at alternating depths:
   LEARN passes behind him, PROPER prints in front, ENGLISH passes behind —
   each travelling the opposite way to its neighbours as you scroll, locking
   into the poster at exactly p=0.5. The lock is also the no-JS, no-scrub and
   reduced-motion frame, so the screenshot cannot fail to exist. */
.sc3{position:relative;height:280vh;background:var(--paper)}
.sc3-stage{position:sticky;top:0;height:100svh;overflow:clip}
.sc3-james{position:absolute;left:50%;bottom:0;height:90svh;width:auto;
  z-index:2;filter:contrast(1.04) grayscale(1);
  transform:translateX(-50%) scale(calc(1.07 - var(--p,.5) * .07));
  transform-origin:50% 30%}
.sc3-w{position:absolute;left:50%;white-space:nowrap;user-select:none;
  font-family:var(--f-display);font-variation-settings:'wdth' 120,'wght' 850;
  font-size:clamp(3.2rem,11vw,14rem);line-height:1;letter-spacing:-.02em}
.sc3-wa{top:12%;z-index:1;color:var(--ink);opacity:.92;
  transform:translateX(-50%) translateX(calc((var(--p,.5) - .5) * -26vw))
    rotate(-1.2deg)}
.sc3-wb{top:36%;z-index:3;color:var(--red);opacity:.94;
  transform:translateX(-50%) translateX(calc((var(--p,.5) - .5) * 20vw))
    rotate(.8deg)}
.sc3-wc{top:60%;z-index:1;color:var(--ink);opacity:.92;
  transform:translateX(-50%) translateX(calc((var(--p,.5) - .5) * -30vw))
    rotate(-.6deg)}
.sc3-anno{position:absolute;right:clamp(16px,6vw,90px);top:10svh;z-index:4}
/* The evidence: casual over formal, stamped on as the shear plays. */
.pair{position:absolute;z-index:3;margin:0;opacity:0;max-width:34%;
  transform:scale(.82) rotate(var(--r,0deg));
  background:var(--paper);border:2px solid var(--ink);border-radius:10px;
  padding:12px 18px;box-shadow:5px 5px 0 rgba(226,59,46,.22)}
.pair b{display:block;font-family:var(--f-display);
  font-variation-settings:'wdth' 112,'wght' 800;font-weight:normal;
  font-size:clamp(1.15rem,1.9vw,1.7rem);color:var(--red);line-height:1.15}
.pair s{display:block;margin-top:5px;font-family:var(--f-mono);font-size:12px;
  color:var(--grey-text)}
.pr1{--r:-2.4deg;left:2%;top:1svh;max-width:26%}
.pr2{--r:1.8deg;right:2%;top:1svh;max-width:26%}
.pr3{--r:-1.6deg;left:2%;bottom:5svh}
.pr4{--r:2.6deg;right:2%;bottom:5svh}
@media(max-width:767px){
  .pair{max-width:46%}
  .pair b{font-size:1rem}
  .pair s{font-size:10px}
  .pr2{top:20svh;bottom:auto}
}
.sc3.f1 .pr1,.sc3.f2 .pr2,.sc3.f3 .pr3,.sc3.f4 .pr4{opacity:1;
  transform:scale(1) rotate(var(--r,0deg));
  transition:opacity .3s ease,transform .34s cubic-bezier(.34,1.4,.64,1)}
/* Past the midpoint the words come FORWARD: they approached behind him and
   leave in front — and the locked poster reads unobstructed. */
.sc3.front .sc3-wa,.sc3.front .sc3-wc{z-index:5;
  text-shadow:0 2px 30px rgba(250,247,240,.55)}
.sc3-wb{z-index:5}
.sc3-sub{position:absolute;left:clamp(16px,5vw,72px);bottom:7svh;z-index:4;
  font:italic 400 clamp(1rem,1.5vw,1.35rem)/1.5 var(--f-voice);
  color:var(--ink);max-width:40ch}
@media(max-width:767px){
  .sc3{height:220vh}
  .sc3-james{height:74svh}
  .sc3-w{font-size:14vw}
  .sc3-wa{transform:translateX(-50%) translateX(calc((var(--p,.5) - .5) * -14vw)) rotate(-1.2deg)}
  .sc3-wb{transform:translateX(-50%) translateX(calc((var(--p,.5) - .5) * 11vw)) rotate(.8deg)}
  .sc3-wc{transform:translateX(-50%) translateX(calc((var(--p,.5) - .5) * -16vw)) rotate(-.6deg)}
}

/* ── SCENE 3.5 — MEET JAMES, in space ──────────────────────────────────────
   The whole section is the stage: starfield edge to edge, James floating at
   centre, the facts fading in and out around him — meanings in biro, facts
   on paper, stats in red — while the bubble keeps talking. */
.sc35{position:relative;min-height:100svh;overflow:clip;color:var(--bone);
  background:radial-gradient(120% 130% at 70% 16%,#1A2140,#0B0B14 62%);
  padding:clamp(70px,10vh,120px) clamp(20px,4vw,64px) 60px}
.sc35>.star-layer{position:absolute;inset:-10%;pointer-events:none}
.sc35>.shoot{position:absolute;top:12%;left:-12%;width:120px;height:1.5px;
  pointer-events:none;transform:rotate(16deg);
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.9));
  animation:shoot 8.5s linear infinite}
.sc35-head{position:relative;z-index:3;max-width:56ch}
.sc35-head .marker{display:block;margin-bottom:14px;color:rgba(243,237,226,.55)}
.sc35-title{font-family:var(--f-display);
  font-variation-settings:'wdth' 120,'wght' 850;
  font-size:clamp(3rem,9vw,10rem);line-height:.9;letter-spacing:-.02em;
  color:var(--bone);margin:0 0 20px}
.sc35-title b{color:var(--red);font-weight:inherit}
.sc35-line{margin:0;font-family:var(--f-voice);
  font-size:clamp(1.15rem,1.8vw,1.7rem);line-height:1.6;color:var(--bone-dim)}
.sc35-line b{color:var(--bone)}
.sc35 .astro{position:absolute;left:50%;bottom:0;transform:translateX(-50%);
  height:min(72svh,760px);width:auto;z-index:2;
  filter:grayscale(1) contrast(1.05) brightness(1.06)
    drop-shadow(0 0 44px rgba(120,150,255,.3));
  animation:drift 6.5s ease-in-out infinite alternate}
.sc35 .bubble{position:absolute;left:clamp(4%,22vw,30%);top:34%;
  max-width:min(340px,38%);z-index:3}
.sc35 .chip{z-index:3;font-size:clamp(11.5px,1vw,14.5px);max-width:30%}
.sc35-pull{position:absolute;right:clamp(16px,4vw,64px);
  bottom:clamp(56px,10vh,110px);z-index:3;margin:0;max-width:34ch;
  font:italic 500 clamp(1.15rem,1.7vw,1.7rem)/1.5 var(--f-voice);
  color:var(--bone);border-left:3px solid var(--red);padding-left:20px}
.sc35 .space-cap{position:absolute;left:clamp(16px,4vw,64px);bottom:14px;
  margin:0;font-family:var(--f-mono);font-size:10px;letter-spacing:.14em;
  text-transform:uppercase;color:rgba(243,237,226,.5);z-index:3}
@media(max-width:860px){
  .sc35{min-height:auto;padding-bottom:44px}
  .sc35 .astro{position:relative;left:auto;transform:none;display:block;
    margin:26px auto 0;height:min(52svh,440px)}
  .sc35 .bubble{position:absolute;left:4%;top:38%;max-width:52%}
  .sc35 .chip{max-width:56%}
  .sc35-pull{position:static;margin:24px 0 0;max-width:none}
}

/* ── SCENE 4 — THE CAST, as a travelling banner ────────────────────────────
   One slow band of cards, each in its own colour, sliding forever. Pauses on
   hover and focus; reduced motion makes it a row you scroll yourself. */
.sc4{position:relative;background:var(--paper);
  padding:clamp(70px,11vh,130px) 0 40px}
.sc4-head{padding:0 clamp(20px,4vw,64px)}
.sc4 .marker{display:block;margin-bottom:14px}
.sc4-title{font-family:var(--f-display);
  font-variation-settings:'wdth' 120,'wght' 850;
  font-size:clamp(2.4rem,7vw,7rem);line-height:.9;letter-spacing:-.02em;
  color:var(--ink);margin:0 0 40px}
.sc4-title b{color:var(--red);font-weight:inherit}
.mq{overflow:hidden;max-width:100%;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 4%,#000 96%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 4%,#000 96%,transparent)}
.mq-track{display:flex;gap:20px;width:max-content;padding:6px 0;
  animation:crawl 80s linear infinite}
.mq:hover .mq-track,.mq:focus-within .mq-track{animation-play-state:paused}
@keyframes crawl{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.mcard{flex:0 0 clamp(280px,30vw,400px);margin:0;border-radius:6px;
  padding:26px 26px 20px;display:flex;flex-direction:column;gap:12px}
.mcard blockquote{margin:0;font-family:var(--f-voice);font-style:italic;
  font-size:1.05rem;line-height:1.6}
.mcard [lang="vi"]{font-family:var(--f-voice)}
.mcard [lang="uk"]{font-family:'Noto Serif',serif}
.mcard [lang="hi"]{font-family:'Noto Serif Devanagari',serif;font-style:normal;
  line-height:1.85}
.mcard [lang="ar"]{font-family:'Noto Naskh Arabic',serif;font-style:normal;
  line-height:2;text-align:right}
.mtr{margin:0;font-family:var(--f-mono);font-size:10.5px;line-height:1.55;
  opacity:.75}
.mcard figcaption{margin-top:auto;padding-top:8px;font-family:var(--f-mono);
  font-size:10px;letter-spacing:.16em;text-transform:uppercase;opacity:.7}
/* The five looks. */
.mcard.v1{background:var(--ink);color:var(--bone)}
.mcard.v2{background:var(--paper);color:var(--ink);
  border:1.5px solid var(--ink)}
.mcard.v3{background:var(--red);color:#fff}
.mcard.v4{background:var(--paper-tint);color:var(--ink);
  border:1.5px solid var(--grey-line)}
.mcard.v5{background:var(--biro);color:#fff}
.cast-foot{margin:26px 0 0;padding:0 clamp(20px,4vw,64px);
  font-family:var(--f-mono);font-size:11px;color:var(--grey-text)}

/* ── SCENE 5 — PICK YOUR SEAT: the prices as cinema tickets ────────────────
   Six tickets on a grid. The stub is the price; the perforation is a dashed
   rule; the whole ticket is the link. */
.sc5{position:relative;background:var(--paper-tint);
  padding:clamp(70px,11vh,130px) clamp(20px,4vw,64px) clamp(150px,22vh,260px);
  overflow:clip}
.sc5-head .marker{display:block;margin-bottom:14px}
.sc5-title{font-family:var(--f-display);
  font-variation-settings:'wdth' 120,'wght' 850;
  font-size:clamp(2.6rem,7.6vw,8.2rem);line-height:.9;letter-spacing:-.02em;
  color:var(--ink);margin:0 0 44px}
.sc5-title b{color:var(--red);font-weight:inherit}
.tix{display:grid;gap:22px;grid-template-columns:repeat(auto-fit,minmax(380px,1fr));
  max-width:1320px}
.ticket{position:relative;display:grid;
  grid-template-columns:1fr auto;grid-template-rows:auto auto auto;
  column-gap:22px;row-gap:6px;align-items:start;
  background:var(--paper);color:var(--ink);text-decoration:none;
  border:2px solid var(--ink);border-radius:10px;
  padding:22px 26px 20px;min-height:44px;
  transform:rotate(var(--tilt,0deg));
  transition:transform .18s cubic-bezier(.34,1.4,.64,1),box-shadow .18s ease}
.ticket:nth-child(odd){--tilt:.7deg}
.ticket:nth-child(even){--tilt:-.6deg}
.ticket:hover,.ticket:focus-visible{transform:rotate(0deg) translateY(-6px);
  box-shadow:7px 7px 0 rgba(226,59,46,.28)}
.ticket:hover .tk-price{transform:scale(1.12) rotate(-3deg)}
.tk-price{transition:transform .18s cubic-bezier(.34,1.4,.64,1)}
.tk-tag{grid-column:1/-1;font-family:var(--f-mono);font-size:9.5px;
  letter-spacing:.2em;text-transform:uppercase;color:var(--grey-text)}
.tk-name{font-family:var(--f-display);
  font-variation-settings:'wdth' 110,'wght' 800;
  font-size:clamp(1.35rem,2vw,1.95rem);line-height:1.1;align-self:center}
.tk-price{grid-row:2/4;grid-column:2;align-self:center;
  font-family:var(--f-display);font-variation-settings:'wdth' 116,'wght' 850;
  font-size:clamp(2.1rem,3.1vw,3.3rem);color:var(--red);
  border-left:2px dashed var(--grey-line);padding-left:22px;line-height:1}
.tk-desc{font:italic 400 .92rem/1.5 var(--f-voice);color:var(--grey-text)}
.tk-cta{grid-column:1;margin-top:8px;font-family:var(--f-mono);
  font-size:.82rem;color:var(--ink);text-decoration:underline;
  text-underline-offset:4px}
.ticket.tk-dark{background:var(--ink);color:var(--bone);border-color:var(--ink)}
.ticket.tk-dark .tk-desc{color:var(--bone-dim)}
.ticket.tk-dark .tk-cta{color:var(--bone)}
.ticket.tk-dark .tk-price{color:var(--red-lit);border-color:rgba(243,237,226,.3)}
.sc5-balloon{position:absolute;right:clamp(8px,4vw,70px);
  bottom:clamp(16px,3vh,40px);width:clamp(180px,17vw,260px);z-index:2}
.sc5-balloon img{width:100%;height:auto;display:block;
  animation:bfloat 6s ease-in-out infinite alternate;transform-origin:38% 8%}
@keyframes bfloat{from{transform:translateY(0) rotate(0)}
  to{transform:translateY(-6px) rotate(1.2deg)}}
.sc5-balloon figcaption{font:italic 400 13px/1.5 var(--f-voice);
  color:var(--grey-text);margin-top:6px;text-align:right}
.sc5-foot{margin:30px 0 0;font-family:var(--f-mono);font-size:11px;
  color:var(--grey-text)}
@media(max-width:900px){
  .sc5{padding-bottom:clamp(120px,18vh,200px)}
  .sc5-balloon{position:static;width:200px;margin:36px 0 0 auto}
}

/* ── SCENE 6 — FIN → BEGIN ─────────────────────────────────────────────── */
.sc6{position:relative;background:var(--house-black);color:var(--bone);
  min-height:120svh;overflow:clip;
  padding:clamp(80px,14vh,170px) clamp(16px,5vw,72px) 40px;
  border-bottom:2px solid var(--red);
  /* The dark arrives as a closing shutter, not a fade. */
  clip-path:inset(var(--shut,0%) 0 0 0)}
.sc6-spot{position:absolute;width:160vmin;height:160vmin;left:-30vmin;top:-20vmin;
  pointer-events:none;z-index:0;
  background:radial-gradient(closest-side,rgba(255,217,160,.4),transparent 62%);
  mix-blend-mode:screen;transform:translate(var(--sx,0px),var(--sy,0px))}
.sc6-james{position:absolute;right:0;bottom:10svh;height:min(74svh,660px);
  width:auto;z-index:1;filter:grayscale(1) brightness(.8);
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 30%);
  mask-image:linear-gradient(90deg,transparent,#000 30%)}
.sc6-setup{position:relative;z-index:2;font-family:var(--f-voice);
  font-style:italic;font-size:clamp(1.2rem,2.4vw,1.9rem);color:var(--bone-dim)}
.sc6-word{position:relative;z-index:2;font-family:var(--f-display);
  font-variation-settings:'wdth' 120,'wght' 850;
  font-size:clamp(2.75rem,10vw,12rem);line-height:.95;letter-spacing:-.02em;
  color:var(--bone);margin:8px 0 34px}
.sc6-word b{color:var(--red);font-weight:inherit}
.sc6-word .g{display:inline-block;opacity:0;transform:scale(1.14);filter:blur(8px)}
.sc6.lit .sc6-word .g{opacity:1;transform:scale(1);filter:blur(0);
  transition:opacity .24s cubic-bezier(.2,.9,.1,1),
    transform .24s cubic-bezier(.2,.9,.1,1),filter .24s cubic-bezier(.2,.9,.1,1)}
.sc6.lit .sc6-word .g:nth-child(2){transition-delay:.06s}
.sc6.lit .sc6-word .g:nth-child(3){transition-delay:.12s}
.sc6.lit .sc6-word .g:nth-child(4){transition-delay:.18s}
.sc6.lit .sc6-word .g:nth-child(5){transition-delay:.24s}
.sc6-tickets{position:relative;z-index:2;display:flex;flex-direction:column;
  gap:14px;align-items:flex-start;margin-bottom:20px}
.sc6-micro{font-family:var(--f-mono);font-size:12px;color:var(--bone-dim);
  letter-spacing:.04em}
.sc6-bare{font-family:var(--f-mono);font-size:13px;color:var(--bone)}
.sc6-bare a{color:var(--bone)}
.sc6-programme{position:relative;z-index:2;margin-top:clamp(48px,9vh,100px);
  max-width:680px}
.sc6-programme h3{font-family:var(--f-mono);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--grey-text);margin:0 0 14px}
.prog-row{display:flex;align-items:baseline;gap:12px;padding:16px 0;
  border-bottom:1px dotted rgba(243,237,226,.22);text-decoration:none;
  color:var(--bone)}
.prog-row span:first-child{font-family:var(--f-display);
  font-variation-settings:'wdth' 112,'wght' 800;
  font-size:clamp(1.25rem,2vw,2rem);line-height:1.1}
.prog-row i{font-family:var(--f-mono);
  font-size:clamp(1rem,1.5vw,1.4rem)}
.prog-row span:first-child{flex:1}
.prog-row i{font-style:normal;color:var(--red-lit)}
.sc6-credits{position:relative;z-index:2;margin-top:clamp(44px,8vh,90px);
  font-family:var(--f-mono);font-size:clamp(14px,1vw,16px);
  color:var(--bone-dim);max-width:680px}
.sc6-credits p{display:flex;gap:8px;align-items:baseline;margin:7px 0}
.sc6-credits p span:first-child{white-space:nowrap}
.sc6-credits p::after{content:"";flex:1;order:1;
  border-bottom:1px dotted rgba(243,237,226,.25);transform:translateY(-3px)}
.sc6-credits p span:last-child{order:2;color:var(--bone)}
.sc6-fin{position:relative;z-index:2;margin-top:clamp(40px,7vh,80px);
  font-family:var(--f-display);font-variation-settings:'wdth' 120,'wght' 850;
  font-size:clamp(2rem,6vw,5rem);display:flex;gap:.5em;align-items:baseline}
.sc6-fin .fin{position:relative;color:var(--bone-dim)}
.sc6-fin .fin::after{content:"";position:absolute;left:-4%;right:-4%;top:52%;
  height:.08em;background:var(--red);transform:scaleX(var(--strike,0));
  transform-origin:left}
.sc6.fin-lit .sc6-fin .fin::after{--strike:1;
  transition:transform .24s cubic-bezier(.65,0,.35,1)}
.sc6-fin .begin{color:var(--bone);opacity:0;transform:scale(1.5);filter:blur(6px)}
.sc6.fin-lit .sc6-fin .begin{opacity:1;transform:scale(1);filter:blur(0);
  transition:opacity .26s cubic-bezier(.22,1.2,.36,1) .33s,
    transform .26s cubic-bezier(.22,1.2,.36,1) .33s,
    filter .26s cubic-bezier(.22,1.2,.36,1) .33s}
.sc6-footer{position:relative;z-index:2;margin-top:clamp(48px,8vh,90px);
  display:flex;flex-wrap:wrap;gap:10px 26px;font-family:var(--f-mono);
  font-size:12px;color:var(--grey-text)}
.sc6-footer a{color:var(--bone-dim)}
.sc6-enddot{position:relative;z-index:2;text-align:center;color:var(--red);
  font-size:18px;margin:44px 0 8px}
@media(max-width:767px){
  .sc6-james{height:min(40svh,300px);bottom:auto;top:8svh}
  .sc6-word{font-size:13vw}
}

/* ── THE PHONE THUMB BAR ───────────────────────────────────────────────── */
.thumbbar{position:fixed;left:0;right:0;bottom:0;z-index:70;
  display:none;align-items:center;justify-content:space-between;gap:12px;
  min-height:52px;background:var(--paper);border-top:1px solid var(--grey-line);
  padding:8px 16px calc(8px + env(safe-area-inset-bottom));
  font-family:var(--f-mono);font-size:12px;color:var(--ink);
  transform:translateY(100%);transition:transform .3s cubic-bezier(.22,1,.36,1)}
.thumbbar .pill{padding:10px 20px;font-size:.8rem}
@media(max-width:767px){.thumbbar{display:flex}}
.thumbbar.show{transform:translateY(0)}

/* ── REDUCED MOTION — the film as a printed programme ──────────────────── */
@media (prefers-reduced-motion:reduce){
  .heard *,.heard *::before,.heard *::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important}
  .cert-roundel{display:block}
  .sc1-james{animation:none}
  .tcard{animation:none;display:none}
  .tcard[style*="--slot:1"]{display:flex;opacity:1}
  .plate{animation:none;display:none}
  .plate.pa{display:block;opacity:.5;transform:none}
  .mq-track{animation:none}
  .mq{-webkit-mask-image:none;mask-image:none;overflow-x:auto}
  .sc3{height:auto}.sc3-stage{position:static;height:100svh}
  .sc3-w,.sc3-james{--p:.5}
  .sc5-balloon img{animation:none}
  .sc6{clip-path:none}
  .sc6 .sc6-word .g,.sc6 .sc6-fin .begin{opacity:1;transform:none;filter:none}
  .sc6 .sc6-fin .fin::after{--strike:1}
  .wipe{clip-path:inset(0 0 0 0)}
}

/* ═══ THE INTRO — lives in index.html, plays at 0ms over the bundle parse ═══
   Pure CSS from certificate to dot-slam; JS only times the iris (html.iris)
   and strikes the set. Every failure path resolves: no JS → intro-bail fades
   it out at 9s; reduced motion → display:none (handled by the head script
   never mounting it… and belt-and-braces below). */
#heard-intro{position:fixed;inset:0;z-index:999;pointer-events:none;
  background:var(--house-black);
  -webkit-mask-image:radial-gradient(circle var(--iris,0px) at var(--dot-x) var(--dot-y),transparent 98.5%,#000 100%);
  mask-image:radial-gradient(circle var(--iris,0px) at var(--dot-x) var(--dot-y),transparent 98.5%,#000 100%);
  animation:booth-flicker 240ms steps(1,end) both,
            intro-bail 600ms ease 9s forwards}
@property --iris{syntax:'<length>';inherits:true;initial-value:0px}
html.iris #heard-intro{animation:booth-flicker 240ms steps(1,end) both,
  iris-open 1100ms cubic-bezier(.8,0,.2,1) forwards,
  cam-drift 1100ms cubic-bezier(.8,0,.2,1) forwards}
html.encore.iris #heard-intro{animation:iris-open .7s cubic-bezier(.8,0,.2,1) forwards}
@keyframes iris-open{to{--iris:165vmax;visibility:hidden}}
@keyframes cam-drift{from{transform:scale(1)}to{transform:scale(1.06)}}
@keyframes intro-bail{to{opacity:0;visibility:hidden}}
@keyframes booth-flicker{0%{opacity:1}30%{opacity:.92}55%{opacity:1}80%{opacity:.96}100%{opacity:1}}

#heard-intro .plate{position:absolute;inset:0;
  background:radial-gradient(60vw 60vw at 50% 46%,var(--tungsten),transparent 70%)}
#heard-intro .plate::before{content:"";position:absolute;inset:0;
  background:url(/img/grain.png);opacity:.06;mix-blend-mode:overlay}
#heard-intro .plate::after{content:"";position:absolute;inset:0;
  background:radial-gradient(transparent 55%,rgba(0,0,0,.5))}

/* The certificate: content and a British joke from frame one. */
#heard-intro .cert{position:absolute;left:50%;top:50%;
  transform:translate(-50%,-50%);text-align:center;
  border:1px solid var(--bone-dim);outline:1px solid var(--bone-dim);
  outline-offset:5px;padding:34px 46px;color:var(--bone-dim);
  font-family:var(--f-mono);letter-spacing:.14em;text-transform:uppercase;
  animation:cert-approve 500ms linear 300ms both,
            cert-zoom 1000ms ease-out both,
            splice-jump 80ms steps(2,end) 1000ms forwards}
#heard-intro .cert .big{display:block;font-size:clamp(1.4rem,4vw,2.6rem);
  font-weight:700;margin-bottom:12px}
#heard-intro .cert .mid{display:block;font-size:clamp(.8rem,1.6vw,1rem);
  margin-bottom:14px}
#heard-intro .cert .small{display:block;font-size:11px;opacity:.75}
@keyframes cert-approve{to{color:var(--bone)}}
@keyframes splice-jump{0%{transform:translate(-50%,-50%)}
  50%{transform:translate(-50%,calc(-50% + 6px))}
  100%{transform:translate(-50%,-50%);visibility:hidden}}
/* The reel-change flash at the splice. */
#heard-intro .flash{position:absolute;inset:0;background:var(--bone);opacity:0;
  animation:splice-flash 60ms linear 1000ms both}
@keyframes splice-flash{from{opacity:.12}to{opacity:0}}

/* The title stage: simply THERE after the splice — a hard cut, no tween.
   Centred and self-contained; the iris opens from ITS dot, measured by JS. */
#heard-intro .ttl{position:absolute;inset:0;top:var(--head-h,72px);
  visibility:hidden;animation:hardcut 1ms linear 1000ms forwards;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:clamp(8px,1.6vh,18px);text-align:center}
@keyframes hardcut{to{visibility:visible}}
#heard-intro .sil{position:absolute;right:4vw;bottom:0;
  height:calc(88svh - var(--head-h,72px));width:auto;
  filter:brightness(0);opacity:.55;z-index:0}
@media(max-width:767px){#heard-intro .sil{right:-8vw;height:60svh}}
#heard-intro .ov-kick{position:relative;z-index:1;margin:0;
  font:italic 400 clamp(1.2rem,2.2vw,2rem)/1.3 var(--f-voice);
  color:var(--bone-dim);opacity:0;animation:kick-in 500ms ease 1050ms both}
@keyframes kick-in{to{opacity:1}}
#heard-intro .ov-word{position:relative;z-index:1;
  font-family:var(--f-display);font-variation-settings:'wdth' 120,'wght' 850;
  font-size:clamp(4rem,15vw,17rem);line-height:.9;letter-spacing:-.02em;
  color:var(--bone);white-space:nowrap}
#heard-intro .ov-word span{display:inline-block;opacity:0;
  transform:scale(1.14);filter:blur(8px);
  animation:glyph-stamp 240ms cubic-bezier(.2,.9,.1,1) both}
#heard-intro .ov-word span:nth-child(1){animation-delay:1150ms}
#heard-intro .ov-word span:nth-child(2){animation-delay:1250ms}
#heard-intro .ov-word span:nth-child(3){animation-delay:1350ms}
#heard-intro .ov-word span:nth-child(4){animation-delay:1450ms}
#heard-intro .ov-word span:nth-child(5){animation-delay:1550ms}
@keyframes glyph-stamp{to{opacity:1;transform:scale(1);filter:blur(0)}}
#heard-intro .ov-dot{display:inline-block;color:var(--red);opacity:0;
  transform:scale(1.6);
  animation:dot-stamp 260ms cubic-bezier(.22,1.2,.36,1) 1750ms both}
@keyframes dot-stamp{to{opacity:1;transform:scale(1)}}
#heard-intro .ring{position:absolute;left:var(--dot-x);top:var(--dot-y);
  width:22vmin;height:22vmin;transform:translate(-50%,-50%);border-radius:50%;
  background:radial-gradient(circle,rgba(243,237,226,.35),transparent 70%);
  opacity:0;animation:ring-flash 220ms ease-out 1790ms both;z-index:1}
@keyframes ring-flash{from{opacity:.35}to{opacity:0}}
@keyframes cert-zoom{from{scale:1}to{scale:1.03}}
/* A single beam of light sweeps the finished title just before the iris. */
#heard-intro .beam{position:absolute;top:0;bottom:0;width:26vw;z-index:2;
  pointer-events:none;transform:translateX(-40vw) skewX(-18deg);
  background:linear-gradient(90deg,transparent,rgba(255,246,227,.14),transparent);
  animation:beam-sweep 700ms ease-in-out 1850ms both}
@keyframes beam-sweep{to{transform:translateX(160vw) skewX(-18deg)}}

/* An encore skips the certificate beats: title, dot and silhouette at 0ms. */
html.encore #heard-intro .cert,html.encore #heard-intro .flash{display:none}
html.encore #heard-intro .ttl{animation-delay:0ms}
html.encore #heard-intro .ov-kick,
html.encore #heard-intro .ov-word span{animation-delay:0ms!important}
html.encore #heard-intro .ov-dot{animation-delay:60ms!important}
html.encore #heard-intro .ring{display:none}
/* Any input: the film sprints to its last frame. */
html.skip #heard-intro,html.skip #heard-intro *{
  animation-duration:120ms!important;animation-delay:0ms!important}
html.no-intro #heard-intro{display:none}
@media (prefers-reduced-motion:reduce){#heard-intro{display:none}}

/* ── JAMES IN SPACE ──────────────────────────────────────────────────────────
   The Director's portrait panel is a starfield. He floats, a speech bubble
   cycles real expressions, and chips pop up around him — meanings in biro,
   facts on paper, stats in red. The static frame carries one bubble and one
   chip, so nothing depends on JavaScript. */
.space{position:relative;margin:0;border-radius:10px;overflow:hidden;
  height:clamp(500px,66vh,700px);
  background:radial-gradient(120% 130% at 72% 18%,rgba(40,50,90,.5),transparent 62%);
  display:flex;align-items:flex-end;justify-content:center}
.star-layer{position:absolute;inset:-20%;pointer-events:none;
  background-image:
    radial-gradient(1px 1px at 12% 20%,rgba(255,255,255,.9) 50%,transparent 51%),
    radial-gradient(1.5px 1.5px at 78% 12%,rgba(255,255,255,.8) 50%,transparent 51%),
    radial-gradient(1px 1px at 55% 38%,rgba(255,255,255,.7) 50%,transparent 51%),
    radial-gradient(2px 2px at 30% 66%,rgba(245,217,139,.8) 50%,transparent 51%),
    radial-gradient(1px 1px at 88% 54%,rgba(255,255,255,.75) 50%,transparent 51%),
    radial-gradient(1.5px 1.5px at 8% 84%,rgba(255,255,255,.6) 50%,transparent 51%),
    radial-gradient(1px 1px at 44% 8%,rgba(255,255,255,.8) 50%,transparent 51%),
    radial-gradient(1px 1px at 66% 76%,rgba(255,255,255,.65) 50%,transparent 51%),
    radial-gradient(1.5px 1.5px at 92% 88%,rgba(255,255,255,.7) 50%,transparent 51%),
    radial-gradient(1px 1px at 20% 46%,rgba(255,255,255,.5) 50%,transparent 51%);
  animation:twinkle 5s ease-in-out infinite alternate}
@keyframes twinkle{from{opacity:.55}to{opacity:1}}
.shoot{position:absolute;top:14%;left:-12%;width:120px;height:1.5px;
  pointer-events:none;transform:rotate(16deg);
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.9));
  animation:shoot 8.5s linear infinite}
@keyframes shoot{0%,88%{transform:translate(0,0) rotate(16deg);opacity:0}
  90%{opacity:1}100%{transform:translate(130vw,34vh) rotate(16deg);opacity:0}}
.astro{display:block;width:auto;max-width:78%;height:auto;
  max-height:calc(100% - 40px);
  filter:grayscale(1) contrast(1.05) brightness(1.06)
    drop-shadow(0 0 34px rgba(120,150,255,.28));
  animation:drift 6.5s ease-in-out infinite alternate}
@keyframes drift{from{transform:translateY(4px) rotate(-1.4deg)}
  to{transform:translateY(-12px) rotate(1.2deg)}}
.bubble{position:absolute;left:6%;top:9%;max-width:56%;margin:0;
  background:var(--paper);color:var(--ink);border-radius:14px;
  padding:12px 18px;font:italic 500 clamp(1rem,1.35vw,1.3rem)/1.35 var(--f-voice);
  box-shadow:0 6px 24px rgba(0,0,0,.4)}
.bubble::after{content:"";position:absolute;right:-9px;top:58%;
  border:10px solid transparent;border-left-color:var(--paper);
  transform:rotate(-14deg)}
.bubble.pop{animation:bpop .34s cubic-bezier(.34,1.4,.64,1)}
@keyframes bpop{from{opacity:0;transform:scale(.82)}to{opacity:1;transform:scale(1)}}
.chip{position:absolute;left:var(--cx,10%);top:var(--cy,70%);margin:0;
  max-width:64%;font-family:var(--f-mono);font-size:11.5px;line-height:1.45;
  letter-spacing:.02em;padding:7px 12px;border-radius:6px;
  box-shadow:0 4px 16px rgba(0,0,0,.35)}
.chip.pop{animation:bpop .3s cubic-bezier(.34,1.4,.64,1)}
.chip-mean{background:var(--biro);color:#fff}
.chip-fact{background:var(--paper);color:var(--ink)}
.chip-stat{background:var(--red);color:#fff}
.space-cap{position:absolute;left:14px;bottom:10px;margin:0;
  font-family:var(--f-mono);font-size:10px;letter-spacing:.14em;
  text-transform:uppercase;color:rgba(243,237,226,.55)}
@media (prefers-reduced-motion:reduce){
  .star-layer,.astro{animation:none}
  .shoot,.sc35>.shoot{display:none}
}

/* ── FUN FACTS — the human row in The Director ──────────────────────────────
   Three hand-drawn chips: the striped shirt, the ring, the snooker table.
   The ring breathes; the red ball rolls on hover; both stand still under
   reduced motion. */
.facts{margin-top:34px}
.facts .marker{display:block;margin-bottom:12px}
.fact-row{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;
  gap:12px}
.fact{display:inline-flex;align-items:center;gap:12px;
  background:rgba(243,237,226,.06);border:1.5px solid rgba(243,237,226,.3);
  border-radius:999px;padding:10px 20px 10px 12px;
  font-family:var(--f-mono);font-size:clamp(12.5px,.95vw,15px);
  letter-spacing:.02em;color:var(--bone);
  transition:transform .15s ease,border-color .15s ease,box-shadow .15s ease}
.fact:hover{transform:translateY(-2px);border-color:var(--bone);
  box-shadow:0 0 22px rgba(245,217,139,.18)}
.facts .marker{color:rgba(243,237,226,.55)}
.fact svg{width:34px;height:34px;flex:0 0 auto}
.fact .ringglow{animation:ringbreathe 3.2s ease-in-out infinite}
@keyframes ringbreathe{0%,100%{opacity:.15}50%{opacity:.45}}
.fact:hover .snkred{transform:translateX(7px)}
.snkred{transition:transform .4s cubic-bezier(.22,1,.36,1)}
@media (prefers-reduced-motion:reduce){
  .fact .ringglow{animation:none}
}
