/* ==========================================================================
   The Playpen School, sample homepage by Defined Solution (Playpen Version 1)
   css/main.css: tokens, type, grid, every section, states, tiers, responsive.
   The preloader overlay is styled in css/preloader.css.
   ========================================================================== */

/* 0. Fonts (self-hosted, Latin, variable; see vendor/fonts/README.md) ------- */
@font-face {
  font-family: 'Newsreader';
  font-style: normal;
  font-weight: 300 400;
  font-display: swap;
  src: url('../vendor/fonts/newsreader-var.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Newsreader';
  font-style: italic;
  font-weight: 300 400;
  font-display: swap;
  src: url('../vendor/fonts/newsreader-italic-var.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('../vendor/fonts/hanken-grotesk-var.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2122, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Metric-matched fallbacks so the swap moves nothing (computed from the fonts' hhea/OS/2 tables) */
@font-face {
  font-family: 'Newsreader Fallback';
  src: local('Georgia');
  size-adjust: 91.52%;
  ascent-override: 80.31%;
  descent-override: 28.95%;
  line-gap-override: 0%;
}
@font-face {
  font-family: 'Hanken Fallback';
  src: local('Arial');
  size-adjust: 101.7%;
  ascent-override: 98.33%;
  descent-override: 29.79%;
  line-gap-override: 0%;
}

/* 1. Tokens ---------------------------------------------------------------- */
:root {
  color-scheme: light;

  --paper: #F5F1EA;
  --paper-2: #ECE6DB;
  --paper-3: #FBF9F5;
  --ink: #1C1715;
  --ink-2: #4A413C;
  --maroon: #8A0204;
  --maroon-deep: #5C0407;
  --gold: #9A6F1E;
  --gold-soft: #B98A2E;
  --amber: #F5A719;
  --clay: #D9C7B2;
  --night: #141110;
  --night-2: #1E1917;
  --bone-dim: #B9B1A6;
  --gold-text: #D9B25C;
  --night-line: rgba(245, 241, 234, 0.16);

  --font-serif: 'Newsreader', 'Newsreader Fallback', Georgia, 'Times New Roman', serif;
  --font-sans: 'Hanken Grotesk', 'Hanken Fallback', Arial, Helvetica, sans-serif;
  --wght-display: 300;
  --body-size: 18px;

  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-mask: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-wipe: cubic-bezier(0.76, 0, 0.24, 1);
  --ease-move: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-soft: cubic-bezier(0.33, 1, 0.68, 1);

  --t-micro: 150ms;
  --t-ui: 300ms;
  --t-hover: 400ms;
  --t-flip: 600ms;
  --t-wipe: 800ms;
  --t-reveal: 900ms;
  --t-mask: 1100ms;
  --t-disp: 1100ms;
  --t-scroll: 1400ms;

  --margin: clamp(20px, 6vw, 120px);
  --gutter: 24px;
  --band-max: 1600px;
  /* polish pass: 96..192 left 100-200 px of dead paper between sheets at 1440 and 1920 */
  --section-pad: clamp(72px, 9vw, 144px);
  --nav-h: 80px;                                    /* 2026-10-26: 72 -> 80 for the stacked lockup (phones: 72, below) */
  --util-h: 0px;   /* the utility row was folded into the Menu overlay and the footer */
  --hairline: 1px solid var(--clay);

  /* written by js/main.js and the scene modules */
  --hero-p: 0;
  --ascent-p: 0;
  --learning-p: 0;
  --ledger-p: 0;
  --sun-x: 0.3;
}
/* registered so they compute to px (js/webgl/hero.js reads --hero-fade for the shader's dissolve) */
@property --hero-lift { syntax: '<length>'; inherits: true; initial-value: 0px; }
@property --hero-fade { syntax: '<length>'; inherits: true; initial-value: 110px; }
@media (max-width: 767px) {
  :root { --gutter: 16px; }
}
@media (min-width: 1440px) {
  :root { --body-size: 20px; }
}

/* 2. Base ------------------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }
html {
  background: var(--paper);
  color: var(--ink);
  font-optical-sizing: auto;
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: calc(var(--nav-h) + 16px);
  scroll-padding-bottom: 72px;
  /* the scrollbar's gutter is reserved from the first paint: the layout is the same under the
     preloader (overflow hidden), on the live page and with the menu or the Sheet open (Lenis
     stopped: overflow clip), so the one ScrollTrigger refresh made during the preloader's exit
     stays exact and nothing jumps sideways when a scrollbar comes or goes */
  scrollbar-gutter: stable;
  /* no overflow clip on <html>: it makes documentElement.scrollHeight report the viewport and Lenis's limit 0 */
}
html.js.is-loading { overflow: hidden; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 var(--body-size) / 1.6 var(--font-serif);
  overflow-x: clip;
  min-height: 100svh;
}
img, picture, video, canvas, svg { display: block; max-width: 100%; }
img { height: auto; }
h1, h2, h3, h4, p, figure, blockquote, dl, dd { margin: 0; }
ul, ol { margin: 0; padding: 0; }
a { color: inherit; }
button { font: inherit; color: inherit; }
b, strong { font-weight: 500; }
em { font-style: italic; }
::selection { background: var(--maroon); color: var(--paper); }
:focus-visible { outline: 2px solid var(--maroon); outline-offset: 3px; }
.is-night :focus-visible, .foot :focus-visible { outline-color: var(--amber); outline-offset: 2px; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.skip {
  position: fixed;
  top: 8px; left: 8px;
  z-index: 110;
  padding: 12px 16px;
  background: var(--paper-3);
  color: var(--ink);
  border: 1px solid var(--maroon);
  font: 500 15px / 1 var(--font-sans);
  text-decoration: none;
  transform: translateY(-200%);
}
.skip:focus-visible { transform: none; outline-offset: 0; }

/* 3. Type ------------------------------------------------------------------ */
.display-xl {
  font-family: var(--font-serif);
  font-weight: var(--wght-display);
  /* polish pass: the headline runs two lines across the whole band from 1280 up ("The whole of a
     childhood, / in one school."), 140 px at most (the 172 px three-liner put the terrace below the
     fold and made the type the hero); the terrace trees sit in the first screen from 1280 × 720 up */
  font-size: clamp(44px, 6vw, 140px);
  line-height: 0.95;
  letter-spacing: -0.015em;
}
.display-l {
  font-family: var(--font-serif);
  font-weight: 400;
  /* 96 px ceiling (was 120): the photographs carry the sheets, the headlines name them */
  font-size: clamp(36px, 4.8vw, 96px);
  line-height: 0.98;
  letter-spacing: -0.012em;
}
@media (min-width: 1715px) {
  .display-l { font-weight: 300; }
}
.display-m, h3.display-m {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(28px, 2.9vw, 54px);
  line-height: 1.05;
  letter-spacing: -0.005em;
}
h3, .h3 {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(22px, 1.8vw, 32px);
  line-height: 1.15;
  letter-spacing: 0;
}
.lead {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(19px, 1.45vw, 26px);
  line-height: 1.4;
}
.caption {
  font: 400 14px / 1.45 var(--font-sans);
  color: var(--ink-2);
}
.label {
  font: 500 11.5px / 1.2 var(--font-sans);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.is-night .label, .foot .label { color: var(--gold-text); }
.num-ledger {
  font: 300 clamp(40px, 4vw, 72px) / 1 var(--font-serif);
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums lining-nums;
}
p, li, dd, blockquote { text-wrap: pretty; }
/* the italic maroon accent is used twice on the page (the hero and the Ledger); every other
   headline is plain roman since the polish pass */
h1 em, h2 em, .quote__line em, .display-xl em, .display-l em { color: var(--maroon); font-style: italic; font-weight: inherit; }
.is-night h2 em, .foot h2 em { color: var(--gold-text); }
.lead em { font-style: italic; }
/* phones: the 11.5 px tracked capitals were a strain for parents reading on a phone */
@media (max-width: 767px) {
  .label, .plate__n, .sheet-rule, .rule__end { font-size: 12.5px; }
  .link__site { font-size: 11px; }
}

/* SplitText pieces: hidden until the split happened (motion tiers only; CSS is the resting state) */
html.js:not([data-tier="still"]) [data-split]:not(.is-split) { visibility: hidden; }
[data-split] .line { display: block; }

/* 4. Layout ---------------------------------------------------------------- */
.band {
  width: min(100% - 2 * var(--margin), var(--band-max));
  margin-inline: auto;
}
.sheet {
  position: relative;
  padding-block: var(--section-pad);
}
.sheet + .sheet { padding-top: 0; }
#results { padding-top: var(--section-pad); }
#notices { padding-top: var(--section-pad); }   /* its own coloured board: keep full top padding after the Parents sheet (moved 2026-10-22) */

.sheet-rule {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding-top: 14px;
  margin-bottom: clamp(40px, 5vw, 72px);
  font: 500 11.5px / 1.2 var(--font-sans);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.sheet-rule__line {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 1px;
  background: var(--clay);
  transform-origin: left center;
}
.sheet-rule__n { font-variant-numeric: tabular-nums; }
.sheet-rule__purpose {
  margin-left: auto;
  font: 400 14px / 1.45 var(--font-sans);
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-2);
}
.is-night .sheet-rule { color: var(--bone-dim); }
.is-night .sheet-rule__n { color: var(--gold-text); }
.is-night .sheet-rule__line { background: var(--night-line); }
.is-night .sheet-rule__purpose { color: var(--bone-dim); }
@media (max-width: 767px) {
  .sheet-rule__purpose { display: none; }
}

/* 5. House devices --------------------------------------------------------- */

/* Links: the gold underline that thickens */
.link {
  color: inherit;
  text-decoration: none;
  background-image: linear-gradient(var(--gold), var(--gold));
  background-repeat: no-repeat;
  background-position: 0 calc(100% - 3px);
  background-size: 100% 1px;
  transition: background-size var(--t-micro) var(--ease-soft);
  /* the padding is the touch target (WCAG 2.5.8, 24 px): the underline stays 1 px under the text */
  padding: 3px 0 4px;
}
.link:hover, .link:focus-visible { background-size: 100% 2px; }
.is-night .link, .foot .link { background-image: linear-gradient(var(--gold-text), var(--gold-text)); }
.link__site {
  display: inline-block;
  margin-left: 8px;
  font: 500 10px / 1 var(--font-sans);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
  vertical-align: 0.2em;
  white-space: nowrap;
}
.is-night .link__site, .foot .link__site { color: var(--bone-dim); }
.link--btn {
  background-color: transparent;
  border: 0;
  cursor: pointer;
  font: inherit;
}
/* Footnote daggers: a 24 × 24 px target drawn as a small superscript (the negative margins keep
   the line box where it was) */
.fn {
  display: inline-block;
  min-width: 24px;
  padding: 0 4px;
  margin: -8px -2px -8px 0.05em;
  font: 400 0.55em / 24px var(--font-sans);
  text-align: center;
  color: var(--maroon);
  text-decoration: none;
  vertical-align: super;
}

/* Buttons */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  padding: 0 26px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font: 500 15px / 1 var(--font-sans);
  letter-spacing: 0.02em;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
}
.btn--primary {
  background: var(--maroon);
  color: var(--paper);
  transition: background var(--t-hover) var(--ease-soft);
}
.btn--primary::after {
  content: '';
  position: absolute;
  inset: 3px;
  border-radius: inherit;
  border: 1px solid var(--gold-text);
  opacity: 0;
  transition: opacity var(--t-hover) var(--ease-soft);
  pointer-events: none;
}
.btn--primary:hover { background: var(--maroon-deep); }
.btn--primary:hover::after { opacity: 1; }
.btn--small { min-height: 44px; padding: 0 18px; font-size: 14px; }
.btn--secondary {
  border: 1px solid var(--ink);
  transition: color var(--t-hover) var(--ease-soft), border-color var(--t-hover) var(--ease-soft);
}
.btn--secondary:hover { color: var(--maroon); border-color: var(--maroon); }
.btn--text {
  padding: 0;
  min-height: 44px;
  border-radius: 0;
  background-image: linear-gradient(var(--gold), var(--gold));
  background-repeat: no-repeat;
  background-position: 0 calc(50% + 0.75em);
  background-size: 100% 1px;
  transition: background-size var(--t-micro) var(--ease-soft);
}
.btn--text:hover, .btn--text:focus-visible { background-size: 100% 2px; }
.btn--pill { min-height: 40px; padding: 0 16px; font-size: 14px; }
.btn--pill:hover { color: var(--maroon); }
.btn__label { display: inline-block; }
.magnet-area { display: inline-block; padding: 8px; margin: -8px; }

/* Plates: every photograph on a paper mount with a hairline, numbered */
.plate {
  position: relative;
  padding: 12px;
  background: var(--paper-3);
  border: 1px solid var(--clay);
}
.plate__frame { overflow: hidden; position: relative; }
.plate img { width: 100%; height: auto; }
.plate__cap {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-top: 10px;
  font: 400 14px / 1.45 var(--font-sans);
  color: var(--ink-2);
}
.plate__n {
  flex: none;
  font: 500 11.5px / 1.2 var(--font-sans);
  letter-spacing: 0.14em;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.plate--bleed {
  max-width: var(--band-max);
  margin-inline: auto;
  padding-inline: 0;
  border-inline: 0;
}
.plate--bleed .plate__cap { padding-inline: var(--margin); }
@media (min-width: 1840px) {
  .plate--bleed { border-inline: 1px solid var(--clay); }
  .plate--bleed .plate__cap { padding-inline: 12px; }
}
.plate__open {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  overflow: hidden;
}
/* hover: the picture eases to 1.03 inside its frame and the caption darkens (the reveal tween
   clears its inline transform when it lands, reveals.js, so this transition can run) */
.plate__open img, .stage .plate img { transition: transform var(--t-hover) var(--ease-soft); }
.plate__cap { transition: color var(--t-ui) var(--ease-soft); }
@media (hover: hover) and (pointer: fine) {
  .plate__open:hover img, .stage .plate:hover img { transform: scale(1.03); }
  .plates__item .plate:hover .plate__cap, .stage .plate:hover .plate__cap { color: var(--ink); }
}

/* The rule: an engraver's scale */
.rule { position: relative; }
.rule--v {
  width: 64px;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: flex-end;
}
.rule--v::before {
  content: '';
  position: absolute;
  top: 0; bottom: 0; right: 0;
  width: 1px;
  background: var(--clay);
}
.rule--v .rule__tick {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  height: 0;
}
.rule--v .rule__tick b {
  font: 500 11.5px / 1 var(--font-sans);
  letter-spacing: 0.08em;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  transition: color var(--t-ui) var(--ease-soft);
}
.rule--v .rule__tick::after {
  content: '';
  width: 12px; height: 1px;
  background: var(--ink-2);
  transition: background var(--t-ui) var(--ease-soft), width var(--t-ui) var(--ease-soft);
}
.rule--v .rule__tick[data-tick="1"]::after, .rule--v .rule__tick[data-tick="5"]::after { width: 20px; }
.rule--v .rule__tick.is-lit b { color: var(--maroon); }
.rule--v .rule__tick.is-lit::after { background: var(--maroon); width: 20px; }
.rule__band {
  position: absolute;
  right: -2px;
  bottom: calc(var(--ascent-p) * 100%);
  width: 5px; height: 72px;
  transform: translateY(50%);
  border-radius: 3px;
  background: linear-gradient(to bottom, rgba(245, 167, 25, 0), var(--amber) 38%, var(--amber) 62%, rgba(245, 167, 25, 0));
  pointer-events: none;
}
.rule__mark {
  position: absolute;
  right: -9px;
  bottom: calc(var(--ascent-p) * 100%);
  width: 19px; height: 2px;
  transform: translateY(50%);
  background: var(--maroon);
  pointer-events: none;
}
.rule--h {
  height: 44px;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  padding-top: 10px;
  margin-top: 40px;
}
.rule--h::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 1px;
  background: var(--clay);
}
.rule--h .rule__tick {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: 0;
}
.rule--h .rule__tick::before {
  content: '';
  width: 1px; height: 8px;
  margin-top: -10px;
  background: var(--ink-2);
}
.rule--h .rule__tick b {
  font: 500 11px / 1 var(--font-sans);
  letter-spacing: 0.06em;
  color: var(--ink-2);
  white-space: nowrap;
}
.rule--h .rule__mark {
  right: auto;
  bottom: auto;
  top: -1px;
  left: calc(var(--learning-p) * 100%);
  width: 28px; height: 3px;
  transform: translateX(-50%);
  border-radius: 2px;
}
.rule__end {
  position: absolute;
  right: 0;
  bottom: 100%;
  margin-bottom: 10px;
  font: 500 11.5px / 1.2 var(--font-sans);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
  white-space: nowrap;
}
/* Media pause disc (WCAG 2.2.2): the courtyard film in the Ascent */
.media-pause {
  position: relative;
  width: 44px; height: 44px;
  border-radius: 50%;
  border: 1px solid var(--clay);
  background: var(--paper-3);
  cursor: pointer;
  padding: 0;
  display: grid;
  place-items: center;
  transition: border-color var(--t-micro);
}
.media-pause[hidden] { display: none; }
.media-pause:hover { border-color: var(--ink-2); }
.media-pause__icon { position: relative; width: 12px; height: 12px; }
.media-pause__icon::before, .media-pause__icon::after {
  content: '';
  position: absolute;
  top: 0; bottom: 0;
  width: 3px;
  background: var(--ink);
}
.media-pause__icon::before { left: 1px; }
.media-pause__icon::after { right: 1px; }
.media-pause[aria-pressed="true"] .media-pause__icon::before {
  left: 2px; width: 0; height: 0; top: 0; bottom: auto;
  background: none;
  border-left: 10px solid var(--ink);
  border-top: 6px solid transparent;
  border-bottom: 6px solid transparent;
}
.media-pause[aria-pressed="true"] .media-pause__icon::after { display: none; }

/* Sample tags (private build; html.clean hides them) */
[data-sample]::after {
  content: 'Sample';
  display: inline-block;
  margin-left: 8px;
  padding: 2px 5px 1px;
  border: 1px solid var(--gold);
  font: 500 9.5px / 1.2 var(--font-sans);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
  vertical-align: middle;
  white-space: nowrap;
}
form[data-sample]::after { display: block; width: max-content; margin: 12px 0 0; }
.is-night [data-sample]::after, .foot [data-sample]::after { color: var(--bone-dim); border-color: var(--gold-text); }
html.clean [data-sample]::after { content: none; }

/* 6. Header ---------------------------------------------------------------- */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 70;
  color: var(--ink);
  transition: transform var(--t-ui) var(--ease-out), background-color var(--t-ui) var(--ease-soft), color var(--t-ui) var(--ease-soft);
}
.nav.is-hidden { transform: translateY(-100%); }
.nav.is-solid { background: rgba(245, 241, 234, 0.96); }
/* the blur only where it is cheap and visible: fine-pointer desktops (re-blurring a 72 px strip
   every frame is a known scroll-jank source on Mali-class phone GPUs, and barely visible on paper) */
@media (hover: hover) and (pointer: fine) and (min-width: 1024px) {
  .nav.is-solid {
    background: rgba(245, 241, 234, 0.92);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
  }
}
.nav.is-night {
  background: rgba(20, 17, 16, 0.9);
  color: var(--paper);
}
.ext::after { content: '\2197'; font-size: 11px; }
.nav__bar {
  position: relative;
  height: var(--nav-h);
  display: grid;
  /* the brand column may shrink (min 0): a long wordmark clips inside its own box instead of
     running under the Book-a-visit button when the bar is narrow */
  grid-template-columns: minmax(0, auto) minmax(0, 1fr) auto;
  align-items: center;
  gap: 24px;
  width: min(100% - 2 * var(--margin), var(--band-max));
  margin-inline: auto;
}
.nav__bar::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--clay);
  opacity: 0;
  transition: opacity var(--t-ui);
}
.nav.is-solid .nav__bar::after, .nav.is-ruled .nav__bar::after { opacity: 1; }
.nav.is-night .nav__bar::after { background: var(--night-line); }
.nav__brand {
  display: flex;
  align-items: center;
  gap: 12px;
  text-decoration: none;
  color: inherit;
  min-height: 44px;
  min-width: 0;
}
.nav__mark {
  width: 52px; height: 52px;
  display: grid;
  place-items: center;
  transition: width var(--t-ui) var(--ease-out), height var(--t-ui) var(--ease-out);
}
.nav.is-solid .nav__mark, .nav.is-night .nav__mark { width: 44px; height: 44px; }
/* 2026-10-20: the school's own crest (transparent PNG/WebP, no white disc); a soft shadow keeps it
   readable over the film */
.nav.is-over-hero:not(.is-solid) .nav__mark img { filter: drop-shadow(0 2px 6px rgba(28, 23, 21, 0.45)); }
.nav__mark img { width: 100%; height: auto; transition: opacity var(--t-micro); }
html.js.is-loading:not(.intro-seen):not([data-tier="still"]) .nav__mark img { opacity: 0; }
html.js.is-loading .nav__mark.is-landed img, html.js.is-loading .nav__mark img.is-visible { opacity: 1; }
.nav__word {
  font: 400 20px / 1 var(--font-serif);
  white-space: nowrap;
  min-width: 0;
  overflow: hidden;
}
.nav__primary {
  display: none;
  justify-content: center;
  gap: 28px;
}
.nav__primary a {
  font: 400 14px / 1 var(--font-sans);
  color: inherit;
  text-decoration: none;
  padding: 15px 0;                                  /* 14 px of type + 30 = a 44 px target */
  white-space: nowrap;                              /* 7 links since Gallery joined (2026-10-22): keep "School life" on one line */
  background-image: linear-gradient(var(--gold), var(--gold));
  background-repeat: no-repeat;
  background-position: 0 calc(100% - 11px);
  background-size: 0 1px;
  transition: background-size var(--t-ui) var(--ease-out);
}
.nav__primary a:hover, .nav__primary a[aria-current="true"], .nav__primary a[aria-current="page"] { background-size: 100% 1px; }
.nav.is-night .nav__primary a { background-image: linear-gradient(var(--gold-text), var(--gold-text)); }
@media (min-width: 1280px) {
  .nav__primary { display: flex; gap: 22px; }
}
@media (min-width: 1440px) {
  .nav__primary { gap: 28px; }
}
.nav__right {
  display: flex;
  align-items: center;
  gap: 18px;
  justify-self: end;
}
.menu-btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 0 4px;
  border: 0;
  background: none;
  font: 500 14px / 1 var(--font-sans);
  letter-spacing: 0.02em;
  cursor: pointer;
}
.menu-btn__icon { position: relative; width: 22px; height: 14px; }
.menu-btn__icon i {
  position: absolute;
  left: 0;
  width: 100%; height: 1.5px;
  background: currentColor;
  transition: transform var(--t-ui) var(--ease-move), top var(--t-ui) var(--ease-move);
}
.menu-btn__icon i:first-child { top: 3px; }
.menu-btn__icon i:last-child { top: 10px; }
html.menu-open .menu-btn__icon i:first-child { top: 6.5px; transform: rotate(45deg); }
html.menu-open .menu-btn__icon i:last-child { top: 6.5px; transform: rotate(-45deg); }
html.menu-open .nav { z-index: 81; color: var(--ink); background: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; transform: none; }
html.menu-open .nav__bar::after { opacity: 0; }
html.menu-open .nav__primary, html.menu-open .nav__right .magnet-area { opacity: 0; pointer-events: none; transition: opacity var(--t-ui); }
/* below 600 px the wordmark (about 160 px) and the two controls do not both fit beside the margins:
   the crest alone carries the brand (480–560 px collided with Book a visit before) */
@media (max-width: 599px) {
  .nav__word { display: none; }
  .nav .btn--small { padding: 0 14px; }
}
@media (max-width: 359px) {
  #nav-visit { display: none; }
}

/* 6b. The centred lockup (2026-10-26, founder; every page: build/shell.py and the home): the Menu on the left, the crest with
   "The Playpen School" under it in the centre, Notices and Book a visit on the right. The primary links stay in the
   markup for the scripts and the home sync; every page is in the Menu overlay. */
.nav--lockup .nav__bar { grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); gap: 16px; }
.nav--lockup .nav__left { grid-column: 1; justify-self: start; display: flex; align-items: center; min-width: 0; }
.nav--lockup .nav__brand { grid-column: 2; justify-self: center; flex-direction: column; justify-content: center; gap: 4px; text-align: center; width: max-content; max-width: 100%; }
.nav--lockup .nav__mark { width: 46px; height: 46px; }
.nav--lockup.is-solid .nav__mark, .nav--lockup.is-night .nav__mark { width: 38px; height: 38px; }
.nav--lockup .nav__word { display: block; font: 400 16px / 1.1 var(--font-serif); letter-spacing: 0.01em; }
.nav--lockup .nav__primary { display: none !important; }
.nav--lockup .nav__right { grid-column: 3; }
.nav--lockup .menu-btn__icon { order: -1; }
.nav--film.nav--lockup .nav__bar { grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); }
.nav--film.nav--lockup .nav__brand { justify-self: center; width: max-content; }
@media (max-width: 599px) {
  :root { --nav-h: 72px; }
  .nav--lockup .nav__bar { gap: 10px; }
  .nav--lockup .nav__mark { width: 34px; height: 34px; }
  .nav--lockup.is-solid .nav__mark, .nav--lockup.is-night .nav__mark { width: 30px; height: 30px; }
  .nav--lockup .nav__word { display: block; font-size: 13px; }
  /* the button keeps its name ("Menu" / "Close") for screen readers; on a phone it shows as the icon only */
  .nav--lockup:not(.nav--film) .menu-btn__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .nav--lockup:not(.nav--film) .menu-btn { min-width: 44px; justify-content: center; }
  /* Book a visit stays on one line in the right third (360 px: about 94 px wide) */
  .nav--lockup #nav-visit { white-space: nowrap; padding: 0 10px; font-size: 13px; }
}
@media (max-width: 339px) { .nav--lockup .nav__word { display: none; } }

/* 7. Hero ------------------------------------------------------------------ */
/* The plate is lifted under the lead by --hero-lift (spec §3.3: the copy sits in the paper zone of
   the image, the melted sky, which is the top 30 % of the 16:9 still = 16.9 vw; the brick walls
   begin at 15.75 vw). 12 vw keeps the lowest line of copy at least 3.75 vw above the walls and
   puts the terrace trees (32–65 % of the still) in the first screen from 1024 × 768 to 2560 × 1215.
   The dissolve into the paper (--hero-fade, CSS mask and the shader's uDissolve) reaches just
   past the copy so the words stand on paper, never on sky. Tablets (768–1023) get the same lift;
   phones keep the stacked cover (no lift, the image top is in the first screen on 390 × 844). */
.hero {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100svh;
  --hero-lift: 0px;
  --hero-fade: 110px;
}
@media (min-width: 768px) {
  .hero {
    /* polish pass: 18 vw (was 12): the baked paper zone now reaches 34 % of the frame (= 19 vw),
       so the lowest line of copy at 18 vw still stands on paper; with the two-line headline the
       terrace trees are in the first screen from 1280 × 720 up */
    --hero-lift: clamp(96px, 18vw, 460px);
    /* the mask's dissolve is short now (the paper is baked into the still): the copy clears it */
    --hero-fade: clamp(48px, 4vw, 80px);
  }
}
.hero__top {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: clamp(20px, 2.4vw, 36px);
  align-items: end;
  padding-top: calc(var(--nav-h) + clamp(20px, 3vw, 40px));
  padding-bottom: clamp(16px, 2vw, 28px);
  /* the lift: the media's auto top margin still parks the plate at the foot of a tall viewport
     (the copy and the plate shorter than 100 svh); otherwise the plate starts this much higher */
  margin-bottom: calc(-1 * var(--hero-lift));
}
@media (min-width: 1920px) {
  .hero__top { width: min(100% - 2 * var(--margin), 2080px); }
}
.hero__text { grid-column: 1 / -1; }
.hero__label { margin-bottom: clamp(16px, 2vw, 28px); }
/* the two headline lines: inline on narrow screens, one line each from 1280 up */
.hero__l { display: inline; }
@media (min-width: 1280px) {
  .hero__l { display: block; }
}
.hero__aside {
  grid-column: 7 / -1;
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 2vw, 28px);
  padding-bottom: 0.12em;
}
@media (min-width: 1280px) {
  .hero__aside { grid-column: 8 / -1; }
}
.hero__lead { max-width: 46ch; color: var(--ink); }
.hero__actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px 32px;
}
.hero__media {
  position: relative;
  margin-top: auto;
  width: 100%;
  background: var(--paper);
}
.hero__picture {
  width: 100%;
  overflow: hidden;
  /* the plate's top edge dissolves into the page over --hero-fade (the baked sky is a shade darker
     than the paper, and the lifted copy sits in that zone); the full tier does the same inside the
     shader (uDissolve), since the plane is drawn on the canvas. The mask sits on the picture, not
     the media: a masked media would be a stacking context at z-index auto and carry the caption
     under the fixed canvas (z-index 1). */
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 var(--hero-fade));
  mask-image: linear-gradient(to bottom, transparent, #000 var(--hero-fade));
}
.hero__picture img {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  /* never taller than the screen: on a 2560 × 1215 monitor the 1440 px plate is cropped at its
     foot (object-position keeps the top edge), so the cover stays about one screen */
  max-height: 100svh;
  object-fit: cover;
  object-position: 50% 0;
  transform-origin: 50% 70%;
}
.hero__caption {
  position: absolute;
  left: var(--margin);
  bottom: 24px;
  z-index: 2;
  margin: 0;
  padding: 8px 12px;
  background: var(--paper-3);
  border: 1px solid var(--clay);
}
/* The corner (Scroll cue + the film's Pause disc) is the hero's last child, a zero-height sticky
   line at the foot of the cover: it rides 24 px above the viewport's bottom edge from the first
   screen, whatever the screen height, and comes to rest at the plate's bottom-right when the
   cover scrolls out. The Pause disc is therefore on screen whenever the loop is (WCAG 2.2.2). */
.hero__corner {
  position: sticky;
  bottom: 0;
  z-index: 2;
  height: 0;
  width: 100%;
  pointer-events: none;
}
.hero__corner-inner {
  position: absolute;
  right: var(--margin);
  bottom: 24px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  pointer-events: auto;
}
/* the scroll cue: a bare 1 px line and a drifting dot (the boxed, labelled version read as a widget) */
.hero__cue {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0 12px;
}
.hero__cue-line {
  position: relative;
  width: 1px; height: 56px;
  background: var(--clay);
}
.hero__cue-dot {
  position: absolute;
  left: -1.5px; top: 0;
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--maroon);
}
@media (prefers-reduced-motion: no-preference) {
  html:not([data-tier="still"]) .hero__cue-dot { animation: cue-drift 2.4s var(--ease-out) infinite; }
}
@keyframes cue-drift {
  0% { transform: translateY(0); opacity: 0; }
  15% { opacity: 1; }
  80% { opacity: 1; }
  100% { transform: translateY(52px); opacity: 0; }
}
/* (2026-10-20) The light tier's CSS sun and Ken Burns, and the full tier's "hide the DOM image once
   the WebGL plane has drawn" rule, were removed with the film hero: the poster is frame 0 of the
   film and must never move or disappear (the WebGL renderer no longer draws the hero). */
@media (max-width: 1023px) {
  .hero__top { grid-template-columns: minmax(0, 1fr); }
  .hero__text, .hero__aside { grid-column: 1; }
  .hero__aside { padding-top: 8px; padding-bottom: 0; }
  .hero__lead { max-width: 60ch; }
}
@media (max-width: 767px) {
  .hero { display: grid; grid-template-columns: 100%; }
  .hero__top { display: contents; }
  .hero__text { order: 1; padding: calc(var(--nav-h) + 24px) var(--margin) 24px; }
  .hero__media { order: 2; }
  .hero__aside { order: 3; padding: 28px var(--margin) 0; gap: 24px; }
  .hero__picture img { aspect-ratio: 4 / 5; max-height: none; }
  .hero__cue, .hero__corner { display: none; }
  .hero__caption { bottom: 16px; }
}

/* 7b. Film hero and burger-only header (2026-10-20, founder) -------------------------------------
   The school's own film fills the first screen edge to edge (object-fit: cover, 100svh), under an ink
   scrim that keeps the header and the copy readable (contrast measured on the brightest frames, see
   redesign-2026-10-20-hero/04-build-notes.md). Copy sits bottom-left. Scoped to .hero--film and
   .nav--film: the inner pages share this file and keep their own hero and header. */

/* Header on the home: crest and wordmark top-left, the burger top-right, nothing else */
.nav--film .nav__primary { display: none !important; }
.nav--film .nav__bar { grid-template-columns: minmax(0, 1fr) auto; }
/* the brand link hugs the crest and wordmark (it stretched 1180 px across the bar: a header-wide
   focus ring, and a tap anywhere in the empty bar jumped to the top) */
.nav--film .nav__brand { justify-self: start; width: max-content; max-width: 100%; }
.nav--film .nav__word { display: block; }
@media (max-width: 339px) { .nav--film .nav__word { display: none; } }
.nav--film .menu-btn__label {   /* stays the button's name ("Menu" / "Close", js/sections/menu.js) */
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}
.nav--film .menu-btn {
  justify-content: center;
  width: 48px; height: 48px;
  min-height: 48px;
  padding: 0;
  border-radius: 0;   /* a deliberate sharp square, as on the reference (open choice for the founder) */
  background: var(--maroon);
  color: var(--paper);
  transition: background-color var(--t-hover) var(--ease-soft);
}
.nav--film .menu-btn:hover { background: var(--maroon-deep); }
.nav--film .menu-btn__icon { width: 22px; }
.nav--film.is-over-hero { color: var(--paper); }
/* a stale over-film class can never leave paper text on paper */
.nav--film.is-solid { color: var(--ink); }
/* the header's own scrim while it sits over the film: it travels with the fixed header, so the
   wordmark keeps its dark backing while the film drifts and scrolls away (the hero's own top scrim
   moved here, 2026-10-20 fix round) */
.nav--film::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 200px;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(28, 23, 21, 0.76) 0, rgba(28, 23, 21, 0.62) 80px, rgba(28, 23, 21, 0) 200px);
  opacity: 0;
  transition: opacity var(--t-ui) var(--ease-soft);
}
.nav--film.is-over-hero::before { opacity: 1; }
html.menu-open .nav--film::before { opacity: 0; }
.nav--film.is-over-hero .nav__word { text-shadow: 0 0 12px rgba(28, 23, 21, 0.5); }
.nav--film.is-over-hero :focus-visible { outline-color: var(--paper); }
html.menu-open .nav--film { color: var(--ink); }
html.menu-open .nav--film :focus-visible { outline-color: var(--maroon); }
/* the crest is maroon and gold: over the film it sits on a small paper disc, so it reads on every
   frame; the disc fades out once the header turns paper */
.nav--film .nav__mark { position: relative; isolation: isolate; border-radius: 50%; }
.nav--film .nav__mark::before {
  content: '';
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  background: var(--paper);
  opacity: 0;
  transition: opacity var(--t-ui) var(--ease-soft);
  z-index: -1;
}
.nav--film.is-over-hero .nav__mark::before { opacity: 0; }   /* 2026-10-20: no paper disc behind the new crest */
html.menu-open .nav--film .nav__mark::before { opacity: 0; }

/* The hero: one screen, the film edge to edge */
.hero--film {
  position: relative;
  display: block;
  height: 100vh;
  height: 100svh;
  min-height: 0;
  overflow: hidden;
  background: var(--ink);
  color: var(--paper);
  --hero-lift: 0px;
  --hero-fade: 0px;
}
.hero--film .hero__media {
  position: absolute;
  inset: 0;
  margin: 0;
  overflow: hidden;
  background: var(--ink);
  z-index: 0;
}
.hero--film .hero__picture,
.hero--film .hero__picture img,
.hero--film .hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-height: none;
  aspect-ratio: auto;
  object-fit: cover;
  object-position: 50% 50%;
  -webkit-mask-image: none;
  mask-image: none;
  transform: none;
  animation: none;
}
.hero--film .hero__picture { overflow: hidden; }
.hero--film .hero__video {
  display: block;
  opacity: 0;
  background: transparent;
  transition: opacity 700ms var(--ease-soft);
}
/* the poster is frame 0, so the film fades in over the same picture: no jump at the hand-off */
.hero--film .hero__media.is-playing .hero__video { opacity: 1; }
.hero--film .hero__scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to top, rgba(28, 23, 21, 0.86) 0, rgba(28, 23, 21, 0.74) 22%, rgba(28, 23, 21, 0.6) 42%, rgba(28, 23, 21, 0.3) 54%, rgba(28, 23, 21, 0) 66%),
    linear-gradient(to right, rgba(28, 23, 21, 0.34) 0, rgba(28, 23, 21, 0) 58%);
}
.hero--film .hero__top {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 2;
  display: block;
  margin: 0 auto;
  /* the copy sits low (the reference keeps its words in the bottom fifth); the buttons share the
     pause pill's bottom line. The width is the header's grid (the 1920 rule above would widen it). */
  width: min(100% - 2 * var(--margin), var(--band-max));
  padding: 0 0 var(--hero-foot);
}
.hero--film { --hero-foot: clamp(28px, 4vh, 44px); }
/* the scroll fade (cover.js) never hides a focused button */
.hero--film .hero__top:focus-within { opacity: 1 !important; }
.hero--film .hero__text { max-width: 1120px; padding: 0; }
.hero--film .hero__label {   /* gold text failed 4.5:1 on the bright frames */
  margin-bottom: clamp(14px, 1.6vw, 22px);
  color: var(--paper);
  font-size: clamp(12px, 0.8vw, 14px);
  letter-spacing: 0.14em;
}
.hero--film .hero__title {
  font-size: clamp(44px, 5.4vw, 104px);
  line-height: 0.96;
  color: var(--paper);
  text-shadow: 0 1px 24px rgba(28, 23, 21, 0.25);
}
.hero--film .hero__title em { color: #EBCD88; }   /* a lighter gold, hero only: --gold-text measured 2.67:1 on the brightest frames */
.hero--film .hero__lead {
  max-width: 44ch;
  margin-top: clamp(14px, 1.4vw, 22px);
  font-size: clamp(18px, 1.35vw, 24px);
  color: var(--paper);
}
.hero--film .hero__actions { margin-top: clamp(20px, 2vw, 28px); gap: 14px 32px; }
.hero--film .hero__actions .btn--text {
  color: var(--paper);
  background-image: linear-gradient(var(--gold-text), var(--gold-text));
}
.hero--film :focus-visible { outline-color: var(--paper); }

/* Pause / play (WCAG 2.2.2): a labelled pill in the bottom-right corner, 44 px tall */
.hero__pause {
  position: absolute;
  z-index: 3;
  /* on the header's grid: the burger's right edge, capped with the band at 1600 px */
  right: max(var(--margin), calc((100% - var(--band-max)) / 2));
  bottom: calc(var(--hero-foot) + 2px);   /* centred on the 48 px buttons' line */
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  min-width: 44px;
  padding: 0 16px 0 14px;
  border: 1px solid rgba(245, 241, 234, 0.55);
  border-radius: 999px;
  background: rgba(28, 23, 21, 0.55);
  color: var(--paper);
  font: 500 13.5px / 1 var(--font-sans);
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: border-color var(--t-micro), background-color var(--t-micro);
}
.hero__pause[hidden] { display: none; }
/* the root's 72 px scroll-padding-bottom (for the phone action bar) made a keyboard focus here nudge the
   page 41 px; the bar is never shown over the hero, so the button opts out */
.hero__pause { scroll-margin-bottom: -72px; }
.hero__pause:hover { border-color: var(--paper); background: rgba(28, 23, 21, 0.75); }
.hero__pause:focus-visible { outline: 2px solid var(--paper); outline-offset: 3px; }
.hero__pause-icon { position: relative; flex: none; width: 12px; height: 12px; }
.hero__pause-icon::before, .hero__pause-icon::after {
  content: '';
  position: absolute;
  top: 0; bottom: 0;
  width: 3px;
  background: currentColor;
}
.hero__pause-icon::before { left: 1px; }
.hero__pause-icon::after { right: 1px; }
.hero__pause[data-state="paused"] .hero__pause-icon::before {
  left: 2px; top: 0; bottom: auto;
  width: 0; height: 0;
  background: none;
  border-left: 10px solid currentColor;
  border-top: 6px solid transparent;
  border-bottom: 6px solid transparent;
}
.hero__pause[data-state="paused"] .hero__pause-icon::after { display: none; }

@media (max-width: 767px) {
  .hero--film .hero__top { padding-bottom: 84px; }
  /* "The whole of / a childhood, / in one school.": each phrase on its own block, balanced; 350
     because 300 reads thin over the busy frames */
  .hero--film .hero__l { display: block; text-wrap: balance; }
  .hero--film .hero__title { font-size: clamp(34px, 9.6vw, 46px); font-weight: 350; }
  .hero--film .hero__lead { font-size: 17px; max-width: 34ch; }
  .hero--film .hero__actions { gap: 12px 24px; }
  /* the pause control: a 44 px round icon button; the label stays its accessible name and swaps */
  .hero__pause { bottom: 24px; width: 44px; padding: 0; justify-content: center; }
  .hero__pause-label {
    position: absolute;
    width: 1px; height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .hero--film .hero__scrim {
    background:
      linear-gradient(to top, rgba(28, 23, 21, 0.9) 0, rgba(28, 23, 21, 0.82) 30%, rgba(28, 23, 21, 0.68) 56%, rgba(28, 23, 21, 0.4) 70%, rgba(28, 23, 21, 0) 84%);
  }
}
/* 375 px and wider: the round pause button joins the buttons' row (no third row of controls), and
   the copy sits that much lower; the row keeps 56 px clear on the right for it */
@media (min-width: 375px) and (max-width: 767px) {
  .hero--film .hero__top { padding-bottom: 40px; }
  .hero--film .hero__actions { padding-right: 56px; }
  .hero__pause { bottom: 42px; }
}
/* short phones (320 x 568): the copy starts at 36 % of the height, so the scrim reaches higher */
@media (max-width: 767px) and (max-height: 640px) {
  .hero--film .hero__scrim {
    background:
      linear-gradient(to top, rgba(28, 23, 21, 0.9) 0, rgba(28, 23, 21, 0.84) 30%, rgba(28, 23, 21, 0.76) 56%, rgba(28, 23, 21, 0.64) 68%, rgba(28, 23, 21, 0.36) 80%, rgba(28, 23, 21, 0) 92%);
  }
}
/* shorter desktop and laptop screens (1280 x 720): the copy takes a larger share of the height, so the
   lower scrim reaches higher (the label measured 4.0:1 at 1280 x 720 with the default stops) */
@media (min-width: 768px) and (max-height: 820px) {
  .hero--film .hero__scrim {
    background:
      linear-gradient(to top, rgba(28, 23, 21, 0.86) 0, rgba(28, 23, 21, 0.78) 24%, rgba(28, 23, 21, 0.62) 48%, rgba(28, 23, 21, 0.3) 60%, rgba(28, 23, 21, 0) 74%),
      linear-gradient(to right, rgba(28, 23, 21, 0.36) 0, rgba(28, 23, 21, 0) 58%);
  }
}
/* short landscape screens (a phone on its side): smaller type so the copy stays under the header */
@media (max-height: 560px) and (orientation: landscape) {
  .hero--film .hero__top { padding-bottom: 28px; padding-right: 170px; }
  .hero--film .hero__label { display: none; }
  .hero--film .hero__title { font-size: clamp(30px, 7.4vh, 44px); }
  .hero--film .hero__l { display: inline; }
  .hero--film .hero__lead { margin-top: 10px; font-size: 16px; max-width: 52ch; }
  .hero--film .hero__actions { margin-top: 14px; }
  .hero__pause { bottom: 28px; }
  /* the 72 px header took 18 % of a 390 px screen: a 56 px bar (nav.js reads it into --nav-h) */
  .nav--film .nav__bar { height: 56px; }
  .nav--film .menu-btn { width: 44px; height: 44px; min-height: 44px; }
  .nav--film .nav__mark { width: 42px; height: 42px; }
}

/* 8. Results and Achievement (2026-10-18; they replace the Ground sheet) --------------------------
   Three panels, one per Cambridge level: a ring of the grade split (js/sections/results.js draws it
   in; the markup holds the final state), the plain-English line, the bars, the subjects. */
.results__head {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: clamp(24px, 3vw, 40px);
  margin-bottom: clamp(40px, 5vw, 72px);
}
.results__head h2 { grid-column: 1 / span 10; max-width: 18ch; }
.results__lead { grid-column: 1 / span 7; max-width: 54ch; }
.results__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--gutter);
}
/* the grade colours, darkest for the top grade; each bar and ring segment reads --c */
.seg--1 { --c: var(--maroon); }
.seg--2 { --c: var(--gold); }
.seg--3 { --c: #D69A2D; }
.seg--4 { --c: #C9B49B; }
.seg--5 { --c: #7D716A; }
.result {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 22px;
  padding: clamp(22px, 2.2vw, 34px);
  background: var(--paper-3);
  border: 1px solid var(--clay);
  border-top: 3px solid var(--maroon);
}
.result__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 14px;
  border-bottom: var(--hairline);
}
.result__name { font: 400 clamp(28px, 2.4vw, 40px) / 1.05 var(--font-serif); letter-spacing: -0.005em; }
.result__chart { position: relative; width: min(100%, 250px); aspect-ratio: 1; margin-inline: auto; }
.donut { display: block; width: 100%; height: 100%; overflow: visible; }
.donut__track, .donut__seg { fill: none; stroke-width: 14; }
.donut__track { stroke: var(--paper-2); }
.donut__seg { stroke: var(--c); }
.donut__centre {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.donut__num {
  font: 300 clamp(50px, 4.4vw, 68px) / 1 var(--font-serif);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums lining-nums;
}
.donut__pc { font-size: 0.5em; margin-left: 2px; vertical-align: 0.7em; }
.donut__what { margin-top: 6px; font: 500 14px / 1.2 var(--font-sans); color: var(--maroon); }
.result__say { font: 400 clamp(18px, 1.3vw, 21px) / 1.4 var(--font-serif); }
.result__say b { font-weight: 600; color: var(--maroon); }
.grades { list-style: none; display: grid; gap: 10px; }
.grades__row {
  display: grid;
  grid-template-columns: 58px minmax(0, 1fr) 42px;
  align-items: center;
  gap: 12px;
  font: 500 15px / 1.2 var(--font-sans);
}
.grades__bar { position: relative; height: 8px; background: var(--paper-2); overflow: hidden; }
/* the longest share is 46 %: the bar's full length stands for 50 % */
.grades__bar i { position: absolute; inset: 0 auto 0 0; width: calc(var(--p) * 2%); background: var(--c); transform-origin: left center; }
.grades__v { text-align: right; font-variant-numeric: tabular-nums; }
/* Subjects (2026-10-21, round 2): no fold-out. Each card ends in a one-line count; one compact panel
   under the cards lists all 14 subjects in three columns, each with level badges (O, AS, A). */
.result__subj {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 60px;
  padding-top: 16px;
  border-top: var(--hairline);
  color: var(--ink);
  text-decoration: none;
  font: 500 15px / 1.25 var(--font-sans);
  white-space: nowrap;
}
.result__subj-n { font: 300 40px / 1 var(--font-serif); color: var(--maroon); font-variant-numeric: lining-nums; }
.result__subj-t { flex: 1; }
.result__subj-go { position: relative; flex: none; width: 32px; height: 32px; border: 1px solid var(--clay); border-radius: 50%; transition: transform var(--t-ui) var(--ease-out), background-color var(--t-ui) ease, border-color var(--t-ui) ease; }
.result__subj-go::before { content: ''; position: absolute; left: 50%; top: 9px; width: 1.5px; height: 13px; margin-left: -0.75px; background: currentColor; }
.result__subj-go::after { content: ''; position: absolute; left: 50%; top: 14px; width: 7px; height: 7px; margin-left: -4px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(45deg); }
.result__subj:hover, .result__subj:focus-visible { color: var(--maroon); }
.result__subj:hover .result__subj-go, .result__subj:focus-visible .result__subj-go { border-color: var(--maroon); transform: translateY(3px); }

.sub {
  margin-top: clamp(28px, 3vw, 40px);
  padding: clamp(24px, 2.6vw, 40px) clamp(20px, 2.6vw, 40px) clamp(14px, 1.6vw, 24px);
  background: var(--paper-3);
  border: 1px solid var(--clay);
  border-top: 3px solid var(--maroon);
  scroll-margin-top: calc(var(--nav-h) + 24px);
}
.sub__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px 40px;
  padding-bottom: clamp(18px, 2vw, 26px);
  border-bottom: 1px solid var(--ink);
}
.sub__title { margin-top: 10px; font: 400 clamp(26px, 2.2vw, 36px) / 1.1 var(--font-serif); letter-spacing: -0.01em; }
.sub__key { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; font: 400 14px / 1.2 var(--font-sans); color: var(--ink-2); }
.sub__key .sub__b + .sub__b, .sub__key .sub__b:not(:first-child) { margin-left: 12px; }
.sub__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: clamp(28px, 3.4vw, 64px); }
.sub__col { display: flex; flex-direction: column; }
.sub__grp { padding-top: clamp(20px, 2vw, 28px); }
.sub__gh { color: var(--gold); padding-bottom: 6px; }
.sub__list { list-style: none; }
.sub__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 50px;
  padding: 8px 0;
  border-bottom: var(--hairline);
}
.sub__list .sub__row:last-child { border-bottom: 0; }
.sub__name { font: 400 clamp(18px, 1.3vw, 20px) / 1.25 var(--font-serif); }
.sub__note { display: block; margin-top: 3px; font: 400 13px / 1.3 var(--font-sans); color: var(--ink-2); }
.sub__lvs { flex: none; display: flex; gap: 6px; }
.sub__b {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 34px;
  height: 26px;
  padding: 0 7px;
  border-radius: 999px;
  background: var(--maroon);
  color: var(--paper);
  font: 600 12px / 1 var(--font-sans);
  letter-spacing: 0.04em;
  transition: opacity var(--t-ui) ease, background-color var(--t-ui) ease, box-shadow var(--t-ui) ease;
}
/* one colour per level (2026-10-21): O Level gold, AS Level maroon, A Level ink; the card of each
   level carries the same colour on its top rule and its subject count, so card and badges match */
[data-lv="o"] { --lv: #8A6216; }
[data-lv="as"] { --lv: var(--maroon); }
[data-lv="a"] { --lv: #2A2320; }
.result[data-lv] { border-top-color: var(--lv); }
.result[data-lv] .result__subj-n { color: var(--lv); }
.sub__b[data-lv] { background: var(--lv); }
.sub__b.is-off { background: transparent; box-shadow: inset 0 0 0 1px var(--paper-2); }
/* a card's "subjects offered" line, hovered or focused, lights that level's badges below */
.results:has(.result__subj[data-lv="o"]:is(:hover, :focus-visible)) .sub__grid .sub__b:not([data-lv="o"]),
.results:has(.result__subj[data-lv="as"]:is(:hover, :focus-visible)) .sub__grid .sub__b:not([data-lv="as"]),
.results:has(.result__subj[data-lv="a"]:is(:hover, :focus-visible)) .sub__grid .sub__b:not([data-lv="a"]) { opacity: 0.18; }
@media (max-width: 1023px) {
  .sub__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 639px) {
  .sub { padding-inline: 16px; }
  .sub__grid { grid-template-columns: minmax(0, 1fr); }
  .sub__key { gap: 8px; }
  .sub__key .sub__b:not(:first-child) { margin-left: 8px; }
  .sub__b { min-width: 30px; height: 24px; padding: 0 6px; font-size: 11.5px; }
  .sub__lvs { gap: 5px; }
}
.results__foot {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: clamp(28px, 3vw, 40px) var(--gutter);
  margin-top: clamp(40px, 5vw, 72px);
}
.venue { grid-column: 1 / span 7; padding: clamp(20px, 2vw, 28px) clamp(20px, 2.4vw, 32px); background: var(--paper-2); border-left: 3px solid var(--gold); }
.venue__text { margin-top: 10px; font: 400 clamp(19px, 1.45vw, 24px) / 1.4 var(--font-serif); max-width: 52ch; }
.results__aside { grid-column: 9 / -1; align-self: end; }
.results__links { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; font: 400 16px / 1.4 var(--font-sans); }
.results__note { margin-top: 16px; }
@media (max-width: 1023px) {
  .results__head h2, .results__lead, .venue, .results__aside { grid-column: 1 / -1; }
  .results__grid { grid-template-columns: minmax(0, 1fr); }
  .result__chart { width: min(100%, 220px); }
}
@media (max-width: 639px) {
  .result { gap: 18px; }
  .result__chart { width: min(100%, 196px); }
}
@media (min-width: 640px) and (max-width: 1023px) {
  /* tablets: the ring beside the line and the bars */
  .result { display: grid; grid-template-columns: 220px minmax(0, 1fr); column-gap: 32px; row-gap: 18px; align-items: center; }
  .result__head, .result__subj { grid-column: 1 / -1; }
  .result__chart { grid-row: span 2; }
}

/* Achievement: the school's own photograph in a maroon mount with a gold inner line */
.achievement__layout {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: clamp(36px, 4vw, 64px) var(--gutter);
  align-items: center;
}
.frame {
  position: relative;
  grid-column: 1 / span 7;
  padding: clamp(10px, 1.2vw, 16px);
  background: var(--maroon);
  box-shadow: 0 32px 60px -36px rgba(92, 4, 7, 0.55);
}
.frame::after {
  content: '';
  position: absolute;
  inset: clamp(4px, 0.5vw, 7px);
  border: 1px solid var(--gold-text);
  pointer-events: none;
}
.frame__mat { padding: clamp(6px, 0.8vw, 10px); background: var(--paper-3); }
.frame img { display: block; width: 100%; height: auto; }
.achievement__text { grid-column: 8 / -1; padding-left: clamp(0px, 2vw, 32px); }
.achievement__text h2 { max-width: 12ch; margin-bottom: clamp(20px, 2.4vw, 32px); }
.achievement__body { margin-top: 16px; font-size: 17px; line-height: 1.55; max-width: 52ch; }
.feats { list-style: none; margin-top: clamp(24px, 3vw, 36px); border-top: var(--hairline); }
.feat {
  display: grid;
  grid-template-columns: 92px minmax(0, 1fr);
  gap: 16px;
  align-items: baseline;
  padding: 14px 0;
  border-bottom: var(--hairline);
}
.feat__n { font: 300 clamp(36px, 3vw, 48px) / 1 var(--font-serif); color: var(--maroon); font-variant-numeric: tabular-nums lining-nums; white-space: nowrap; }
.feat__t { font: 400 15px / 1.45 var(--font-sans); color: var(--ink-2); }
.achievement__link { margin-top: 24px; font: 400 16px / 1.4 var(--font-sans); }
@media (max-width: 1023px) {
  .frame, .achievement__text { grid-column: 1 / -1; }
  .achievement__text { padding-left: 0; }
}
/* Achievement carousel (2026-10-20): 7 Graduation Ceremony 2025 photographs in the same mount. The
   plate holds its 3:2 shape, the slides are stacked in it and cross-dissolve (js/sections/results.js
   drives the fade, the slow drift and the gold progress line). Without JavaScript the first slide
   shows on its own and the counter and buttons stay hidden. */
:is(.achievement, .words) .ach-carousel { grid-column: 1 / span 7; min-width: 0; }
:is(.achievement, .words) .ach-plate { aspect-ratio: 3 / 2; background: var(--paper-2); touch-action: pan-y; }
:is(.achievement, .words) .ach-slide { position: absolute; inset: 0; opacity: 0; z-index: 0; }
:is(.achievement, .words) .ach-slide.is-active { opacity: 1; z-index: 1; }
:is(.achievement, .words) .ach-slide.is-incoming { z-index: 2; }
:is(.achievement, .words) .ach-slide__media { display: block; width: 100%; height: 100%; }
:is(.achievement, .words) .ach-slide img { width: 100%; height: 100%; object-fit: cover; }
:is(.achievement, .words) .ach-carousel:not(.is-still) .ach-slide.is-active .ach-slide__media,
:is(.achievement, .words) .ach-carousel:not(.is-still) .ach-slide.is-incoming .ach-slide__media { will-change: transform; }
:is(.achievement, .words) .ach-carousel:not(.is-still) .ach-slide.is-incoming { will-change: opacity; }
:is(.achievement, .words) .ach-bar {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px 20px;
  margin-top: clamp(18px, 2vw, 26px);
  padding-top: clamp(14px, 1.6vw, 20px);
}
:is(.achievement, .words) .ach-bar__track { position: absolute; top: 0; left: 0; right: 0; height: 1px; background: var(--clay); }
:is(.achievement, .words) .ach-bar__fill {
  position: absolute;
  top: -0.5px; left: 0; right: 0;
  height: 2px;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: 0 50%;
}
:is(.achievement, .words) .ach-cap { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 16px; flex: 1 1 0; min-width: 0; }
:is(.achievement, .words) .ach-count {
  font: 300 clamp(22px, 1.8vw, 28px) / 1 var(--font-serif);
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: 0.01em;
  color: var(--ink-2);
  white-space: nowrap;
}
:is(.achievement, .words) .ach-count__now { display: inline-block; color: var(--maroon); }
:is(.achievement, .words) .ach-count__sep { margin: 0 0.32em; color: var(--clay); }
:is(.achievement, .words) .ach-cap__t {
  font: 500 11.5px / 1.35 var(--font-sans);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
}
:is(.achievement, .words) .ach-nav { display: flex; gap: 8px; flex: none; }
:is(.achievement, .words) .ach-btn {
  width: 44px; height: 44px;
  padding: 0;
  display: grid;
  place-items: center;
  border: 1px solid var(--clay);
  border-radius: 50%;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  transition: border-color var(--t-hover) var(--ease-out), color var(--t-hover) var(--ease-out), background-color var(--t-hover) var(--ease-out);
}
:is(.achievement, .words) .ach-btn svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform var(--t-hover) var(--ease-out);
}
:is(.achievement, .words) .ach-btn:hover { border-color: var(--maroon); color: var(--maroon); background-color: var(--paper-3); }
:is(.achievement, .words) .ach-btn--prev:hover svg { transform: translateX(-2px); }
:is(.achievement, .words) .ach-btn--next:hover svg { transform: translateX(2px); }
:is(.achievement, .words) .ach-btn--toggle .ach-ico-play { display: none; }
:is(.achievement, .words) .ach-btn--toggle[data-state="paused"] .ach-ico-play { display: inline; }
:is(.achievement, .words) .ach-btn--toggle[data-state="paused"] .ach-ico-pause { display: none; }
:is(.achievement, .words) .ach-btn[hidden] { display: none; }
:is(.achievement, .words) .ach-carousel:not(.is-ready) .ach-count,
:is(.achievement, .words) .ach-carousel:not(.is-ready) .ach-nav,
:is(.achievement, .words) .ach-carousel:not(.is-ready) .ach-bar__fill { visibility: hidden; }
:is(.achievement, .words) .ach-carousel.is-still .ach-bar__fill { display: none; }
@media (max-width: 1023px) {
  :is(.achievement, .words) .ach-carousel { grid-column: 1 / -1; }
}
@media (max-width: 767px) {
  :is(.achievement, .words) .ach-cap__t { font-size: 12.5px; }
}

/* 9. The Ascent ------------------------------------------------------------ */
.ascent__intro { margin-bottom: clamp(40px, 6vw, 96px); }
.ascent__intro h2 { max-width: 14ch; margin-bottom: clamp(24px, 3vw, 40px); }
.ascent__intro .lead { max-width: 60ch; }
/* the pinned scene uses a wider band than the sheets (1920 px): the plate is the screen */
.ascent__pin {
  position: relative;
  width: min(100% - 2 * var(--margin), 1920px);
  margin-inline: auto;
}
.ascent__media { position: relative; }
.ascent__mount {
  padding: 12px;
  background: var(--paper-3);
  border: 1px solid var(--clay);
}
.ascent__stage {
  position: relative;
  aspect-ratio: 16 / 10;
  width: 100%;
  overflow: hidden;
  background: var(--paper-2);
}
.ascent__pic {
  position: absolute;
  inset: 0;
  opacity: 0;
}
.ascent__pic img, .ascent__video {
  width: 100%; height: 100%;
  object-fit: cover;
}
.ascent__pic.is-active { opacity: 1; z-index: 2; }
.ascent__pic.is-prev { opacity: 0.6; z-index: 1; }
.ascent__video {
  position: absolute;
  inset: 0;
  z-index: 3;
  opacity: 0;
  pointer-events: none;
  transition: opacity 600ms var(--ease-soft);
}
.ascent__stage.is-playing .ascent__video { opacity: 1; }
#ascent-pause { position: absolute; right: 16px; bottom: 16px; z-index: 4; }
.ascent__under {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 24px;
  margin-top: 12px;
}
.ascent__counter {
  font: 400 14px / 1 var(--font-sans);
  color: var(--ink-2);
  font-variant-numeric: tabular-nums lining-nums;
  white-space: nowrap;
}
/* the current number is a stack: at a chapter change the incoming numeral rises in while the
   outgoing one leaves (ascent.js), so the counter never reads "/ 05" alone */
.counter__cur { display: inline-grid; color: var(--ink); vertical-align: top; }
.counter__num { grid-area: 1 / 1; }
.rail {
  position: relative;
  list-style: none;
  padding-left: 22px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  font: 400 14px / 1.4 var(--font-sans);
}
/* inactive stops in ink-2 (8.8:1 on paper); the earlier opacity 0.5 fell to about 3.5:1 */
.rail li { color: var(--ink-2); transition: color var(--t-ui) var(--ease-soft); }
.rail li.is-active { color: var(--ink); }
/* 18 px of text plus 6 px above and below = a 30 px target (WCAG 2.5.8); the negative margins keep
   the 10 px rhythm of the list */
.rail a { display: inline-block; padding-block: 6px; margin-block: -6px; color: inherit; text-decoration: none; }
.rail__marker {
  position: absolute;
  left: 0; top: 0;
  width: 10px; height: 1px;
  background: var(--maroon);
  transform: translateY(var(--rail-y, 10px));
  transition: transform var(--t-ui) var(--ease-move);
}
.chapter__title { margin-bottom: 16px; max-width: 14ch; }
/* (2026-10-21) the rooftop pool picture is an illustration until the school sends a photograph */
.chapter__note { margin-top: 14px; padding-left: 12px; border-left: 2px solid var(--gold); font: 400 14px / 1.45 var(--font-sans); color: var(--ink-2); }
.chapter > p { max-width: 42ch; font-size: var(--body-size); }
.chapter__cap { margin-top: 20px; }
/* the facilities list sits in the last chapter (the roof) since the polish pass */
.ascent__facilities {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 0;
  margin-top: 24px;
  padding-top: 16px;
  border-top: var(--hairline);
  max-width: 46ch;
  font: 400 13.5px / 1.5 var(--font-sans);
  color: var(--ink-2);
}
.ascent__facilities li + li::before { content: '\00B7'; margin: 0 8px; color: var(--gold); }
@media (min-width: 1024px) {
  .ascent__pin {
    height: 100svh;
    display: grid;
    /* polish pass: the plate takes three quarters of the band and stands 4:3 (cover-fitted), so it
       fills 70 % and more of the screen height at 1440 × 900 and 1920 × 1080; the copy keeps a
       narrow column on the right. The vertical scale is a phone device now: on desktop the rail
       and the counter are the two instruments (the scale made a third for the same idea). */
    grid-template-columns: minmax(0, 9fr) minmax(0, 3fr);
    column-gap: clamp(24px, 3vw, 48px);
    align-items: center;
    padding-top: calc(var(--nav-h) + 12px);
    padding-bottom: 20px;
  }
  .ascent__rule { display: none; }
  .ascent__media { align-self: center; }
  .ascent__mount { padding: 10px; }
  .ascent__stage { aspect-ratio: 4 / 3; max-height: calc(100svh - var(--nav-h) - 112px); }
  .ascent__side {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: clamp(28px, 4vh, 48px);
    min-height: 0;
  }
  .ascent__chapters { position: relative; display: grid; }
  /* inactive chapters stay in the accessibility tree (opacity, not visibility) */
  .chapter { grid-area: 1 / 1; opacity: 0; pointer-events: none; }
  .chapter.is-active { opacity: 1; pointer-events: auto; }
  html:not(.js) .chapter { position: static; opacity: 1; margin-bottom: 32px; pointer-events: auto; }
  html:not(.js) .ascent__chapters { display: block; }
}
@media (min-width: 1024px) and (max-width: 1279px) {
  .ascent__pin { grid-template-columns: minmax(0, 7.5fr) minmax(0, 4.5fr); }
}
@media (max-height: 760px) and (min-width: 1024px) {
  .ascent__pin { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
}
@media (max-width: 1023px) {
  .ascent__pin {
    display: grid;
    grid-template-columns: 44px minmax(0, 1fr);
    column-gap: 16px;
    align-items: start;
  }
  .ascent__rule {
    grid-column: 1;
    grid-row: 1 / span 2;
    position: sticky;
    top: calc(var(--nav-h) + 16px);
    height: calc(100svh - 160px);
  }
  .rule--v { width: 44px; }
  .rule--v .rule__tick b { display: none; }
  .rule--v .rule__tick[data-tick="1"] b, .rule--v .rule__tick[data-tick="5"] b, .rule--v .rule__tick.is-lit b { display: block; }
  .ascent__media {
    grid-column: 2;
    grid-row: 1;
    position: sticky;
    top: var(--nav-h);
    /* above .ascent__side (z-index 2): the chapter copy slides behind the solid paper strip
       instead of being drawn over the photograph */
    z-index: 3;
    background: var(--paper);
    padding-top: 12px;
    padding-bottom: 12px;
  }
  .ascent__mount { padding: 8px; }
  /* 4:3, capped at 38 svh so a chapter's title and first lines fit under the strip (the stage used
     to run a chapter ahead of the copy at 46 svh) */
  .ascent__stage { aspect-ratio: 4 / 3; max-height: min(38svh, 480px); }
  .ascent__side { grid-column: 2; grid-row: 2; }
  .rail { display: none; }
  .chapter { padding: 32px 0 40px; border-bottom: var(--hairline); }
  .chapter:first-child { padding-top: 20px; }
  .chapter:last-child { border-bottom: 0; }
  html:not(.js) .ascent__stage { aspect-ratio: auto; max-height: none; }
  html:not(.js) .ascent__pic { position: static; opacity: 1; }
}
/* Narrow phones: the storey rule becomes a 24 px strip without numerals, so the copy keeps a
   readable measure (the band and the lit tick still climb) */
@media (max-width: 479px) {
  .ascent__pin { grid-template-columns: 24px minmax(0, 1fr); column-gap: 12px; }
  .ascent__pin .rule--v { width: 24px; }
  .ascent__pin .rule--v .rule__tick[data-tick] b { display: none; }
}

/* 10. Learning ------------------------------------------------------------- */
.learning h2 { max-width: 12ch; margin-bottom: clamp(40px, 5vw, 72px); }
.learning__layout { display: flex; flex-direction: column; }
.learning__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(32px, 4vw, 48px) var(--gutter);
}
.stage { display: flex; flex-direction: column; gap: 10px; }
.stage .plate { margin-bottom: 14px; }
.stage .plate img { aspect-ratio: 4 / 5; object-fit: cover; width: 100%; }
/* two caption lines are reserved wherever stages share a row, so a caption that wraps (Elementary
   at 1440) never pushes its number and name off the others' baseline */
@media (min-width: 640px) {
  .stage .plate__cap { min-height: 2.9em; min-height: 2lh; }
}
.stage__n { order: 0; }
.stage__name { margin-top: 2px; }
.stage__classes { color: var(--ink-2); }
.stage > p:not(.label) { font-size: 17px; line-height: 1.5; max-width: 40ch; }
.stage__link { align-self: flex-start; margin-top: 6px; font-family: var(--font-sans); font-size: 15px; }
#learning-rule { order: 2; }
@media (max-width: 1023px) {
  .learning__layout {
    display: grid;
    grid-template-columns: 28px minmax(0, 1fr);
    column-gap: 20px;
    align-items: start;
  }
  .learning__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-column: 2; }
  #learning-rule {
    order: 0;
    grid-column: 1;
    grid-row: 1;
    position: sticky;
    top: calc(var(--nav-h) + 24px);
    height: calc(100svh - var(--nav-h) - 120px);
    width: 28px;
    flex-direction: column;
    align-items: flex-end;
    padding: 0;
    margin: 0;
  }
  .rule--h::before { left: auto; right: 0; top: 0; bottom: 0; width: 2px; height: auto; }
  .rule--h .rule__tick { flex-direction: row; width: auto; height: 0; align-items: center; gap: 8px; }
  .rule--h .rule__tick::before { width: 8px; height: 1px; margin: 0; }
  .rule--h .rule__tick b { display: none; font-size: 10px; }
  .rule--h .rule__tick:first-of-type b, .rule--h .rule__tick:last-of-type b { display: block; }
  .rule--h .rule__mark {
    top: calc(var(--learning-p) * 100%);
    left: auto;
    right: -1px;
    width: 4px; height: 28px;
    transform: translateY(-50%);
  }
  .rule__end { display: none; }
}
@media (max-width: 639px) {
  .learning__grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 479px) {
  .learning__layout { grid-template-columns: 20px minmax(0, 1fr); column-gap: 14px; }
  #learning-rule { width: 20px; }
  #learning-rule .rule__tick b { display: none; }
}

/* 11. Events (2026-10-18; replaces the School life sheet): five cards, each one link to its page.
   Desktop: two wide cards, then three. Tablets: two columns. Phones: a sideways row that snaps. */
.top-events__head {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: clamp(24px, 3vw, 40px);
  margin-bottom: clamp(40px, 5vw, 72px);
}
.top-events__head h2 { grid-column: 1 / span 10; max-width: 16ch; }
.top-events__head .lead { grid-column: 1 / span 7; max-width: 50ch; }
.ev-grid {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: clamp(36px, 3.5vw, 56px) var(--gutter);
}
.ev { grid-column: span 2; }
.ev--wide { grid-column: span 3; }
.ev__card { display: flex; flex-direction: column; gap: 8px; height: 100%; color: inherit; text-decoration: none; }
.ev__media {
  display: block;
  margin-bottom: 10px;
  padding: 10px;
  background: var(--paper-3);
  border: 1px solid var(--clay);
  transition: border-color var(--t-ui) var(--ease-soft);
}
.ev__media .plate__frame { display: block; }
.ev__media img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  object-position: 50% 40%;
  transition: transform var(--t-hover) var(--ease-soft);
}
.ev--wide .ev__media img { aspect-ratio: 16 / 9; }
/* the Pohela Boishakh frame is a tall view from above: keep the painted floor in the crop */
.ev__card[href*="pohela-boishakh"] img { object-position: 50% 58%; }
.ev__name { font: 400 clamp(24px, 2vw, 34px) / 1.1 var(--font-serif); letter-spacing: -0.005em; transition: color var(--t-ui) var(--ease-soft); }
.ev__text { font-size: 17px; line-height: 1.5; color: var(--ink-2); max-width: 46ch; }
.ev__more {
  align-self: flex-start;
  margin-top: auto;
  padding: 6px 0 4px;
  font: 500 15px / 1.2 var(--font-sans);
  background-image: linear-gradient(var(--gold), var(--gold));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 1px;
  transition: background-size var(--t-micro) var(--ease-soft);
}
.ev__more::after { content: '\2192'; display: inline-block; margin-left: 8px; transition: transform var(--t-ui) var(--ease-out); }
.ev__card:focus-visible { outline-offset: 6px; }
.ev__card:hover .ev__name, .ev__card:focus-visible .ev__name { color: var(--maroon); }
.ev__card:hover .ev__media { border-color: var(--ink-2); }
.ev__card:hover .ev__more { background-size: 100% 2px; }
@media (hover: hover) and (pointer: fine) {
  .ev__card:hover img { transform: scale(1.03); }
  .ev__card:hover .ev__more::after { transform: translateX(4px); }
}
.top-events__foot {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 24px var(--gutter);
  align-items: end;
  margin-top: clamp(40px, 5vw, 72px);
  padding-top: 24px;
  border-top: var(--hairline);
}
.top-events__more { grid-column: 1 / span 8; max-width: 62ch; font-size: 18px; line-height: 1.55; }
.top-events__link { grid-column: 10 / -1; justify-self: end; }
@media (max-width: 1023px) {
  .ev-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ev, .ev--wide { grid-column: auto; }
  .ev:first-child { grid-column: 1 / -1; }
  .top-events__head h2, .top-events__head .lead, .top-events__more { grid-column: 1 / -1; }
  .top-events__link { grid-column: 1 / -1; justify-self: start; }
}
@media (max-width: 639px) {
  /* phones: one row that scrolls sideways and snaps, the next card peeking in */
  .ev-grid {
    display: flex;
    gap: 16px;
    margin-inline: calc(-1 * var(--margin));
    padding: 0 var(--margin) 12px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--margin);
    overscroll-behavior-x: contain;
  }
  .ev, .ev:first-child { flex: 0 0 82%; scroll-snap-align: start; }
  .ev--wide .ev__media img { aspect-ratio: 3 / 2; }
}

/* Lightbox (shared: the inner pages' gallery lightbox builds on it, css/pages.css) */
.dialog {
  padding: 12px;
  border: 1px solid var(--clay);
  background: var(--paper-3);
  color: var(--ink);
  max-width: min(90vw, 1800px);
  max-height: 85vh;
  margin: auto;
}
.dialog::backdrop { background: rgba(20, 17, 16, 0.78); }
.dialog__figure { display: flex; flex-direction: column; gap: 10px; }
.dialog__img {
  width: auto; height: auto;
  max-width: calc(90vw - 26px);
  max-height: calc(85vh - 90px);
  object-fit: contain;
  margin-inline: auto;
}
.dialog__cap { margin: 0; padding-right: 56px; }
.dialog__close {
  position: absolute;
  top: 12px; right: 12px;
  min-width: 44px; min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--clay);
  border-radius: 999px;
  background: var(--paper-3);
  font: 500 13px / 1 var(--font-sans);
  letter-spacing: 0.04em;
  cursor: pointer;
}
.dialog__close:hover { border-color: var(--ink-2); }

/* 12. (The Ledger was removed on 2026-10-18.) ---------------------------------------------- */

/* 13. In their own words --------------------------------------------------- */
.quote {
  position: relative;
  padding-left: clamp(36px, 5vw, 80px);
}
.quote__mark {
  position: absolute;
  left: 0; top: -0.08em;
  font: 300 clamp(60px, 7.5vw, 160px) / 1 var(--font-serif);
  color: var(--maroon);
  transform-origin: top;
}
.quote__line { font-weight: 400; max-width: 26ch; }
@media (min-width: 1715px) { .quote__line { font-weight: 300; } }
.quote__line--2 { margin-top: clamp(24px, 3vw, 40px); max-width: 58ch; font-weight: 400; }
.quote__cite { margin-top: clamp(24px, 3vw, 40px); padding-left: clamp(36px, 5vw, 80px); }
.quote__cite cite { font-style: normal; }
/* 2026-10-26: laid out like Achievement (above): .achievement__layout, .frame, .frame__mat and .achievement__text
   are shared; only what the words need is here. Since 2026-10-26 the plate is a carousel of the school's 3 playground
   photographs (pre-cropped to 3:2), sharing the Achievement carousel rules above. */
/* 2026-10-26 (founder): mirrored from 1024 px: the words on the left, the photographs on the right (phones: photo first) */
@media (min-width: 1024px) {
  .words .ach-carousel { grid-column: 6 / -1; grid-row: 1; }
  .words .achievement__text { grid-column: 1 / span 5; grid-row: 1; padding-left: 0; padding-right: clamp(0px, 2vw, 32px); }
}
.words .ach-plate { aspect-ratio: 3 / 2; background: var(--paper-2); }
.words .ach-plate picture { display: block; width: 100%; height: 100%; }
.words .ach-plate img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 42%; }
.words .quote { padding-left: clamp(28px, 3vw, 48px); }
.words .quote__mark { font-size: clamp(48px, 4.5vw, 96px); }
.words .quote__line:not(.quote__line--2) { max-width: 22ch; }
.words .quote__line--2 { margin-top: clamp(16px, 2vw, 24px); max-width: 52ch; }
.words__vision { margin-top: clamp(24px, 3vw, 36px); padding: clamp(16px, 2vw, 24px) 0 0 clamp(28px, 3vw, 48px); border-top: var(--hairline); }
.words__label { margin: 0 0 10px; color: var(--gold); }
.words__vq { margin: 0; }
.words__vq .achievement__body { margin-top: 0; }
.words .quote__cite { margin-top: clamp(20px, 2.4vw, 28px); padding-left: clamp(28px, 3vw, 48px); }

/* 14. For current parents -------------------------------------------------- */
.parents h2 { max-width: 14ch; margin-bottom: clamp(40px, 5vw, 72px); }
/* Phones: one column. From 1024: staying in touch and quick links side by side (the notices column moved to its own
   Sheet 01 on 2026-10-22, section 14b) */
.parents__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(32px, 4vw, 64px);
}
@media (min-width: 1024px) {
  .parents__grid {
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: clamp(56px, 5vw, 88px) var(--gutter);
  }
  #keep-in-touch { grid-column: 1 / span 6; }
  #parent-links { grid-column: 8 / -1; }
}
.parents__h {
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--ink);
}
.notices, .quick { list-style: none; }
.notices li {
  padding: 16px 0;
  border-bottom: var(--hairline);
  font-size: 17px;
  line-height: 1.5;
}
.quick li { padding: 10px 0; border-bottom: var(--hairline); font: 400 16px / 1.4 var(--font-sans); }
.parents__links {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 24px;
  margin-top: 20px;
  font-family: var(--font-sans);
  font-size: 15px;
}

/* 14b. Notices: the notice board (nb-), 2026-10-22 ----------------------------------------------
   One card design for the home's Sheet 01 and the /notices/ page (build/pages/notices.html adds only its
   own nbp- layout in build/additions/notices.css). Spec: redesign-2026-10-22-notices/spec.md section 4.
   Colour never carries meaning alone: every status and topic is also a word. No text in --gold or --amber
   on paper. Card reading order = DOM order: tile and chips, title, For / What to do / When, one action, source. */
.nb-sheet { background: var(--paper-2); }
.nb-sheet h2 { max-width: 16ch; }
.nb-sheet h2 em { white-space: nowrap; }   /* "school." stays one piece: the full stop never sits on a line alone */
.nb-lead { margin-top: clamp(20px, 2.4vw, 32px); max-width: 48ch; }
.nb-count {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 16px;
  font: 500 16px / 1.4 var(--font-sans);
  color: var(--ink);
}
.nb-count::before {   /* a small maroon square: decoration beside the words */
  content: '';
  flex: none;
  width: 8px; height: 8px;
  background: var(--maroon);
}
.nb-board {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 24px;
  margin-top: clamp(32px, 4vw, 56px);
}
.nb-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
  min-width: 0;
}
@media (min-width: 720px) {
  .nb-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gutter); }
  .nb-card--feature { grid-column: 1 / -1; }
}
@media (min-width: 1024px) {
  .nb-board { grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--gutter); align-items: start; }
  .nb-board > .nb-grid { grid-column: 1 / span 8; }
  .nb-board > .nb-ask { grid-column: 9 / -1; position: sticky; top: calc(var(--nav-h, 72px) + 24px); }
}

/* the card */
.nb-card {
  --nb-edge: var(--ink-2);
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
  padding: clamp(20px, 2.2vw, 32px);
  border-top: 4px solid var(--nb-edge);
  background: var(--paper-3);
  color: var(--ink);
  box-shadow: 0 1px 0 rgba(28, 23, 21, 0.06);
  transition: translate var(--t-hover) var(--ease-soft), box-shadow var(--t-hover) var(--ease-soft);
}
.nb-topic--admissions { --nb-edge: var(--maroon); }
.nb-topic--exams { --nb-edge: var(--gold-soft); }
.nb-topic--rules { --nb-edge: var(--ink-2); }
@media (hover: hover) and (pointer: fine) {
  /* translate, not transform: the reveal leaves an inline transform on the card */
  .nb-card:hover { translate: 0 -2px; box-shadow: 0 10px 28px -14px rgba(28, 23, 21, 0.28); }
}
.nb-card__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 16px;
}
.nb-tile {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  min-width: 64px;
  padding: 10px 12px;
  border: 1px solid var(--clay);
  background: var(--paper);
  text-align: left;
}
.nb-tile__big {
  font: 300 26px / 1 var(--font-serif);
  font-variant-numeric: lining-nums;
  color: var(--ink);
  white-space: nowrap;
}
.nb-tile__small {
  font: 500 11.5px / 1.2 var(--font-sans);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
}
@media (min-width: 720px) {
  .nb-tile__big { font-size: 40px; }
}
.nb-card__chips { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.nb-status, .nb-topic {
  display: inline-flex;
  align-items: center;
  min-height: 28px;
  padding: 4px 12px;
  border: 1px solid transparent;
  border-radius: 999px;
  font: 600 12.5px / 1.2 var(--font-sans);
  letter-spacing: 0.04em;
}
.nb-status--current { background: var(--maroon); color: var(--paper); }
.nb-status--always { border-color: var(--ink-2); color: var(--ink); }
.nb-status--ended { border-color: var(--clay); background: var(--paper-2); color: var(--ink-2); }
.nb-status--new { background: var(--amber); color: var(--ink); }
.nb-topic { gap: 8px; padding-left: 0; padding-right: 0; color: var(--ink-2); }
.nb-topic::before {   /* the topic's colour, as decoration beside the word */
  content: '';
  flex: none;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--nb-edge);
}
.nb-card__title {
  font: 400 clamp(22px, 2vw, 30px) / 1.15 var(--font-serif);
  color: var(--ink);
  text-wrap: balance;
}
.nb-card--feature .nb-card__title { font-size: clamp(26px, 2.6vw, 40px); max-width: 24ch; }
.nb-card__facts { display: grid; gap: 0; }
.nb-fact {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 4px;
  padding: 12px 0;
  border-top: var(--hairline);
}
.nb-fact:last-child { border-bottom: var(--hairline); }
.nb-fact dd {
  font: 400 17px / 1.5 var(--font-sans);
  color: var(--ink);
  overflow-wrap: anywhere;
}
@media (max-width: 479px) {
  .nb-fact dd { font-size: 18px; }
}
@media (min-width: 1024px) {
  /* the wide card: the label beside its answer */
  .nb-card--feature .nb-fact { grid-template-columns: 9rem minmax(0, 1fr); gap: 24px; align-items: baseline; }
}
.nb-card__actions { display: flex; flex-wrap: wrap; gap: 12px 24px; margin-top: auto; padding-top: 4px; }
.nb-card__source { margin-top: -4px; }
@media (max-width: 719px) {
  .nb-card__actions .btn { width: 100%; min-height: 48px; white-space: normal; text-align: center; }
}
/* an ended notice is clearly quieter than a current one: a neutral clay rule instead of the topic colour,
   a smaller title in ink-2, a paper-2 tile that reads "Ended". The word "Ended" (chip and tile) carries the
   meaning, never the colour. ink-2 on paper-3 is about 9.5:1, so every line stays well above AA. */
.nb-card.nb-card--ended { --nb-edge: var(--clay); box-shadow: none; }
.nb-card--ended .nb-card__title { font-size: clamp(20px, 1.6vw, 24px); color: var(--ink-2); }
.nb-card--ended .nb-fact dd { color: var(--ink-2); }
.nb-card--ended .nb-tile { border-color: var(--clay); background: var(--paper-2); }
.nb-card--ended .nb-tile__big { color: var(--ink-2); font-size: 26px; }

/* the honest empty slot: never a made-up notice */
.nb-empty {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 10px;
  min-width: 0;
  padding: clamp(20px, 2.2vw, 32px);
  border: 1px dashed var(--ink-2);
  background: transparent;
}
.nb-empty__text { font: 400 17px / 1.5 var(--font-sans); color: var(--ink-2); max-width: 36ch; }
.nb-none { grid-column: 1 / -1; padding: 20px 0; font: 400 17px / 1.5 var(--font-sans); color: var(--ink-2); }
/* /notices/ with a topic chosen that has no current notice: the line sits in a dashed slot, like the empty slot */
.nb-none--topic { padding: clamp(20px, 2.2vw, 32px); border: 1px dashed var(--ink-2); color: var(--ink); }

/* Ask the school */
.nb-ask {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
  padding: 24px;
  border-top: 1px solid var(--ink);
  background: var(--paper-3);
  font: 400 16px / 1.5 var(--font-sans);
  color: var(--ink);
}
.nb-ask__title { font: 400 clamp(22px, 1.8vw, 28px) / 1.15 var(--font-serif); }
.nb-ask .phones { margin-top: 0; }
.nb-ask .phones__row { flex-wrap: wrap; align-items: center; gap: 0 12px; padding: 0; max-width: none; }
.nb-ask .phones a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0;
  background-position: 0 calc(50% + 0.8em);
}
.nb-ask .link--ext { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 0 6px; min-height: 44px; }

.nb-more {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 24px;
  margin-top: clamp(32px, 4vw, 48px);
}
.nb-more__note { font: 400 15px / 1.45 var(--font-sans); color: var(--ink-2); }
@media (max-width: 719px) {
  .nb-more .btn { width: 100%; }
}

/* The hero's notice chip: solid paper, so its contrast never depends on the film. In the flow under the
   buttons; never moves, never pulses. */
.hero__notice { margin-top: clamp(16px, 1.6vw, 24px); }
.nb-hero {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  max-width: min(100%, 40rem);
  min-height: 44px;
  padding: 8px 16px 8px 8px;
  border-radius: 999px;
  background: var(--paper-3);
  color: var(--ink);
  font: 500 15px / 1.3 var(--font-sans);
  text-decoration: none;
  transition: background-color var(--t-micro) var(--ease-soft);
}
.nb-hero:hover { background: var(--paper); }
.nb-hero:hover .nb-hero__text { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--maroon); }
.hero--film .nb-hero:focus-visible, .nb-hero:focus-visible { outline: 2px solid var(--paper); outline-offset: 3px; }
.nb-hero__tag {
  flex: none;
  padding: 6px 10px;
  border-radius: 999px;
  background: var(--maroon);
  color: var(--paper);
  font: 600 11.5px / 1 var(--font-sans);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.nb-hero__text { min-width: 0; }
.nb-hero__go { flex: none; color: var(--maroon); font-size: 18px; line-height: 1; }
/* phones: the tag sits in the line of text (not a flex item), so the notice keeps to two lines at 360 px */
@media (max-width: 767px) {
  .nb-hero { display: block; padding: 10px 14px; border-radius: 20px; font-size: 14.5px; line-height: 1.4; }
  .nb-hero__tag { display: inline-block; margin-right: 8px; padding: 4px 8px; vertical-align: 1px; }
  .nb-hero__go { margin-left: 6px; font-size: 16px; }
}
/* 375–767 px: the round Pause button sits on the bottom row of the copy; keep 56 px clear for it */
@media (min-width: 375px) and (max-width: 767px) {
  .hero--film .hero__notice { padding-right: 56px; }
}

/* The inner header's "Notices 2" pill (build/shell.py render_notices_pill). Under 720 px the Menu carries
   the count ("Notices (2 current)"). */
.nb-pill {
  display: none;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 8px 0 16px;
  border: 1px solid currentColor;
  border-radius: 999px;
  color: inherit;
  font: 500 14px / 1 var(--font-sans);
  letter-spacing: 0.02em;
  text-decoration: none;
  white-space: nowrap;
}
@media (min-width: 720px) {
  .nb-pill { display: inline-flex; }
}
.nb-pill__n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  height: 28px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--maroon);
  color: var(--paper);
  font: 600 13px / 1 var(--font-sans);
  font-variant-numeric: tabular-nums;
}
.nb-pill:hover { text-decoration: underline; text-underline-offset: 4px; }
.nb-pill[aria-current="page"] { box-shadow: inset 0 0 0 1px currentColor; }
html.menu-open .nav__right .nb-pill { opacity: 0; pointer-events: none; transition: opacity var(--t-ui); }

/* still, reduced motion, forced colours */
@media (prefers-reduced-motion: reduce) {
  .nb-card, .nb-hero { transition: none; }
  .nb-card:hover { translate: none; }
}
html[data-tier="still"] .nb-card, html[data-motion="reduced"] .nb-card { transition: none; }
html[data-tier="still"] .nb-card:hover, html[data-motion="reduced"] .nb-card:hover { translate: none; }
@media (forced-colors: active) {
  .nb-status, .nb-topic, .nb-tile, .nb-hero, .nb-hero__tag, .nb-pill__n { border: 1px solid CanvasText; }
  .nb-card { border: 1px solid CanvasText; border-top-width: 4px; }
  .nb-topic::before, .nb-count::before { background: CanvasText; }
}

/* 15. Admissions ----------------------------------------------------------- */
.admissions h2 { max-width: 14ch; }
.admissions__lead { margin-top: clamp(24px, 3vw, 40px); max-width: 40ch; }
.steps {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: var(--gutter);
  margin-top: clamp(48px, 6vw, 96px);
}
.step { position: relative; padding-top: 24px; --drawn: 1; }
.step::before {
  content: '';
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 1px;
  background: var(--ink);
  transform-origin: left center;
  transform: scaleX(var(--drawn));
}
.step__n {
  display: block;
  margin-bottom: 16px;
  color: var(--gold);
  font-weight: 300;
  font-variant-numeric: tabular-nums lining-nums;
}
.step h3 { margin-bottom: 10px; }
.step p { font-size: 17px; line-height: 1.5; max-width: 30ch; }
.admissions__foot {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(32px, 4vw, 64px);
  margin-top: clamp(48px, 6vw, 96px);
  padding-top: 32px;
  border-top: var(--hairline);
}
.docs {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  margin-top: 12px;
  font-size: 17px;
}
.docs li + li::before { content: '\00B7'; margin: 0 10px; color: var(--gold); }
.phones {
  margin-top: 12px;
  font-family: var(--font-sans);
  font-variant-numeric: tabular-nums lining-nums;
  list-style: none;
}
.phones__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 10px 0;
  border-bottom: var(--hairline);
  max-width: 440px;
}
.phones__who { color: var(--ink-2); font-size: 14px; }
.phones a {
  color: var(--ink);
  font-size: 16px;
  text-decoration: none;
  background-image: linear-gradient(var(--gold), var(--gold));
  background-repeat: no-repeat;
  background-position: 0 calc(100% - 3px);
  background-size: 100% 1px;
  padding: 3px 0 4px;
}
.phones a:hover { background-size: 100% 2px; }
.admissions__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 28px;
  margin-top: clamp(40px, 5vw, 64px);
}
@media (max-width: 1023px) {
  .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 40px var(--gutter); }
  .step p { max-width: 40ch; }
}
@media (max-width: 639px) {
  .steps { grid-template-columns: minmax(0, 1fr); }
  .admissions__foot { grid-template-columns: minmax(0, 1fr); }
}

/* 15b. Find the school (map, 2026-10-22) ------------------------------------- */
.findus {
  display: grid;
  grid-template-columns: minmax(300px, 5fr) minmax(0, 7fr);
  margin-top: clamp(56px, 7vw, 112px);
  border-radius: 6px;
  overflow: hidden;
  background: var(--night);
  color: var(--paper);
  box-shadow: 0 30px 60px -30px rgba(28, 23, 21, 0.45);
}
.findus__panel {
  display: flex;
  flex-direction: column;
  gap: 22px;
  padding: clamp(32px, 4vw, 64px);
  border-right: 1px solid var(--night-line);
}
.findus .label { color: var(--gold-text); }
.findus__title {
  font: var(--wght-display) clamp(30px, 3vw, 46px) / 1.08 var(--font-serif);
  margin: 0;
}
.findus__title em { color: var(--gold-text); }
.findus__address {
  display: flex;
  flex-direction: column;
  font-style: normal;
  font-size: 18px;
  line-height: 1.5;
  padding-left: 16px;
  border-left: 2px solid var(--maroon);
}
.findus__facts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin: 0;
  padding-top: 20px;
  border-top: 1px solid var(--night-line);
}
.findus__facts dt { margin-bottom: 6px; }
.findus__facts dd { margin: 0; color: var(--bone-dim); }
.findus__facts a { color: var(--paper); text-decoration: none; border-bottom: 1px solid var(--gold); }
.findus__facts a:hover { color: var(--gold-text); }
.findus__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 24px;
  margin-top: auto;
}
.btn--gold {
  background: var(--amber);
  color: var(--ink);
  transition: background var(--t-hover) var(--ease-soft);
}
.btn--gold:hover { background: var(--gold-text); }
.findus__open {
  color: var(--paper);
  text-decoration: none;
  border-bottom: 1px solid var(--gold);
  padding-bottom: 2px;
  font-size: 15px;
}
.findus__open:hover { color: var(--gold-text); }
.findus__map {
  position: relative;
  min-height: 460px;
  background: var(--clay);
}
.findus__frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  filter: grayscale(0.55) sepia(0.18) contrast(1.02);
  transition: filter var(--t-flip) var(--ease-soft);
}
.findus__map:hover .findus__frame,
.findus__map:focus-within .findus__frame { filter: none; }
.findus__tag {
  position: absolute;
  top: 18px;
  left: 18px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 10px 16px 10px 12px;
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink);
  font: 500 14px / 1 var(--font-sans);
  box-shadow: 0 8px 24px -8px rgba(28, 23, 21, 0.4);
  pointer-events: none;
}
.findus__dot {
  position: relative;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--maroon);
}
.findus__dot::after {
  content: '';
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  border: 2px solid var(--maroon);
  opacity: 0.5;
  animation: findus-ping 2.4s var(--ease-out) infinite;
}
@keyframes findus-ping {
  from { transform: scale(0.6); opacity: 0.6; }
  to { transform: scale(1.8); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .findus__dot::after { animation: none; }
  .findus__frame { transition: none; }
}
@media (max-width: 1023px) {
  .findus { grid-template-columns: minmax(0, 1fr); }
  .findus__panel { border-right: 0; border-bottom: 1px solid var(--night-line); }
  .findus__map { min-height: 340px; order: -1; }
}

/* 16. (The "Where next" sheet was folded into the footer in the polish pass.) ------------------ */

/* 17. Footer --------------------------------------------------------------- */
.foot {
  position: relative;
  background: var(--night);
  color: var(--paper);
  border-top: 4px solid var(--maroon);
  padding: clamp(64px, 8vw, 120px) 0 calc(40px + env(safe-area-inset-bottom, 0px));
}
.foot__top {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 32px;
  padding-bottom: 40px;
  border-bottom: 1px solid var(--night-line);
}
.foot__brand { display: flex; align-items: center; gap: 20px; }
.foot__crest { width: 72px; height: auto; flex: none; }
.foot__name { font: 400 24px / 1 var(--font-serif); }
.foot__address {
  font-style: normal;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  font: 400 16px / 1.5 var(--font-sans);
  color: var(--bone-dim);
}
.foot__address .link { color: var(--paper); }
.foot__grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr 1fr 1fr;
  gap: 48px clamp(24px, 3vw, 48px);
  padding: 48px 0;
  border-bottom: 1px solid var(--night-line);
}
@media (max-width: 1199px) {
  .foot__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .foot__col--phones { grid-column: 1 / -1; }
}
.foot__h a { color: inherit; text-decoration: none; }
.foot__h a:hover, .foot__h a:focus-visible { text-decoration: underline; text-decoration-color: var(--gold-text); text-underline-offset: 4px; }
/* current-parent shortcuts under the grid, and the legal row at the very bottom */
.foot__util { padding: 32px 0; border-bottom: 1px solid var(--night-line); }
.foot__util .foot__h { margin-bottom: 12px; }
/* the row gaps (22 and 23 px) are what keep a wrapped row of links 44 px apart, so each link's hit area has its own space */
.foot__util ul { list-style: none; display: flex; flex-wrap: wrap; gap: 22px 28px; font: 400 15px / 1.5 var(--font-sans); }
.foot__util li { display: flex; align-items: center; }
.foot__legal { display: flex; flex-wrap: wrap; align-items: center; gap: 23px 0; font: 400 14px / 1.5 var(--font-sans); color: var(--bone-dim); }
.foot__legal .foot__dot { margin: 0 12px; }
.foot__display { display: flex; align-items: center; }
.foot__display .toggle { font-size: 14px; }
.phones__nums { display: inline-flex; flex-direction: column; align-items: flex-end; gap: 19px; }   /* two stacked numbers, 44 px apart */
.phones__nums .foot__dot { display: none; }
.phones__nums a { white-space: nowrap; }
.foot__h { margin-bottom: 16px; }
.foot__phones {
  list-style: none;
  font-family: var(--font-sans);
  font-variant-numeric: tabular-nums lining-nums;
  font-size: 15px;
}
.foot__phones li {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 6px 16px;
  padding: 10px 0;
  border-bottom: 1px solid var(--night-line);
}
.foot__phones .phones__who { color: var(--bone-dim); font-size: 14px; }
.foot__phones a { color: var(--paper); text-decoration: none; background-image: linear-gradient(var(--gold-text), var(--gold-text)); background-repeat: no-repeat; background-position: 0 calc(100% - 3px); background-size: 100% 1px; padding: 3px 0 4px; }
.foot__phones a:hover { background-size: 100% 2px; }
.foot__dot { color: var(--bone-dim); }
.foot__nums { display: inline-flex; flex-wrap: wrap; justify-content: flex-end; gap: 4px 10px; margin-left: auto; }
.foot__nums a { white-space: nowrap; }
.foot__email { margin-top: 16px; font: 400 15px / 1.5 var(--font-sans); color: var(--bone-dim); }
.foot__email .link { color: var(--paper); }
.foot__links ul {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 19px;
  font-family: var(--font-sans);
  font-size: 16px;
}
.foot__links li { display: flex; align-items: center; }
.toggle {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: 500 15px / 1 var(--font-sans);
  cursor: pointer;
}
.toggle__switch {
  position: relative;
  width: 44px; height: 24px;
  border-radius: 12px;
  border: 1px solid var(--bone-dim);
  transition: border-color var(--t-micro);
}
.toggle__switch::after {
  content: '';
  position: absolute;
  top: 3px; left: 3px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--bone-dim);
  transition: transform var(--t-micro) var(--ease-soft), background var(--t-micro);
}
.toggle[aria-pressed="true"] .toggle__switch { border-color: var(--amber); }
.toggle[aria-pressed="true"] .toggle__switch::after { transform: translateX(20px); background: var(--amber); }
.foot__toggle-note { margin-top: 10px; color: var(--bone-dim); max-width: 36ch; }
.foot__bottom {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 16px 32px;
  padding-top: 32px;
  color: var(--bone-dim);
}
.foot__bottom .caption { color: var(--bone-dim); }
.foot__sample { max-width: 76ch; }
.foot__bottom .link { color: var(--paper); }
@media (max-width: 767px) {
  .foot { padding-bottom: calc(96px + env(safe-area-inset-bottom, 0px)); }
  /* phones: the phone lines take the full width, the four link columns sit two by two */
  .foot__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 36px 20px; }
  .foot__col--phones { grid-column: 1 / -1; }
  .foot__util ul { gap: 22px 20px; }
  .foot__bottom { flex-direction: column; align-items: flex-start; }
  /* the legal links wrap on a phone: no separator dots (one could be left hanging at a line end), a gap instead */
  .foot__legal { gap: 23px 22px; }
  .foot__legal .foot__dot { display: none; }
}
@media (max-width: 419px) {
  .foot__links ul { font-size: 15px; }
}

/* Footer link groups (2026-10-18): each group is a <details class="foot__group">. Under 720 px they are
   accordions (closed in the markup), so the footer is about one screen tall on a phone; the phone lines,
   the email line and the address stay open. From 720 px the script keeps them open (js/main.js,
   js/inner.js); without it, ::details-content shows the lists anyway. */
.foot__sum { display: block; list-style: none; }
.foot__sum::-webkit-details-marker { display: none; }
.foot__sum::marker { content: ''; }
.foot__chev { display: none; }
@media (min-width: 720px) {
  .foot__group::details-content { content-visibility: visible; block-size: auto; }
  .foot__sum { pointer-events: none; cursor: default; }
}
@media (max-width: 719px) {
  .foot { padding: 32px 0 calc(72px + env(safe-area-inset-bottom, 0px)); border-top-width: 3px; }
  .foot__top { align-items: center; gap: 14px 24px; padding-bottom: 20px; }
  .foot__brand { gap: 14px; }
  .foot__crest { width: 44px; }
  .foot__name { font-size: 20px; }
  .foot__address { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0 14px; font-size: 15px; }
  .foot__grid { grid-template-columns: minmax(0, 1fr); gap: 0; padding: 16px 0 0; border-bottom: 0; }
  .foot__col--phones { padding-bottom: 14px; }
  .foot__col--phones .foot__h { margin-bottom: 4px; }
  .foot__phones li { padding: 6px 0; }
  .foot__email { margin-top: 10px; }
  .foot__links, .foot__util { border-top: 1px solid var(--night-line); }
  .foot__util { padding: 0; }
  .foot__sum {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    min-height: 48px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .foot__sum .foot__h { margin: 0; font-size: 13px; }
  .foot__chev { display: block; position: relative; flex: none; width: 14px; height: 14px; color: var(--gold-text); }
  .foot__chev::before, .foot__chev::after {
    content: '';
    position: absolute;
    left: 0; top: 50%;
    width: 14px; height: 1.5px;
    margin-top: -0.75px;
    background: currentColor;
    transition: transform var(--t-ui) var(--ease-out);
  }
  .foot__chev::after { transform: rotate(90deg); }
  .foot__group[open] .foot__chev::after { transform: rotate(0deg); }
  .foot__links ul { gap: 19px; padding: 6px 0 22px; }
  .foot__util ul { padding: 6px 0 22px; }
  .foot__util .foot__h { margin-bottom: 0; }
  .foot__bottom { flex-direction: row; align-items: center; padding-top: 20px; gap: 6px 24px; border-top: 1px solid var(--night-line); }
  .foot__legal { flex-basis: 100%; gap: 23px 20px; }
}

/* Touch targets (WCAG 2.5.8 asks 24 px; this site asks 44): the footer, menu and phone links keep their size and their
   look, and an invisible hit area grows around each of them. The 12 to 16 px gaps between rows mean the areas never overlap
   a neighbour's text. */
.foot a, .menu__util .link, .menu__actions .link, .menu__contact a, .phones a { position: relative; }
.foot a::before, .menu__util .link::before, .menu__actions .link::before, .menu__contact a::before, .phones a::before {
  content: '';
  position: absolute;
  inset: -7px -4px;
}
.foot__legal a::before { inset: -8px -4px; }

/* 18. Sticky actions: the phone bottom bar only (the desktop floating pill was removed in the
   polish pass: five devices for one action on a page that calls itself a quiet record) ---------- */
.actions { display: contents; }
.actions__bar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 60;
  display: none;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  background: var(--paper);
  border-top: 1px solid var(--clay);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  transform: translateY(100%);
  /* while it is off screen it is also out of the tab order and the accessibility tree (a bar that is only moved away
     still takes focus, with the ring somewhere below the screen); visibility flips after the slide, and at once when it opens */
  visibility: hidden;
  transition: transform var(--t-ui) var(--ease-out), visibility 0s linear var(--t-ui);
}
.actions.is-visible .actions__bar { transform: none; visibility: visible; transition: transform var(--t-ui) var(--ease-out), visibility 0s; }
html:not(.js) .actions__bar { display: none; }              /* without JavaScript the bar never slides up, so it is not offered */
.actions__item {
  min-height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-right: 1px solid var(--clay);
  background: none;
  color: var(--ink);
  font: 500 15px / 1 var(--font-sans);
  text-decoration: none;
  cursor: pointer;
}
.actions__item:last-child { border-right: 0; }
.actions__item--primary { background: var(--maroon); color: var(--paper); }
/* the ring is drawn inside each item (the bar clips it at the screen edges), and in paper on the maroon one */
.actions__item:focus-visible { outline-offset: -4px; }
.actions__item--primary:focus-visible { outline-color: var(--paper); }
@media (max-width: 767px) { .actions__bar { display: grid; } }

/* 19. The Sheet (right-side drawer) ---------------------------------------- */
.sheet-drawer {
  position: fixed;
  inset: 0;
  z-index: 85;
  display: grid;
  justify-items: end;
}
.sheet-drawer[hidden] { display: none; }
/* a paper-tinted, softly blurred scrim (the grey one turned the hero into mud) */
.sheet-drawer::before {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(245, 241, 234, 0.6);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity 400ms var(--ease-soft);
}
.sheet-drawer.is-open::before { opacity: 1; }
.sheet__panel {
  position: relative;
  width: min(480px, 100%);
  height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--paper-2);
  border-left: 1px solid var(--maroon);
  padding: 24px clamp(24px, 4vw, 40px) 48px;
  transform: translateX(100%);
  transition: transform 500ms var(--ease-out);
}
.sheet-drawer.is-open .sheet__panel { transform: none; }
.sheet-drawer.is-closing .sheet__panel { transition-duration: 350ms; }
.sheet__close {
  position: sticky;
  top: 0;
  float: right;
  width: 44px; height: 44px;
  border-radius: 50%;
  border: 1px solid var(--clay);
  background: var(--paper-3);
  cursor: pointer;
  display: grid;
  place-items: center;
  z-index: 2;
}
.sheet__close-icon { position: relative; width: 14px; height: 14px; }
.sheet__close-icon::before, .sheet__close-icon::after {
  content: '';
  position: absolute;
  left: 0; top: 6.5px;
  width: 14px; height: 1.5px;
  background: var(--ink);
}
.sheet__close-icon::before { transform: rotate(45deg); }
.sheet__close-icon::after { transform: rotate(-45deg); }
.sheet__title { clear: both; margin: 32px 0 24px; outline: none; max-width: 10ch; }
.sheet__variant { display: none; }
.sheet-drawer[data-variant="visit"] .sheet__variant[data-variant="visit"],
.sheet-drawer[data-variant="enquire"] .sheet__variant[data-variant="enquire"],
.sheet-drawer[data-variant="apply"] .sheet__variant[data-variant="apply"] { display: block; }
.sheet__text { margin-bottom: 20px; font-size: 17px; line-height: 1.5; }
.sheet__text .label { display: inline-block; margin-bottom: 6px; }
.sheet__phones { margin: 0 0 24px; }
.sheet__phones .phones__row { max-width: none; }
.sheet__address { font-size: 16px; line-height: 1.5; color: var(--ink-2); }
.sheet__address .link { color: var(--ink); margin-left: 8px; }
.sheet__steps { padding-left: 22px; margin-bottom: 24px; font-size: 17px; line-height: 1.5; }
.sheet__steps li { margin-bottom: 10px; }
.form { margin-bottom: 24px; }
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 18px; }
.field label { font: 500 13px / 1.2 var(--font-sans); color: var(--ink-2); }
/* underline-only fields in the house style (the default 1 px boxes read as a form, not a sheet) */
.field input, .field select, .field textarea {
  width: 100%;
  min-height: 48px;
  padding: 10px 0;
  border: 0;
  border-bottom: 1px solid var(--ink-2);
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font: 400 17px / 1.4 var(--font-serif);
  transition: border-color var(--t-micro);
}
/* the focus ring is drawn as well as the thicker line: a 1 px ink-2 line turning 2 px maroon is a change of thickness and hue
   only (1.01:1 in luminance); the ring is 8.9:1 against the paper */
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible { outline: 2px solid var(--maroon); outline-offset: 2px; border-bottom: 2px solid var(--maroon); }
.field textarea { resize: vertical; }
.field [aria-invalid="true"] { border-bottom: 2px solid var(--maroon); }
.field__error { font: 400 14px / 1.4 var(--font-sans); color: var(--maroon); }
.field__error:empty { display: none; }
.sheet__status {
  display: none;
  padding: 16px;
  margin-bottom: 24px;
  border: 1px solid var(--maroon);
  background: var(--paper-3);
  font-size: 16px;
  line-height: 1.5;
}
.sheet__variant.is-sent .form { display: none; }
.sheet__variant.is-sent .sheet__status { display: block; }
@media (max-width: 639px) {
  .sheet__panel { width: 100%; border-left: 0; }
}

/* 20. Menu overlay --------------------------------------------------------- */
.menu {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: var(--paper-3);
  clip-path: inset(0 0 100% 0);
}
.menu[hidden] { display: none; }
.menu.is-open { clip-path: inset(0); }
.menu__panel {
  height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: clamp(32px, 4vw, 64px);
  align-content: start;
  width: min(100% - 2 * var(--margin), var(--band-max));
  margin-inline: auto;
  padding: calc(var(--nav-h) + 24px) 0 48px;
}
.menu__list { list-style: none; display: flex; flex-direction: column; }
.menu__list > li { border-bottom: var(--hairline); }
/* the six group rows: sized so that all six and one open group fit a 1366 x 768 screen (the type
   follows the viewport height as well as its width) */
.menu__link {
  --menu-i: clamp(52px, 5vw, 84px);
  display: flex;
  align-items: baseline;
  gap: 0;
  padding: clamp(6px, 1vw, 14px) 0;
  font: 300 clamp(36px, min(5.2vw, 7.4svh), 80px) / 1 var(--font-serif);
  letter-spacing: -0.012em;
  color: var(--ink);
  text-decoration: none;
  transition: color var(--t-micro);
}
.menu__link:hover, .menu__link:focus-visible { color: var(--maroon); }
.menu__link[aria-current] { color: var(--maroon); }
/* the current group is marked by more than colour (maroon on ink is 1.8:1): a short rule follows its name */
.menu__link[aria-current]::after { content: ''; flex: none; align-self: center; width: 28px; height: 1px; margin-left: 16px; background: var(--maroon); }
/* the panel scrolls (overflow-y clips x as well) and the links start at its left edge: the ring is drawn inside them */
.menu__link:focus-visible, .menu__sub a:focus-visible { outline-offset: -3px; }
.menu__i {
  flex: none;
  width: var(--menu-i);
  font: 300 clamp(24px, 1.8vw, 30px) / 1 var(--font-serif);
  color: var(--gold);
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: 0;
}
/* 20b. Menu groups: a disclosure button opens one group's pages as a quiet row of links under its
   heading (the same behaviour on the home, js/sections/menu.js, and on inner pages, js/inner.js) */
.menu__row { display: flex; align-items: center; gap: 12px; }
.menu__row .menu__link { flex: 1 1 auto; min-width: 0; }
.menu__toggle {
  flex: none;
  position: relative;
  width: 44px; height: 44px;
  border: 1px solid var(--clay);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: border-color var(--t-micro), background var(--t-micro);
}
.menu__toggle:hover { border-color: var(--ink-2); }
.menu__toggle[aria-expanded="true"] { border-color: var(--ink); background: var(--paper-2); }
.menu__toggle-icon { position: absolute; inset: 0; }
.menu__toggle-icon::before, .menu__toggle-icon::after {
  content: '';
  position: absolute;
  left: 50%; top: 50%;
  width: 12px; height: 1.5px;
  margin: -0.75px 0 0 -6px;
  background: var(--ink);
  transition: transform var(--t-ui) var(--ease-move);
}
.menu__toggle-icon::after { transform: rotate(90deg); }
.menu__toggle[aria-expanded="true"] .menu__toggle-icon::after { transform: rotate(0deg); }
.menu__sub {
  list-style: none;
  display: none;
  flex-wrap: wrap;
  gap: 0 26px;
  margin: 0 0 14px var(--menu-i, 64px);
  padding: 0;
  font: 400 16px / 1.3 var(--font-sans);
}
.menu__item.is-open > .menu__sub { display: flex; }
html:not(.js) .menu__sub { display: flex; }
.menu__sub li { display: inline-flex; align-items: center; }
@media (max-width: 639px) {
  .menu__item.is-open > .menu__sub, html:not(.js) .menu__sub { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 12px; }
  .menu__sub li { display: block; }
}
.menu__sub a {
  display: inline-block;
  padding: 12px 0;
  color: var(--ink-2);
  text-decoration: none;
  background-image: linear-gradient(var(--gold), var(--gold));
  background-repeat: no-repeat;
  background-position: 0 calc(100% - 10px);
  background-size: 0 1px;
  transition: color var(--t-micro), background-size var(--t-ui) var(--ease-out);
}
.menu__sub a:hover, .menu__sub a:focus-visible { color: var(--ink); background-size: 100% 1px; }
.menu__sub a[aria-current] { color: var(--maroon); background-size: 100% 1px; }
.menu__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; font-family: var(--font-sans); font-size: 15px; }
.menu__link, .menu__sub a { -webkit-tap-highlight-color: transparent; }
.menu__aside { display: flex; flex-direction: column; gap: 28px; }
.menu__preview {
  position: relative;
  aspect-ratio: 16 / 10;
  padding: 12px;
  background: var(--paper-3);
  border: 1px solid var(--clay);
  overflow: hidden;
}
.menu__img {
  position: absolute;
  inset: 12px;
  width: calc(100% - 24px);
  height: calc(100% - 24px);
  object-fit: cover;
  opacity: 0;
  transform: scale(1.04);
  transition: opacity 600ms var(--ease-out), transform 600ms var(--ease-out);
}
.menu__img.is-current { opacity: 1; transform: none; }
.menu__util {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 24px;
  font-family: var(--font-sans);
  font-size: 15px;
}
.menu__contact { font: 400 16px / 1.5 var(--font-sans); color: var(--ink-2); display: flex; flex-direction: column; gap: 12px; }
.menu__contact .phones { margin: 0; }
@media (max-width: 1023px) {
  .menu__panel { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .menu__preview { display: none; }
}
@media (min-width: 1024px) and (max-height: 820px) {
  .menu__aside { gap: 20px; }
  .menu__preview { aspect-ratio: 2 / 1; }
}

/* 21. Cursor, canvas, present mode ----------------------------------------- */
#gl {
  position: fixed;
  inset: 0;
  z-index: 1;
  width: 100%; height: 100%;
  display: none;
  pointer-events: none;
  will-change: transform;
}
html.gl-ready #gl { display: block; }
#gl.is-lost { opacity: 0; }
/* text that sits over a [data-gl] rect stays above the canvas (the fixed, sticky and absolute
   elements already have their own stacking; the rule keeps position: sticky on phones) */
.ascent__under, .ascent__side, .hero__text, .hero__aside { position: relative; z-index: 2; }
.hero__caption, .hero__corner { z-index: 2; }
.ascent__rule { z-index: 2; }

.cursor {
  position: fixed;
  top: 0; left: 0;
  z-index: 100;
  display: none;
  width: 10px; height: 10px;
  margin: -5px 0 0 -5px;
  border-radius: 50%;
  background: #fff;
  mix-blend-mode: difference;
  pointer-events: none;
  will-change: transform;
  place-items: center;
  transition: width var(--t-ui) var(--ease-soft), height var(--t-ui) var(--ease-soft), margin var(--t-ui) var(--ease-soft), background var(--t-ui) var(--ease-soft), opacity var(--t-micro);
}
html.has-cursor .cursor { display: grid; }
.cursor.is-off { opacity: 0; }
.cursor__label {
  display: none;
  font: 500 11.5px / 1 var(--font-sans);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
}
.cursor[data-state="link"] {
  width: 40px; height: 40px;
  margin: -20px 0 0 -20px;
  background: transparent;
  border: 1px solid var(--gold);
  mix-blend-mode: normal;
}
/* over a plate: a maroon ring (the white labelled disc was the stock award-site cursor) */
.cursor[data-state="view"] {
  width: 48px; height: 48px;
  margin: -24px 0 0 -24px;
  background: transparent;
  border: 1px solid var(--maroon);
  mix-blend-mode: normal;
}
.cursor[data-state="view"] .cursor__label { display: none; }
.cursor[data-state="hide"] { width: 4px; height: 4px; margin: -2px 0 0 -2px; }
html.cursor-big .cursor[data-state="link"], html.cursor-big .cursor[data-state=""] {
  width: 96px; height: 96px;
  margin: -48px 0 0 -48px;
  background: transparent;
  border: 1px solid var(--gold);
  mix-blend-mode: normal;
}

/* the overlay is .present-box: html.present is the present-mode flag set by the gate */
.present-box {
  position: fixed;
  inset: 0;
  z-index: 86;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  justify-items: center;
  align-items: center;
  gap: 16px;
  padding: 24px;
  background: rgba(20, 17, 16, 0.92);
}
.present-box[hidden] { display: none; }
.present__phone {
  width: 390px;
  max-width: 100%;
  height: min(844px, 100%);
  border: 10px solid var(--night-2);
  border-radius: 44px;
  overflow: hidden;
  background: var(--paper);
  box-shadow: 0 0 0 1px rgba(245, 241, 234, 0.12);
}
.present__frame { width: 100%; height: 100%; border: 0; display: block; }
.present__help { font: 400 13px / 1.4 var(--font-sans); color: var(--bone-dim); text-align: center; }
.present__close { font: 500 13px / 1 var(--font-sans); color: var(--paper); background: none; border: 1px solid var(--bone-dim); border-radius: 999px; padding: 8px 14px; cursor: pointer; }
.present-box:focus { outline: none; }

/* 22. Tiers, no-JS, reduced motion ----------------------------------------- */
html[data-tier="still"] #gl,
html[data-tier="still"] .cursor,
html[data-tier="still"] .ascent__video,
html[data-tier="still"] .media-pause { display: none !important; }
html[data-tier="still"] .hero__cue-dot { animation: none; top: 22px; }
html[data-tier="still"] .rule--v .rule__tick[data-tick="5"] b { color: var(--maroon); }
html[data-tier="still"] .rule--v .rule__tick[data-tick="5"]::after { background: var(--maroon); }
html[data-tier="still"] .rule__band { display: none; }
html[data-tier="still"] .nav { transition: background-color var(--t-ui), color var(--t-ui); }
html[data-tier="still"] .nav.is-hidden { transform: none; }
/* Still tier: the Ascent is a static stack (no pin), the same layout as with JavaScript off */
html[data-tier="still"] .ascent__pin { height: auto; align-items: start; }
html[data-tier="still"] .ascent__stage { aspect-ratio: auto; max-height: none; }
/* the static stack is taller than a phone screen: it must scroll with the page, not stick */
html[data-tier="still"] .ascent__media, html:not(.js) .ascent__media { position: relative; top: auto; }
html[data-tier="still"] .ascent__pic { position: static; opacity: 1; margin-bottom: 12px; }
html[data-tier="still"] .ascent__pic:last-of-type { margin-bottom: 0; }
html[data-tier="still"] .ascent__chapters { display: block; }
html[data-tier="still"] .chapter { position: static; opacity: 1; visibility: visible; padding: 0 0 40px; pointer-events: auto; }
html[data-tier="still"] .ascent__rule { position: sticky; top: calc(var(--nav-h) + 16px); height: calc(100svh - 160px); align-self: start; }
html[data-tier="still"] .ascent__video, html[data-tier="still"] #ascent-pause { display: none; }
html[data-tier="still"] .rail { display: none; }
/* Still tier: nothing waits to be revealed. The reveal helpers (reveals.js) create no triggers and
   set no inline opacity in this tier; this is the resting state they leave alone. */
html[data-tier="still"] [data-reveal],
html[data-tier="still"] [data-split] .line,
html[data-tier="still"] [data-clip] .plate__frame,
html[data-tier="still"] .plate__cap,
html[data-tier="still"] .step,
html[data-tier="still"] .sheet-rule > span,
html[data-tier="still"] .chapter > p { opacity: 1; transform: none; clip-path: none; visibility: visible; }

html:not(.js) #gl, html:not(.js) .cursor, html:not(.js) #present, html:not(.js) .media-pause { display: none; }
html:not(.js) .nav__mark img { opacity: 1; }
/* the boot watchdog (index.html) drops .js and adds .no-app when the module graph never ran */
html.no-app #preloader, html.no-app #preloader-flip { display: none !important; }
html:not(.js) .hero__cue-dot { animation: none; top: 22px; }
html:not(.js) .ascent__pic { position: static; opacity: 1; margin-bottom: 12px; }
html:not(.js) .ascent__stage { aspect-ratio: auto; }
html:not(.js) .ascent__pin { height: auto; align-items: start; }
html:not(.js) .ascent__video { display: none; }
html:not(.js) .rail { display: none; }
html:not(.js) .chapter { padding-bottom: 40px; }
html:not(.js) [data-split] { visibility: visible; }
/* the film hero: no film without scripts, and none before the visitor presses Play in the still tier
   or on Save-Data (cover.js sets data-started when it loads a file) */
html:not(.js) .hero__video, html:not(.js) .hero__pause { display: none; }
html[data-tier="still"] .hero__video:not([data-started]),
html[data-save="1"] .hero__video:not([data-started]) { display: none; }

@media (prefers-reduced-motion: reduce) {
  .hero__cue-dot, .hero__picture img { animation: none !important; }
  .plate__open img, .stage .plate img, .ev__media img, .subjects__icon::after, .ev__more::after { transition: none; }
}

@media (forced-colors: active) {
  .btn--primary, .actions__item--primary { border: 1px solid ButtonText; }
  .sheet-rule__line, .rule--v::before, .rule--h::before { background: CanvasText; }
}

/* 23. Page transitions (2026-10-18): cross-document View Transitions, no script. The header and the
   phone bar keep their place (each is its own transition group); the page under them fades out and the
   next one rises in, about 400 ms. Browsers without support navigate as before; reduced motion (the OS
   setting, or the site's own switch: html[data-motion] on inner pages, html[data-tier="still"] on the
   home) gets no animation. */
@view-transition { navigation: auto; }
#top.nav { view-transition-name: pp-header; }
.actions__bar { view-transition-name: pp-actions; }
/* the home's first visit in a session runs its own intro (the crest flies into the header): the header
   is not carried over then, so the two never fight. Return visits skip the intro (below). */
html.is-loading:not(.intro-seen) #top.nav { view-transition-name: none; }
::view-transition-old(root) { animation: pp-vt-out 180ms var(--ease-soft) both; }
::view-transition-new(root) { animation: pp-vt-in 380ms var(--ease-out) 70ms both; }
::view-transition-group(pp-header), ::view-transition-group(pp-actions) { animation-duration: 300ms; }
@keyframes pp-vt-out { to { opacity: 0; } }
@keyframes pp-vt-in { from { opacity: 0; transform: translateY(12px); } }
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}
html[data-motion="reduced"]::view-transition-group(*),
html[data-motion="reduced"]::view-transition-old(*),
html[data-motion="reduced"]::view-transition-new(*),
html[data-tier="still"]::view-transition-group(*),
html[data-tier="still"]::view-transition-old(*),
html[data-tier="still"]::view-transition-new(*) { animation: none !important; }
/* A return to the home in the same session (a link, or back/forward when the page is not restored
   from the back-forward cache): the preloader's short mode is plain paper under the header, no crest
   and no Skip, so the transition lands on the header and paper, and the page fades in under it.
   A restore from the cache shows no preloader at all. */
html.intro-seen #preloader { z-index: 65; }
html.intro-seen #preloader .preloader__crest,
html.intro-seen #preloader .preloader__skip,
html.intro-seen #preloader-flip { visibility: hidden; }

/* 2026-11-05 (founder): "Playpen turns 50" header pill, every page (build/shell.py render_p50_pill + site/index.html).
   Gold on maroon/film; the short label under 720 px so it fits beside the centred crest. */
.p50-pill {
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 16px 0 12px;
  border-radius: 999px; border: 1px solid #F1DD9C;
  background: linear-gradient(180deg, #F3D98C 0%, #D9B25C 55%, #B98A2E 100%);
  color: var(--maroon-deep); font: 700 14px / 1 var(--font-sans); letter-spacing: 0.01em;
  text-decoration: none; white-space: nowrap;
  box-shadow: 0 6px 18px -8px rgba(60, 10, 10, 0.55);
  transition: transform var(--t-ui), box-shadow var(--t-ui);
}
.p50-pill:hover { transform: translateY(-1px); box-shadow: 0 10px 22px -8px rgba(60, 10, 10, 0.6); }
.p50-pill:focus-visible { outline: 3px solid var(--gold-text); outline-offset: 3px; }
.p50-pill__icon { width: 18px; height: 18px; flex: none; }
.p50-pill__short { display: none; }
.nav__right .p50-pill + .nb-pill, .nav__right .p50-pill + .magnet-area { margin-left: 4px; }
html.menu-open .nav__right .p50-pill { opacity: 0; pointer-events: none; transition: opacity var(--t-ui); }
@media (max-width: 1099px) { .nav:not(.nav--film) .p50-pill__long { display: none; } .nav:not(.nav--film) .p50-pill__short { display: inline; } }
@media (max-width: 719px) {
  .p50-pill { padding: 0 10px; min-height: 40px; font-size: 12px; gap: 5px; }
  .p50-pill__long { display: none; } .p50-pill__short { display: inline; }
  .p50-pill__icon { width: 15px; height: 15px; }
}
@media (max-width: 389px) { .p50-pill__short { display: none; } .p50-pill { padding: 0 11px; } .p50-pill::after { content: "50"; } }
@media (forced-colors: active) { .p50-pill { border: 1px solid CanvasText; background: Canvas; color: LinkText; } }
@media (prefers-reduced-motion: reduce) { .p50-pill, .p50-pill:hover { transition: none; transform: none; } }
/* phones, inner pages (Book a visit is also on the right): the 50th pill becomes a round cake icon */
@media (max-width: 719px) {
  .nav:not(.nav--film) .nav__right { gap: 6px; }
  .nav:not(.nav--film) .p50-pill { width: 40px; min-height: 40px; height: 40px; padding: 0; justify-content: center; }
  .nav:not(.nav--film) .p50-pill__short, .nav:not(.nav--film) .p50-pill__long { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; display: inline; }
  .nav:not(.nav--film) .p50-pill::after { content: none; }
  .nav:not(.nav--film) .p50-pill__icon { width: 18px; height: 18px; }
}
@media (max-width: 719px) {
  .nav:not(.nav--film) .nav__bar { position: relative; }
  .nav:not(.nav--film) .p50-pill { position: absolute; left: 72px; top: 50%; transform: translateY(-50%); }
  .nav:not(.nav--film) .p50-pill:hover { transform: translateY(-50%); }
}
