/* GENERATED by build/build.py from build/additions/*.css, in file-name order. Do not edit this file: edit your own file in build/additions/ and run the build. */
/* ---- additions/a11y.css ---- */
/* Accessibility button + panel (founder, 2026-11-03).
   An icon-only button, bottom left, in the brand maroon with the light-gold figure. It opens a small panel:
   text size, read aloud, high contrast, readable font, wider spacing, underline links, reading guide, stop animations.
   Choices are kept in localStorage pp:a11y (motion keeps the shared pp:motion key). Script: additions/a11y.js. */

/* ---- the button ---- */
.ppa-btn {
  position: fixed; z-index: 64;
  left: 16px; bottom: calc(16px + var(--pp-actions-h, 0px) + var(--pp-notice-h, 0px));
  width: 52px; height: 52px; padding: 0;
  display: grid; place-items: center;
  border: 1px solid rgba(217, 178, 92, 0.55); border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, var(--maroon) 0%, var(--maroon-deep) 100%);
  color: rgb(241, 221, 109);
  box-shadow: inset 0 0 0 1px rgba(241, 221, 109, 0.18), 0 10px 24px -10px rgba(20, 17, 16, 0.6);
  cursor: pointer;
  transition: transform var(--t-ui) var(--ease-out), box-shadow var(--t-ui) var(--ease-out), border-color var(--t-ui) var(--ease-out);
}
html.pp-noticed .ppa-btn { bottom: calc(28px + var(--pp-actions-h, 0px) + var(--pp-notice-h, 0px)); }
.ppa-btn svg { width: 30px; height: 30px; display: block; }
.ppa-btn:hover { transform: translateY(-2px); border-color: var(--gold-text); box-shadow: inset 0 0 0 1px rgba(241, 221, 109, 0.35), 0 14px 28px -10px rgba(20, 17, 16, 0.7); }
.ppa-btn:focus-visible { outline: 3px solid rgb(241, 221, 109); outline-offset: 3px; }
.ppa-btn[aria-expanded="true"] { border-color: rgb(241, 221, 109); }
.ppa-btn.is-on::after { /* a small gold dot when any setting is on */
  content: ''; position: absolute; top: 3px; right: 3px; width: 10px; height: 10px; border-radius: 50%;
  background: var(--amber); box-shadow: 0 0 0 2px var(--maroon-deep);
}

/* ---- the panel ---- */
.ppa-panel {
  position: fixed; z-index: 65;
  left: 16px; bottom: calc(80px + var(--pp-actions-h, 0px) + var(--pp-notice-h, 0px));
  width: min(340px, calc(100vw - 32px));
  max-height: calc(100vh - 120px - var(--pp-actions-h, 0px)); overflow: auto;
  background: var(--paper-3); color: var(--ink);
  border: 1px solid var(--clay); border-radius: 10px;
  box-shadow: 0 24px 60px -24px rgba(28, 23, 21, 0.55);
  font: 400 15px / 1.45 var(--font-sans);
}
html.pp-noticed .ppa-panel { bottom: calc(92px + var(--pp-actions-h, 0px) + var(--pp-notice-h, 0px)); }
.ppa-panel[hidden] { display: none; }
.ppa-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 16px; background: var(--maroon-deep); color: var(--paper);
  border-radius: 9px 9px 0 0;
}
.ppa-head h2 { margin: 0; font: 500 17px / 1.2 var(--font-sans); color: var(--paper); letter-spacing: 0.01em; }
.ppa-close {
  width: 44px; height: 44px; margin: -8px -10px -8px 0; border: 0; border-radius: 50%;
  background: transparent; color: var(--paper); font-size: 24px; line-height: 1; cursor: pointer;
}
.ppa-close:hover, .ppa-close:focus-visible { background: rgba(245, 241, 234, 0.14); outline: none; }
.ppa-body { padding: 14px 16px 16px; display: grid; gap: 14px; }
.ppa-label { margin: 0 0 6px; font-size: 13px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-2); }

/* text size: three buttons in a row */
.ppa-size { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.ppa-size button {
  min-height: 44px; border: 1px solid var(--clay); border-radius: 6px; background: var(--paper);
  color: var(--ink); font-family: var(--font-serif); cursor: pointer;
}
.ppa-size button:nth-child(1) { font-size: 15px; }
.ppa-size button:nth-child(2) { font-size: 19px; }
.ppa-size button:nth-child(3) { font-size: 23px; }
.ppa-size button[aria-pressed="true"] { background: var(--maroon); border-color: var(--maroon); color: var(--paper); }

/* read aloud */
.ppa-read {
  width: 100%; min-height: 48px; display: flex; align-items: center; justify-content: center; gap: 10px;
  border: 0; border-radius: 6px; background: var(--maroon); color: var(--paper);
  font: 500 15px / 1.2 var(--font-sans); cursor: pointer;
}
.ppa-read:hover { background: var(--maroon-deep); }
.ppa-read svg { width: 20px; height: 20px; flex: none; }
.ppa-read[aria-pressed="true"] { background: var(--ink); }
.ppa-hint { margin: 6px 0 0; font-size: 13px; color: var(--ink-2); }

/* the on/off tiles */
.ppa-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.ppa-tile {
  min-height: 72px; padding: 10px 8px; display: grid; justify-items: center; align-content: center; gap: 6px;
  border: 1px solid var(--clay); border-radius: 8px; background: var(--paper); color: var(--ink);
  font: 500 14px / 1.2 var(--font-sans); text-align: center; cursor: pointer;
}
.ppa-tile svg { width: 24px; height: 24px; color: var(--maroon); }
.ppa-tile:hover { border-color: var(--gold); }
.ppa-tile[aria-pressed="true"] { background: var(--maroon); border-color: var(--maroon); color: var(--paper); }
.ppa-tile[aria-pressed="true"] svg { color: rgb(241, 221, 109); }
.ppa-size button:focus-visible, .ppa-read:focus-visible, .ppa-tile:focus-visible, .ppa-reset:focus-visible {
  outline: 3px solid var(--gold); outline-offset: 2px;
}
.ppa-reset {
  justify-self: start; min-height: 44px; padding: 0 4px; border: 0; background: none;
  color: var(--maroon); font: 500 14px / 1 var(--font-sans); text-decoration: underline; text-underline-offset: 3px; cursor: pointer;
}

/* ---- what the settings do to the page ---- */
html.a11y-size-1 main, html.a11y-size-1 .foot { zoom: 1.15; }
html.a11y-size-2 main, html.a11y-size-2 .foot { zoom: 1.3; }
html.a11y-size-1 main, html.a11y-size-2 main { overflow-x: clip; }   /* the home's pinned scenes measure in unzoomed pixels */

html.a11y-contrast {
  --paper: #FFFFFF; --paper-2: #FFFFFF; --paper-3: #FFFFFF;
  --ink: #000000; --ink-2: #000000; --clay: #000000;
  --gold: #5E4300; --gold-soft: #5E4300; --bone-dim: #FFFFFF;
}
html.a11y-contrast main img, html.a11y-contrast main video { filter: contrast(1.1); }
html.a11y-contrast main :is(p, li, dd, dt, figcaption, small, span) { opacity: 1 !important; }

html.a11y-font { --font-serif: var(--font-sans); }
html.a11y-font main :is(p, li, dd, h1, h2, h3, h4, a, figcaption) { letter-spacing: 0.02em; }

html.a11y-spacing main :is(p, li, dd, figcaption, blockquote) { line-height: 1.95 !important; word-spacing: 0.14em; letter-spacing: 0.02em; }
html.a11y-spacing main p { margin-bottom: 1.1em; }

html.a11y-links a:not(.ppa-btn) { text-decoration: underline !important; text-underline-offset: 3px; text-decoration-thickness: 2px; }
html.a11y-links main a { background: rgba(245, 167, 25, 0.22); }

.ppa-guide {
  position: fixed; z-index: 63; left: 0; right: 0; top: 0; height: 56px;
  pointer-events: none;
  border-top: 2px solid rgb(241, 221, 109); border-bottom: 2px solid rgb(241, 221, 109);
  box-shadow: 0 0 0 100vmax rgba(20, 17, 16, 0.42);
  transform: translateY(-200px);
}
.ppa-guide[hidden] { display: none; }

/* the word being read aloud */
.ppa-reading { background: rgba(245, 167, 25, 0.35); outline: 2px solid var(--amber); outline-offset: 2px; border-radius: 2px; }

@media (max-width: 720px) {
  .ppa-btn { width: 48px; height: 48px; left: 12px; }
  .ppa-btn svg { width: 28px; height: 28px; }
  .ppa-panel { left: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .ppa-btn { transition: none; }
  .ppa-btn:hover { transform: none; }
}
html[data-motion="reduced"] .ppa-btn { transition: none; }
@media print { .ppa-btn, .ppa-panel, .ppa-guide { display: none !important; } }

/* ---- go to top (founder, 2026-11-03): sits above the accessibility button, shows after 1.5 screens of scrolling ---- */
.ppt-btn {
  position: fixed; z-index: 64;
  left: 16px; bottom: calc(80px + var(--pp-actions-h, 0px) + var(--pp-notice-h, 0px));
  width: 52px; height: 52px; padding: 0;
  display: grid; place-items: center;
  border: 1px solid rgba(217, 178, 92, 0.55); border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, var(--maroon) 0%, var(--maroon-deep) 100%);
  color: rgb(241, 221, 109);
  box-shadow: inset 0 0 0 1px rgba(241, 221, 109, 0.18), 0 10px 24px -10px rgba(20, 17, 16, 0.6);
  cursor: pointer;
  opacity: 0; visibility: hidden; transform: translateY(10px);
  transition: opacity var(--t-ui) var(--ease-out), transform var(--t-ui) var(--ease-out), visibility 0s linear var(--t-ui), border-color var(--t-ui) var(--ease-out);
}
html.pp-noticed .ppt-btn { bottom: calc(92px + var(--pp-actions-h, 0px) + var(--pp-notice-h, 0px)); }
.ppt-btn.is-shown { opacity: 1; visibility: visible; transform: none; transition-delay: 0s; }
.ppt-btn.is-shown:hover { transform: translateY(-2px); border-color: var(--gold-text); }
.ppt-btn:focus-visible { outline: 3px solid rgb(241, 221, 109); outline-offset: 3px; }
.ppt-btn svg { width: 24px; height: 24px; display: block; }
/* while the accessibility panel is open, the arrow steps aside */
html.ppa-open .ppt-btn { opacity: 0; visibility: hidden; }
@media (max-width: 720px) {
  .ppt-btn { width: 48px; height: 48px; left: 12px; bottom: calc(72px + var(--pp-actions-h, 0px) + var(--pp-notice-h, 0px)); }
  html.pp-noticed .ppt-btn { bottom: calc(84px + var(--pp-actions-h, 0px) + var(--pp-notice-h, 0px)); }
}
@media (prefers-reduced-motion: reduce) { .ppt-btn { transition: none; transform: none; } }
html[data-motion="reduced"] .ppt-btn { transition: none; transform: none; }
@media print { .ppt-btn { display: none !important; } }

/* ---- additions/about.css ---- */
/* about group (/about/, history, school administration, who looks after each class, campus, child protection, policies,
   careers): extra rules. Prefix: .abt-. Tokens only. Rewritten 2026-10-24 for the pages redesign (group "about"), on the
   home's design language (research/design-language.md): the inner page kit is not built yet, so the pieces it names
   (head, foot, panel, cover, mounted plate, counter, line mask) live here under the group's own prefix. When the
   Foundation ships build/additions/0-kit.css, each .abt- recipe below can be replaced by its pk- twin.
   The two older global fixes (the dagger on a night ground, the caption of a stacked table) are kept at the top. */

/* history, 2026-10-11: the footnote dagger on the dark ground (main.css draws it maroon, which fails on --night) */
.is-night .fn { color: var(--gold-text); }
/* final review 2026-10-25: the card numbers in the night band of History (01/02/03) were ink-2 on near-black (1.89:1); they take the night labels' light muted ink (about 9:1) */
.is-night .chapter-card__n { color: var(--bone-dim); }

/* leadership (also fixes every table--stack), 2026-10-11: under 640 px the stacked table's caption stayed a table-caption
   box and shrink-wrapped. A block caption takes the full width. */
@media (max-width: 639px) {
  .table--stack caption { display: block; width: 100%; }
}

/* ---- the cover: a photographic hero at page scale (/about/, /about/campus/; 2026-10-24) ------------------------------
   The home's film hero, still. The page keeps the breadcrumb and the rule above the photograph on paper (44 px targets,
   measured contrast), then the picture edge to edge, min(78svh, 760px) tall on a desktop and a 4:5 frame on phones (a
   second <source> in the <picture>, so one file is downloaded). The H1 and the standfirst sit bottom-left in paper over
   the home's two-direction ink scrim (the same stops as .hero--film .hero__scrim). Phones keep 96 px clear under the copy
   for the fixed robot launcher and the visit-code toast. */
.abt-cover { position: relative; }
.abt-cover__rule.sheet-rule { margin-bottom: clamp(20px, 2.6vw, 36px); }
.abt-cover__media {
  position: relative;
  height: min(78svh, 760px);
  min-height: 420px;
  overflow: hidden;
  background: var(--ink);
  color: var(--paper);
}
.abt-cover__picture, .abt-cover__picture img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 45%;
}
/* review fixes 2026-10-24: the Campus band is the building band of the facade (r3: no sky but a strip at the right,
   grade v2 only, so it matches the hub's cover), so the frame sits high (the arcade stays under the copy); the hub's
   crop ends on the arcade, so it sits low */
.abt-cover--top .abt-cover__picture img { object-position: 50% 30%; }
.abt-cover--low .abt-cover__picture img { object-position: 50% 62%; }
/* the scrim (review fixes 2026-10-24, WCAG 1.4.3): the dark band now holds 0.55 up to 58 % of the height and fades
   out at 78 %, and the left band is stronger, so the first H1 line sits on ink, not on bright brick; measured 2.1:1
   before on the hub at 1366, the target is 3:1 for large text against the brightest quarter of the backdrop */
.abt-cover__scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to top, rgba(28, 23, 21, 0.88) 0, rgba(28, 23, 21, 0.78) 22%, rgba(28, 23, 21, 0.64) 42%, rgba(28, 23, 21, 0.55) 58%, rgba(28, 23, 21, 0.28) 70%, rgba(28, 23, 21, 0) 80%),
    linear-gradient(to right, rgba(28, 23, 21, 0.46) 0, rgba(28, 23, 21, 0.2) 40%, rgba(28, 23, 21, 0) 64%);
}
/* the one-line caption under a cover: what the photograph is and when (figcaptions are stripped by the build) */
.abt-cover__cap { display: block; margin-top: 10px; text-align: right; }
.abt-cover__copy {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 1;
  padding-bottom: clamp(28px, 4vh, 44px);
}
.abt-cover__title {
  font: 300 clamp(36px, 5.4vw, 104px) / 0.96 var(--font-serif);
  letter-spacing: -0.015em;
  color: var(--paper);
  max-width: 16ch;
  text-wrap: balance;
  text-shadow: 0 1px 2px rgba(28, 23, 21, 0.55), 0 0 24px rgba(28, 23, 21, 0.5);
}
/* the lighter gold the home's film hero uses for its em: --gold-text measured 2.67:1 on the brightest frames (main.css) */
.abt-cover__title em { color: #EBCD88; font-style: italic; font-weight: inherit; }
.abt-cover__lead {
  max-width: 46ch;
  margin-top: clamp(14px, 1.4vw, 22px);
  font: 400 clamp(17px, 1.3vw, 23px) / 1.4 var(--font-serif);
  color: var(--paper);
  text-shadow: 0 1px 2px rgba(28, 23, 21, 0.55), 0 0 18px rgba(28, 23, 21, 0.45);
}
.abt-cover :focus-visible { outline-color: var(--paper); }
@media (max-width: 767px) {
  .abt-cover__media { height: min(92svh, 640px); min-height: 480px; }
  .abt-cover__picture img { object-position: 50% 38%; }
  /* the Campus phone frame (r3) is a people-free 4:5 of the left wing: the whole height shows, the sides are trimmed */
  .abt-cover--top .abt-cover__picture img { object-position: 50% 50%; }
  .abt-cover__copy { padding-bottom: 96px; }
  .abt-cover__title { font-size: clamp(32px, 9vw, 44px); font-weight: 350; }
  .abt-cover__lead { font-size: 16px; max-width: 36ch; }
}
.abt-cover + .page-section { padding-top: clamp(48px, 6vw, 96px); }

/* ---- the mounted hero plate (history, administration, child protection, careers; 2026-10-24) --------------------------
   The photograph that opens a page sits on the home's paper-3 mount inside the band (never a bare bleed), with the
   curtain reveal figure.plate[data-reveal] already gives. 16:9 on a desktop, 4:3 on a phone; --mark is the smaller 3:2
   plate used when the page's first screen is something else (the organisation chart). */
.abt-hero-plate { margin-top: calc(-1 * clamp(8px, 1.6vw, 28px)); }
.abt-hero-plate + .page-section, .abt-hero-side + .page-section { padding-top: clamp(48px, 6vw, 96px); }
.abt-plate img { aspect-ratio: 16 / 9; object-fit: cover; width: 100%; }
.abt-plate--21x9 img { aspect-ratio: 21 / 9; }
.abt-plate--2x1 img { aspect-ratio: 2 / 1; }
.abt-plate--mark { max-width: min(100%, 44rem); }
.abt-plate--mark img { aspect-ratio: 3 / 2; }
/* review fixes 2026-10-24 (r3): where the phone's 4:3 crop should keep the lower part of the frame (the building
   under the sky on History) */
.abt-plate--lawn img { object-position: 50% 62%; }
/* the visible one-line caption under a mounted plate (what and when); the figcaption stays in the source as the record */
.abt-plate__line { margin-top: 10px; }
@media (max-width: 767px) {
  .abt-plate img, .abt-plate--21x9 img, .abt-plate--2x1 img { aspect-ratio: 4 / 3; }
}

/* ---- the side hero (school administration; review r3): the H1 row with the 3:2 plate beside the standfirst, built in
   the body like the covers, so the first screen is not a type hero over a small plate alone at the left. The type
   classes are the shell's (page-hero__title, page-hero__lead, page-hero__rule), so the rise and the sizes match every
   other inner page; the band's padding repeats .page-hero's without its top padding, which the breadcrumb band the
   build prepends already gives. From 1024 px: title and lead in columns 1 to 7, the plate in 8 to 12 across both rows. */
.abt-hero-side { padding-bottom: clamp(8px, 1.6vw, 28px); }
.abt-hero-side__band { display: grid; grid-template-columns: minmax(0, 1fr); column-gap: var(--gutter); row-gap: 0; align-items: end; }
.abt-hero-side__rule.sheet-rule { margin-bottom: clamp(28px, 3.6vw, 52px); }
.abt-hero-side__lead { margin-top: clamp(20px, 2.4vw, 36px); }
.abt-hero-side__plate { margin-top: clamp(28px, 4vw, 56px); }
.abt-hero-side__plate .abt-plate--mark { max-width: none; }
@media (min-width: 1024px) {
  .abt-hero-side__band { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .abt-hero-side__rule { grid-column: 1 / -1; }
  .abt-hero-side__title { grid-column: 1 / span 7; grid-row: 2; align-self: end; }
  .abt-hero-side__lead { grid-column: 1 / span 6; grid-row: 3; align-self: start; padding-bottom: 0.5em; }
  .abt-hero-side__plate { grid-column: 8 / -1; grid-row: 2 / span 2; align-self: end; margin-top: 0; }
}

/* ---- the paper tag on a plate (the pool illustration; review r3): a small label in the caption style, top left on the
   photograph itself, so a parent skimming the plates never takes the render for the school ------------------------ */
.abt-walk__plate .plate__frame { position: relative; }
.abt-plate__tag {
  position: absolute;
  top: 12px; left: 12px;
  z-index: 1;
  padding: 6px 10px 5px;
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--clay);
  font: 500 11.5px / 1.2 var(--font-sans);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  pointer-events: none;
}

/* ---- sheet head and sheet foot (every section of the group; 2026-10-24) ----------------------------------------------
   The home's head grid: the H2 at the display-l size (36 to 96 px) on 10 of 12 columns, one lead paragraph on 7; the
   foot: a hairline, a sentence on 8 columns, an action on the right, the source line under both (so the source moves
   from a comment onto the page). */
.abt-head {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: clamp(20px, 2.6vw, 36px);
  margin-bottom: clamp(36px, 4.6vw, 64px);
}
.abt-head__title {
  grid-column: 1 / span 10;
  font-size: clamp(36px, 4.8vw, 96px);
  line-height: 0.98;
  letter-spacing: -0.012em;
  max-width: 18ch;
}
.abt-head__title + * { margin-top: 0; }
.abt-head__lead { grid-column: 1 / span 7; max-width: 54ch; }
.abt-head--tight { margin-bottom: clamp(24px, 3vw, 44px); }
@media (max-width: 1023px) {
  .abt-head__title, .abt-head__lead { grid-column: 1 / -1; }
}
/* the H2 rises through a mask like the home's split headline (the whole line, no GSAP): clip from the bottom and a
   0.4em rise over 1100 ms. Without JavaScript, with reduced motion and in print the heading is simply there. */
html.js-reveal .abt-head__title[data-reveal] { transition: clip-path var(--t-mask) var(--ease-mask), transform var(--t-mask) var(--ease-mask), opacity var(--t-micro); }
/* a 1 px sliver stays unclipped: Chrome's IntersectionObserver measures the clipped box, and a fully clipped heading
   would never be seen entering the screen, so it would never reveal */
html.js-reveal .abt-head__title[data-reveal]:not(.is-in) { opacity: 1; transform: translateY(0.4em); clip-path: inset(0 0 calc(100% - 2px) 0); }
html.js-reveal .abt-head__title[data-reveal].is-in { clip-path: inset(-0.1em -0.2em -0.25em -0.2em); }
@media (prefers-reduced-motion: reduce) {
  html.js-reveal .abt-head__title[data-reveal] { clip-path: none !important; transform: none !important; transition: none !important; }
}
html[data-motion="reduced"] .abt-head__title[data-reveal] { clip-path: none !important; transform: none !important; transition: none !important; }

.abt-foot {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 18px var(--gutter);
  align-items: end;
  margin-top: clamp(36px, 4.6vw, 64px);
  padding-top: 24px;
  border-top: var(--hairline);
}
.abt-foot__text { grid-column: 1 / span 8; max-width: 62ch; font-size: 18px; line-height: 1.55; }
.abt-foot__action { grid-column: 10 / -1; justify-self: end; font: 400 16px / 1.4 var(--font-sans); }
.abt-foot__source { grid-column: 1 / -1; max-width: 70ch; }
.abt-foot__source + .abt-foot__source { margin-top: -8px; }
@media (max-width: 899px) {
  .abt-foot__text, .abt-foot__action { grid-column: 1 / -1; justify-self: start; }
}
.is-night .abt-foot { border-top-color: var(--night-line); }
.is-night .abt-foot__text { color: var(--paper); }

/* ---- the one coloured sheet of a page (2026-10-24): the home's full --paper-2 ground, not the 50 % mix ---------------- */
.page-section.abt-tint { background: var(--paper-2); }
.abt-tint .abt-panel, .abt-tint .callout { background: var(--paper-3); }

/* ---- panel: the home's results-card recipe as a general card (2026-10-24) ---------------------------------------------
   paper-3, a 1 px clay border and a 3 px coloured top rule (maroon by default, --gold or --ink by modifier). A head on a
   hairline (a label and a serif name), 17 px text, an optional short list. .abt-panels lays them in 2, 3 or 4 columns. */
.abt-panel {
  --abt-edge: var(--maroon);
  position: relative;
  padding: clamp(20px, 2.2vw, 32px);
  background: var(--paper-3);
  border: 1px solid var(--clay);
  border-top: 3px solid var(--abt-edge);
  min-width: 0;
}
.abt-panel--gold { --abt-edge: var(--gold); }
.abt-panel--ink { --abt-edge: var(--ink); }
.abt-panel__label { display: block; margin-bottom: 10px; }
.abt-panel__title { font: 400 clamp(22px, 1.8vw, 30px) / 1.15 var(--font-serif); letter-spacing: -0.005em; text-wrap: balance; overflow-wrap: anywhere; }
.abt-panel__title--l { font-size: clamp(26px, 2.4vw, 40px); }
.abt-panel__text { margin-top: 12px; font-size: 17px; line-height: 1.55; color: var(--ink); max-width: 46ch; }
.abt-panel__text--quiet { color: var(--ink-2); font-size: 16px; }
.abt-panel__text a { color: inherit; }
.abt-panel__more { display: inline-block; margin-top: 16px; font: 500 15px / 1.2 var(--font-sans); padding: 6px 0; }
.abt-panel .checklist { margin-top: 14px; }
.abt-panel .checklist li { font-size: 16.5px; padding: 10px 0 10px 30px; }
.abt-panel .checklist li::before { top: 16px; }
.abt-panel > * + .abt-panel__label { margin-top: 18px; }
.abt-panels { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); }
@media (min-width: 640px) { .abt-panels { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) {
  .abt-panels--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .abt-panels--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  /* a last card alone on its row takes the whole row (child protection: seven measures in three columns) */
  .abt-panels--3 > .abt-panel:last-child:nth-child(3n + 1) { grid-column: 1 / -1; }
  .abt-panels--3 > .abt-panel:last-child:nth-child(3n + 1) .abt-panel__text { max-width: 70ch; }
}
.abt-panels .abt-panel[hidden] { display: none; }

/* ---- fact strip: the numbers in maroon (the home's numerals), two columns on a phone (2026-10-24) ---------------------- */
.abt-facts .abt-fact--num dd { color: var(--maroon); }
.abt-facts .fn { margin-left: 4px; }
@media (max-width: 639px) {
  .abt-facts .fact-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gutter); }
  .abt-facts .fact:nth-last-child(2):nth-child(odd) { border-bottom: 0; }
  .abt-facts .fact dd { font-size: 21px; }
}

/* ---- photo doors: the home's event cards as a hub's children (2026-10-24) ---------------------------------------------
   .ev-grid / .ev__card come from main.css (mounted photograph, label number, serif name, 17 px text, one action, the
   whole card one link). On a phone the home's row snaps sideways; six pages are a list, so here they stack. */
.abt-doors { margin-top: 0; }
.abt-doors .ev__more { color: var(--ink); }
.abt-doors .ev__media img { object-position: 50% 45%; }
/* review fixes 2026-10-24: six doors close as two rows of three (every card spans 2 of the 6 columns, 3:2), so no card
   is left alone on a third row above the finder panel; between 640 and 1023 px main.css would make the first card full
   width (1 + 2 + 2 + 1), so the first card is an ordinary cell there too (2 + 2 + 2) */
.abt-doors .ev, .abt-doors .ev--wide { grid-column: span 2; }
.abt-doors .ev--wide .ev__media img { aspect-ratio: 3 / 2; }
@media (max-width: 1023px) {
  .abt-doors .ev, .abt-doors .ev:first-child, .abt-doors .ev--wide { grid-column: auto; }
}
/* the type door (Policies): the card's frame holds eight rule topics as a small ledger on the home's paper-2 instead of
   a texture photograph; the card's name and text carry the meaning, the tile is decoration (aria-hidden) */
.abt-door-type {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-content: center;
  gap: 0 18px;
  aspect-ratio: 3 / 2;
  padding: clamp(14px, 1.6vw, 24px) clamp(16px, 1.8vw, 28px);
  background: var(--paper-2);
  border-top: 3px solid var(--gold);   /* gold, like every other card rule of the group (r3) */
  overflow: hidden;
}
.abt-door-type__row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  min-width: 0;
  padding: clamp(5px, 0.6vw, 9px) 0;
  border-bottom: var(--hairline);
  font: 400 clamp(14px, 1.1vw, 18px) / 1.25 var(--font-serif);
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.abt-door-type__row::before { content: ''; flex: none; width: 10px; height: 1px; background: var(--gold); transform: translateY(-0.28em); }
.abt-door-type__row:nth-last-child(-n + 2) { border-bottom: 0; }
@media (max-width: 639px) {
  .abt-doors.ev-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 36px; margin-inline: 0; padding: 0; overflow: visible; }
  .abt-doors .ev, .abt-doors .ev:first-child { flex: none; }
  .abt-doors .ev__media img, .abt-doors .ev--wide .ev__media img { aspect-ratio: 16 / 9; }
  .abt-door-type { aspect-ratio: 16 / 9; }
  .abt-door-type__row { font-size: 15px; }
}
.abt-doors + .abt-panel { margin-top: clamp(28px, 3.5vw, 48px); }

/* a number that counts up once (about.js); the final value is in the markup */
.abt-count { font-variant-numeric: tabular-nums lining-nums; }

/* ---- proof: the home's .feats beside a list of evidence pages (2026-10-24) -------------------------------------------- */
.abt-proof { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 4vw, 56px) var(--gutter); align-items: start; }
.abt-proof .feats { margin-top: 0; }
.abt-proof__links .label { margin-bottom: 14px; }
@media (min-width: 900px) {
  .abt-proof { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .abt-proof__feats { grid-column: 1 / span 8; }
  .abt-proof__links { grid-column: 10 / -1; }
}

/* ---- the quotation sheet: the home's .quote on the left, the four goals on the right (2026-10-24) --------------------- */
.abt-belief { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(32px, 4vw, 64px) var(--gutter); align-items: start; }
.abt-belief .quote__line.display-l { font-size: clamp(28px, 3.6vw, 64px); }
@media (min-width: 1024px) {
  .abt-belief { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .abt-belief__quote { grid-column: 1 / span 7; }
  .abt-belief__goals { grid-column: 9 / -1; }
}

/* ---- the venue panel outside the home's results grid (2026-10-24) ---------------------------------------------------- */
.abt-venue.venue { grid-column: auto; max-width: 62rem; }
.abt-venue .venue__text { max-width: 60ch; }
.abt-venue .venue__text + .caption { margin-top: 12px; }

/* ---- history: three eras, each a story chapter with one plate and its dates (2026-10-24; stacked since the review
   fixes of the same day) ----------------------------------------------------------------------------------------------
   The era's plate runs 16:9 across 10 of 12 columns under the era heading, the Campus walk's recipe, and the dated
   entries follow at full width: the plates read at the home's Ascent scale, and an era without a plate (Beginnings, no
   cleared archive frame) leaves no empty column. The timeline stays on paper (not night): the dates are the chapter,
   not a dark ledger. */
.abt-era { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 3.5vw, 48px) var(--gutter); align-items: start; }
.abt-era .timeline { margin-top: 0; }
.abt-era__dates { max-width: 64rem; }
.abt-era__plate { align-self: start; }
.abt-era__plate img { aspect-ratio: 16 / 9; object-fit: cover; }
/* the crest sits on the right third of its frame (r3); the phone's 4:3 cut keeps it */
.abt-era__plate--crest img { object-position: 62% 50%; }
/* r3: the dates come first, then the plate and its line (history.html); the plate keeps a little air above it */
.abt-era__dates + .abt-era__plate { margin-top: clamp(8px, 1.4vw, 20px); }
@media (min-width: 1024px) {
  .abt-era__plate { width: calc(100% * 10 / 12); }
}
@media (max-width: 767px) {
  .abt-era__plate img { aspect-ratio: 4 / 3; }
}
.abt-eras .story-chapter .abt-head { margin-bottom: clamp(24px, 3vw, 40px); }
/* the visible date line under an era plate (the figcaption is stripped by the build) */
.abt-era__line { margin-top: 10px; }

/* history 03 and campus 04: three chapter cards on the night ground keep the dark variant pages.css gives them; the
   quiet status line under them */
.abt-status { margin-top: clamp(24px, 3vw, 40px); max-width: 60ch; }

/* ---- campus: the facilities grid and the walk (2026-10-24) ----------------------------------------------------------- */
.abt-facilities.tag-list { grid-template-columns: repeat(auto-fill, minmax(min(100%, 16rem), 1fr)); gap: 0 var(--gutter); border-top: 1px solid var(--ink); }
.abt-facilities.tag-list li { min-height: 44px; padding: 10px 0; border-bottom: var(--hairline); font-size: 17.5px; }
.abt-facilities a { color: inherit; }
@media (max-width: 639px) {
  .abt-facilities.tag-list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 16px; }
  .abt-facilities.tag-list li { font-size: 16px; }
}
/* the walk: each space is a head, one large plate (10 of 12 columns, always 16:9, 4:3 on a phone) with a visible
   one-line caption, and a short definition list; no plate changes size (review fixes 2026-10-24: the small glassware
   plate and the 3:2 field plate are gone, the three teaching spaces share one chapter and one plate) */
.abt-walk .story-chapter { padding-block: clamp(40px, 5.6vw, 88px); }
.abt-walk__plate img { aspect-ratio: 16 / 9; object-fit: cover; }
.abt-walk__facts { margin-top: clamp(24px, 3vw, 40px); max-width: 60rem; }
.abt-walk__facts .dl dd { font-size: 17.5px; }
.abt-walk__facts .label + .dl { margin-top: 10px; }
.abt-walk__facts .dl + .label { margin-top: 28px; }
.abt-walk__note { margin-top: 10px; }
@media (min-width: 1024px) {
  .abt-walk__plate { width: calc(100% * 10 / 12); }
}
@media (max-width: 767px) {
  .abt-walk__plate img { aspect-ratio: 4 / 3; }
}
.abt-walk .abt-head { margin-bottom: clamp(24px, 3vw, 40px); }
.abt-walk .abt-head__title { font-size: clamp(30px, 3.4vw, 64px); }

/* ---- chapter-nav on a phone (review fixes 2026-10-24; interim, scoped to the group's three story pages until the
   Foundation adopts one rule in pages.css): the scrolling index gets 40 px of end padding, a paper fade at its right
   edge so a cut word never shows, and scroll-snap so a chip settles whole ----------------------------------------- */
@media (max-width: 1023px) {
  :is(.abt-eras, .abt-walk, .abt-rules) .chapter-nav ol {
    padding-right: 40px;
    scroll-snap-type: x proximity;
    scroll-padding-inline: 0 40px;
    -webkit-mask-image: linear-gradient(to right, black calc(100% - 44px), transparent);
    mask-image: linear-gradient(to right, black calc(100% - 44px), transparent);
  }
  :is(.abt-eras, .abt-walk, .abt-rules) .chapter-nav a { scroll-snap-align: start; }
}
/* r3 (X12): under 480 px the index wraps into rows instead of scrolling, so no label is ever cut mid-word; the labels
   were shortened in the sources as well (campus.html) */
@media (max-width: 479px) {
  :is(.abt-eras, .abt-walk, .abt-rules) .chapter-nav ol {
    flex-wrap: wrap;
    gap: 0 20px;
    overflow: visible;
    padding-right: 0;
    scroll-snap-type: none;
    -webkit-mask-image: none;
    mask-image: none;
  }
  :is(.abt-eras, .abt-walk, .abt-rules) .chapter-nav a { padding: 13px 0 12px; }
}

/* ---- the story pages at desktop width (history 01, campus 03; review r3): the 3-column chapter nav left a 25 % gutter
   empty down the whole record and walk. From 1024 px the nav is a sticky index row across the sheet (the phone
   treatment, with room), and the chapters take the full sheet width under it, so the plates (10 of 12 columns) get the
   size the walk promises. Policies keeps the left column: its accordion is narrow by nature. ------------------------ */
@media (min-width: 1024px) {
  :is(.abt-eras, .abt-walk) .story { display: block; }
  :is(.abt-eras, .abt-walk) .chapter-nav {
    position: sticky;
    top: var(--nav-h);
    z-index: 20;
    margin: 0 calc(-1 * var(--margin)) clamp(16px, 2vw, 28px);
    padding: 0 var(--margin);
    background: rgba(245, 241, 234, 0.96);
    border: 0;
    border-bottom: var(--hairline);
  }
  body.inner:has(.nav.is-hidden) :is(.abt-eras, .abt-walk) .chapter-nav { top: 0; }
  :is(.abt-eras, .abt-walk) .chapter-nav ol { flex-direction: row; gap: 32px; overflow-x: auto; border-top: 0; font-size: 14px; }
  :is(.abt-eras, .abt-walk) .chapter-nav a { padding: 17px 0 16px; border-left: 0; border-bottom: 2px solid transparent; font-size: 15px; white-space: nowrap; }
  :is(.abt-eras, .abt-walk) .chapter-nav a:hover, :is(.abt-eras, .abt-walk) .chapter-nav a[aria-current="true"] { border-bottom-color: var(--maroon); }
  :is(.abt-eras, .abt-walk) .story__chapters { grid-column: auto; }
  :is(.abt-eras, .abt-walk) .story-chapter:first-child { padding-top: clamp(24px, 3vw, 40px); }
}

/* ---- the fixed overlays and the first screen (review r3, interim for Foundation X16): while a cover, a hero plate or
   the class finder is still in the launcher's corner, the chat launcher, its tease and the first-visit notice step
   below the viewport (about.js sets html.abt-hero-in from the element's position); they come back as soon as the
   visitor scrolls past it. The chat panel itself is never moved. ------------------------------------------------- */
html.abt-hero-in:not(.ppc-open) :is(.ppc-launch, .ppc-tease, .pp-notice) {
  transform: translateY(calc(100% + 40px));
  visibility: hidden;
  transition: transform 0.35s var(--ease-out), visibility 0s 0.35s;
}
html:not(.abt-hero-in) :is(.ppc-launch, .ppc-tease, .pp-notice) { transition: transform 0.35s var(--ease-out), visibility 0s; }
@media (prefers-reduced-motion: reduce) {
  html.abt-hero-in:not(.ppc-open) :is(.ppc-launch, .ppc-tease, .pp-notice), html:not(.abt-hero-in) :is(.ppc-launch, .ppc-tease, .pp-notice) { transition: none; }
}
html[data-motion="reduced"].abt-hero-in:not(.ppc-open) :is(.ppc-launch, .ppc-tease, .pp-notice) { transition: none; }

/* ---- child protection, the lines of the concern card come from {{phones:all}} (r3): the home's .phones list set at the
   call-sheet size, 44 px targets, both further-queries numbers ------------------------------------------------------- */
.abt-concern .phones { margin-top: 0; border-top: 1px solid var(--ink); }
.abt-concern .phones__row { max-width: none; flex-wrap: wrap; gap: 2px 24px; padding: 14px 0 12px; }
.abt-concern .phones__who { font: 500 12px / 1.3 var(--font-sans); letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-2); }
.abt-concern .phones a { display: inline-block; padding: 6px 0 8px; font: 300 clamp(28px, 3vw, 46px) / 1.1 var(--font-serif); letter-spacing: -0.005em; background-position: 0 calc(100% - 6px); }
.abt-concern .phones__nums { align-items: flex-start; gap: 4px; }
@media (max-width: 479px) { .abt-concern .phones__row { flex-direction: column; align-items: flex-start; } }
@media (min-width: 640px) { .abt-concern .phones__row { padding: 16px 0 14px; } }

/* ---- who looks after each class, 03 the lines (r3): two columns of two from 900 px, so the sheet is not a list down
   its left third --------------------------------------------------------------------------------------------------- */
.abt-lines .phones { margin-top: 0; border-top: 1px solid var(--ink); }
.abt-lines .phones__row { max-width: none; min-height: 52px; }
.abt-lines .phones a { font-size: 18px; }
@media (min-width: 900px) {
  .abt-lines .phones { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gutter); }
}

/* ---- child protection: the concern card (2026-10-24): the maroon-edged panel with the call sheet (admissions.css
   .call-lines) inside it; the numbers are the biggest thing on the screen and 44 px tel: links ---------------------- */
.abt-concern { max-width: none; }
.abt-concern__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(24px, 3vw, 40px) var(--gutter); align-items: start; }
.abt-concern .call-lines { border-top-color: var(--ink); }
.abt-concern .call-line__tel { font-size: clamp(28px, 3vw, 46px); }
.abt-concern__text { font-size: 18px; line-height: 1.55; max-width: 44ch; }
.abt-concern__text + .abt-concern__text { margin-top: 14px; }
.abt-concern__text--quiet { font-size: 16px; color: var(--ink-2); }
@media (min-width: 900px) {
  .abt-concern__grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .abt-concern__lead { grid-column: 1 / span 5; }
  .abt-concern__lines { grid-column: 7 / -1; }
}

/* ---- policies: quick answers (2026-10-24): filter chips over four-column panels; each answer one sentence and a link
   that opens the full rule in the accordion below ------------------------------------------------------------------- */
.abt-quick .chips { margin-bottom: 4px; }
.abt-quick .chips__status { margin: 10px 0 18px; }
.abt-quick .abt-panel__title { font-size: clamp(20px, 1.5vw, 26px); }
.abt-quick .abt-panel__text { font-size: 16.5px; }
/* the forms card beside the last group of rules */
.abt-forms .doc-list a { font-size: clamp(17px, 1.3vw, 20px); }
.abt-forms .doc-list li { padding: 12px 0; }
.abt-forms .doc-list__meta { font-size: 13px; }
/* the current-parents strip: a hairline list in two columns, 44 px rows */
.abt-fastlane { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); border-top: 1px solid var(--ink); max-width: 60rem; }
.abt-fastlane li { display: flex; align-items: center; min-height: 52px; padding: 4px 0; border-bottom: var(--hairline); font: 400 17px / 1.4 var(--font-sans); }
.abt-fastlane a { padding: 12px 0; }
@media (min-width: 640px) { .abt-fastlane { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gutter); } }

/* ---- careers: the home's .steps in four columns, and the one empty-state sentence (2026-10-24) ------------------------ */
.abt-steps .steps { grid-template-columns: repeat(4, minmax(0, 1fr)); margin-top: clamp(28px, 3.5vw, 48px); }
.abt-steps .step p { max-width: 34ch; }
@media (max-width: 1023px) { .abt-steps .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 40px var(--gutter); } }
@media (max-width: 639px) { .abt-steps .steps { grid-template-columns: minmax(0, 1fr); } }
.abt-roles { font-size: 18px; line-height: 1.55; max-width: 62ch; }
/* the panel that holds the school's own words at the home's quote size */
.abt-panel--quote .abt-panel__quote { margin: 0; }
.abt-panel--quote .abt-panel__quote p { margin-top: 10px; font: 400 clamp(24px, 2vw, 34px) / 1.15 var(--font-serif); letter-spacing: -0.005em; text-wrap: balance; }
.abt-panel--quote .abt-panel__quote p::before { content: '\201C'; color: var(--maroon); }
.abt-panel--quote .abt-panel__quote p::after { content: '\201D'; color: var(--maroon); }
.abt-panel--quote cite { display: block; margin-top: 12px; font: 400 14px / 1.45 var(--font-sans); font-style: normal; color: var(--ink-2); }

/* ---- the pager and the small print of a reference page --------------------------------------------------------------- */
.abt-pager-note { margin-top: 18px; }

/* ---- print and high contrast ----------------------------------------------------------------------------------------- */
@media print {
  .abt-cover__media { height: auto; }
  .abt-cover__picture, .abt-cover__picture img { position: static; height: auto; }
  .abt-cover__scrim { display: none; }
  .abt-cover__copy { position: static; color: var(--ink); }
  .abt-cover__title, .abt-cover__lead { color: var(--ink); text-shadow: none; }
  :is(.abt-eras, .abt-walk, .abt-rules) .chapter-nav ol { -webkit-mask-image: none; mask-image: none; }
  .abt-plate__tag { position: static; display: inline-block; margin-bottom: 6px; }
}
@media (forced-colors: active) {
  .abt-panel { border-top-width: 3px; }
  .abt-cover__scrim { display: none; }
}

/* ---- additions/achievements.css ---- */
/* Achievement stories (2026-11-05, founder): story circles, the full-screen viewer, cards and the full story.
   Script: additions/achievements.js. Also copied to site/css/achievements.css for the hand-built home. */

/* ---------- circles ---------- */
.ach-circles { display: flex; gap: clamp(14px, 2.4vw, 26px); list-style: none; margin: 0; padding: 4px 2px 8px; overflow-x: auto; scrollbar-width: none; }
.ach-circles::-webkit-scrollbar { display: none; }
.ach-circles li { flex: none; }
/* 2026-11-05 (founder): reel-size cards (9:16), like Instagram / Facebook reels. Class names kept from the first "circles" version. */
.ach-circle { position: relative; display: block; width: clamp(128px, 11vw, 160px); padding: 0; border: 0; background: none; color: var(--paper); cursor: pointer; text-decoration: none; font: inherit; text-align: left; }
.ach-circle__ring { position: relative; display: block; width: 100%; aspect-ratio: 9 / 16; border-radius: 14px; padding: 3px; overflow: hidden;
  background: linear-gradient(160deg, var(--gold-text), var(--maroon) 55%, var(--gold-soft)); transition: transform var(--t-ui), box-shadow var(--t-ui);
  box-shadow: 0 14px 30px -18px rgba(60, 10, 10, 0.55); }
.ach-circle__ring img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 25%; border-radius: 11px; background: var(--maroon-deep); }
.ach-circle__ring::after { content: ""; position: absolute; inset: 3px; border-radius: 11px; pointer-events: none;
  background: linear-gradient(180deg, rgba(30, 1, 2, 0.35) 0%, transparent 28%, transparent 55%, rgba(30, 1, 2, 0.88) 100%); }
.ach-circle__play { position: absolute; z-index: 2; top: 12px; right: 12px; width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center;
  background: rgba(30, 1, 2, 0.55); border: 1px solid rgba(217, 178, 92, 0.7); color: var(--paper); font-size: 11px; line-height: 1; padding-left: 2px; }
.ach-circle:hover .ach-circle__ring { transform: translateY(-4px); box-shadow: 0 22px 36px -18px rgba(60, 10, 10, 0.6); }
.ach-circle:focus-visible { outline: none; }
.ach-circle:focus-visible .ach-circle__ring { outline: 3px solid var(--gold); outline-offset: 3px; }
.ach-circle__label { position: absolute; z-index: 2; left: 12px; right: 12px; bottom: 12px; font: 600 14px / 1.25 var(--font-sans); color: var(--paper); text-shadow: 0 1px 4px rgba(0, 0, 0, 0.5); }
.ach-circle--all .ach-circle__ring, .ach-circle--soon .ach-circle__ring { background: var(--paper-2); box-shadow: none; }
.ach-circle--all .ach-circle__ring::after, .ach-circle--soon .ach-circle__ring::after { display: none; }
.ach-circle--all .ach-circle__label, .ach-circle--soon .ach-circle__label { color: var(--maroon); text-shadow: none; text-align: center; }
.ach-circle__all { display: grid; place-items: center; width: 100%; height: 100%; border-radius: 11px; border: 1px dashed var(--gold); font-size: 30px; color: var(--maroon); }
@media (max-width: 719px) { .ach-circle { width: 132px; } }

/* the home strip that holds the circles */
.ach-bar-sheet { padding-block: clamp(28px, 4vw, 44px); background: var(--paper); border-bottom: 1px solid var(--paper-2); }
.ach-bar-sheet .band { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: clamp(18px, 3vw, 40px); align-items: start; }
.ach-bar__head { display: grid; gap: 6px; }
.ach-bar__title { margin: 0; font: 400 clamp(22px, 2.4vw, 30px) / 1.1 var(--font-serif); color: var(--maroon); }
.ach-bar__title em { color: var(--gold); }
.ach-bar__link { font: 600 14px / 1.2 var(--font-sans); color: var(--ink-2); }
@media (max-width: 719px) { .ach-bar-sheet .band { grid-template-columns: 1fr; } }
/* two groups under "Our Recent Updates": Achievements and Study Tour */
.ach-groups { display: flex; flex-wrap: wrap; gap: clamp(18px, 3vw, 44px); min-width: 0; }
.ach-group { min-width: 0; display: grid; gap: 10px; }
.ach-group + .ach-group { padding-left: clamp(18px, 3vw, 44px); border-left: 1px solid var(--paper-2); }
.ach-group__title { margin: 0; font: 700 12px / 1 var(--font-sans); letter-spacing: 0.18em; text-transform: uppercase; color: var(--gold); }
.ach-circle--soon { cursor: default; opacity: 0.75; }
@media (max-width: 719px) { .ach-groups { display: grid; } .ach-group + .ach-group { padding-left: 0; border-left: 0; padding-top: 14px; border-top: 1px solid var(--paper-2); } }
.ach-anchor { scroll-margin-top: 120px; }

/* ---------- viewer ---------- */
html.ach-viewer-open { overflow: hidden; }
.ach-viewer { position: fixed; inset: 0; z-index: 9999; display: grid; place-items: center; background: rgba(20, 3, 4, 0.92); backdrop-filter: blur(6px);
  opacity: 0; transition: opacity 250ms; }
.ach-viewer.is-open { opacity: 1; }
.ach-viewer[hidden] { display: none; }
.ach-viewer__card { position: relative; width: min(420px, 100vw); height: min(92vh, 760px); border-radius: 16px; overflow: hidden; background: var(--maroon-deep); color: var(--paper);
  box-shadow: 0 30px 80px -20px rgba(0, 0, 0, 0.8); touch-action: pan-y; user-select: none; }
@media (max-width: 520px) { .ach-viewer__card { width: 100vw; height: 100dvh; border-radius: 0; } }
.ach-viewer__bars { position: absolute; z-index: 4; top: 10px; left: 10px; right: 10px; display: flex; gap: 4px; }
.ach-viewer__bars i { flex: 1; height: 3px; border-radius: 3px; background: rgba(255, 255, 255, 0.3); overflow: hidden; }
.ach-viewer__bars b { display: block; height: 100%; background: var(--paper); transform: scaleX(0); transform-origin: left; }
.ach-viewer__bars i.is-done b { transform: scaleX(1); }
.ach-viewer__head { position: absolute; z-index: 5; top: 22px; left: 12px; right: 8px; display: flex; align-items: center; gap: 6px; }
.ach-viewer__who { flex: 1; display: flex; flex-direction: column; font: 13px / 1.25 var(--font-sans); text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6); }
.ach-viewer__who b { font-weight: 700; font-size: 14px; }
.ach-viewer__who span { opacity: 0.8; }
.ach-viewer__btn { width: 40px; height: 40px; border-radius: 50%; border: 0; background: rgba(0, 0, 0, 0.3); color: var(--paper); font-size: 16px; line-height: 1; cursor: pointer; }
.ach-viewer__close { font-size: 26px; }
.ach-viewer__btn:focus-visible, .ach-viewer__arrow:focus-visible, .ach-viewer__tap:focus-visible { outline: 3px solid var(--gold-text); outline-offset: 2px; }
.ach-viewer__stage { position: absolute; inset: 0; }
.ach-viewer__card.is-text .ach-viewer__stage { z-index: 4; }   /* the last slide: its button sits above the tap areas */
.ach-viewer__tap { position: absolute; z-index: 3; top: 70px; bottom: 90px; width: 35%; border: 0; background: transparent; cursor: pointer; }
.ach-viewer__tap--prev { left: 0; }
.ach-viewer__tap--next { right: 0; width: 65%; }
.ach-viewer__arrow { position: absolute; top: 50%; translate: 0 -50%; width: 52px; height: 52px; border-radius: 50%; border: 1px solid rgba(217, 178, 92, 0.6); background: rgba(30, 1, 2, 0.6); color: var(--paper); font-size: 22px; cursor: pointer; }
.ach-viewer__arrow:disabled { opacity: 0.25; cursor: default; }
.ach-viewer__arrow--prev { left: calc(50% - 300px); }
.ach-viewer__arrow--next { right: calc(50% - 300px); }
@media (max-width: 720px) { .ach-viewer__arrow { display: none; } }

.ach-slide { position: absolute; inset: 0; animation: ach-in 350ms ease both; }
@keyframes ach-in { from { opacity: 0; transform: scale(1.02); } to { opacity: 1; transform: none; } }
.ach-slide__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; filter: blur(24px) brightness(0.5); transform: scale(1.2); }
.ach-slide__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.ach-slide__cap { position: absolute; left: 0; right: 0; bottom: 0; padding: 70px 22px 28px; background: linear-gradient(180deg, transparent, rgba(30, 1, 2, 0.92)); }
.ach-slide__top { margin: 0; font: 500 28px / 1.1 var(--font-serif); color: var(--gold-text); }
.ach-slide__bottom { margin: 6px 0 0; font: 600 14px / 1.35 var(--font-sans); letter-spacing: 0.02em; }
.ach-slide--text { display: flex; flex-direction: column; justify-content: center; gap: 14px; padding: 80px 28px 40px;
  background: radial-gradient(120% 80% at 50% 20%, var(--maroon), var(--maroon-deep)); }
.ach-slide__kicker { margin: 0; font: 700 12px / 1 var(--font-sans); letter-spacing: 0.2em; text-transform: uppercase; color: var(--gold-text); }
.ach-slide__title { margin: 0; font: 500 30px / 1.12 var(--font-serif); }
.ach-slide__sum { margin: 0; font: 16px / 1.55 var(--font-sans); opacity: 0.9; }
.ach-slide__go { position: relative; z-index: 6; align-self: flex-start; margin-top: 8px; }

/* ---------- cards ---------- */
.ach-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: clamp(18px, 2.4vw, 28px); }
.ach-card__link { display: flex; flex-direction: column; height: 100%; border-radius: 12px; overflow: hidden; background: var(--paper-3); border: 1px solid var(--paper-2); color: inherit; text-decoration: none;
  transition: transform var(--t-ui), box-shadow var(--t-ui); }
.ach-card__link:hover { transform: translateY(-3px); box-shadow: 0 18px 36px -20px rgba(60, 10, 10, 0.45); }
.ach-card__link:focus-visible { outline: 3px solid var(--gold); outline-offset: 3px; }
.ach-card__media { position: relative; display: block; aspect-ratio: 4 / 5; background: var(--paper-2); overflow: hidden; }
.ach-card__media img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 25%; }
.ach-card__tag { position: absolute; left: 14px; top: 14px; padding: 6px 10px; border-radius: 999px; background: var(--maroon); color: var(--paper); font: 700 11px / 1 var(--font-sans); letter-spacing: 0.14em; text-transform: uppercase; }
.ach-card__body { display: flex; flex-direction: column; gap: 8px; padding: 18px 20px 22px; flex: 1; }
.ach-card__date { font: 600 12px / 1 var(--font-sans); letter-spacing: 0.12em; text-transform: uppercase; color: var(--gold); }
.ach-card__title { font: 500 21px / 1.2 var(--font-serif); color: var(--maroon); }
.ach-card__who { font: 14px / 1.4 var(--font-sans); color: var(--ink-2); }
.ach-card__more { margin-top: auto; padding-top: 8px; font: 700 14px / 1 var(--font-sans); color: var(--maroon); }
.ach-empty { color: var(--ink-2); }

/* ---------- full story ---------- */
.ach-story { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(24px, 4vw, 56px); align-items: start; }
@media (max-width: 899px) { .ach-story { grid-template-columns: 1fr; } }
.ach-story__media { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.ach-story__fig { margin: 0; }
.ach-story__fig img { display: block; width: 100%; height: auto; border-radius: 10px; box-shadow: 0 18px 40px -24px rgba(60, 10, 10, 0.5); }
.ach-story__fig figcaption { margin-top: 8px; }
.ach-story__meta { display: flex; gap: 12px; align-items: center; margin: 0 0 14px; font: 600 13px / 1 var(--font-sans); color: var(--ink-2); }
.ach-story__tag { padding: 6px 10px; border-radius: 999px; background: var(--maroon); color: var(--paper); font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; }
.ach-story__headline { margin: 0; font: 500 clamp(30px, 3.4vw, 44px) / 1.05 var(--font-serif); color: var(--gold); }
.ach-story__subline { margin: 8px 0 0; font: 600 15px / 1.4 var(--font-sans); color: var(--ink); }
.ach-story__facts { display: grid; gap: 0; margin: 22px 0; border-top: 1px solid var(--paper-2); }
.ach-story__facts div { display: grid; grid-template-columns: 130px 1fr; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--paper-2); }
.ach-story__facts dt { font: 600 12px / 1.4 var(--font-sans); letter-spacing: 0.1em; text-transform: uppercase; color: var(--gold); }
.ach-story__facts dd { margin: 0; font: 15px / 1.45 var(--font-sans); }
.ach-story__p { font: 17px / 1.65 var(--font-sans); color: var(--ink); margin: 0 0 14px; max-width: 62ch; }
.ach-story__source { margin-top: 18px; }
.ach-story__actions { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-top: 22px; }
.ach-pager { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-top: clamp(32px, 5vw, 56px); padding-top: 22px; border-top: 1px solid var(--paper-2); }
.ach-pager__a { display: flex; flex-direction: column; gap: 6px; color: var(--maroon); text-decoration: none; font: 500 18px / 1.3 var(--font-serif); }
.ach-pager__a--prev { text-align: right; }

@media (prefers-reduced-motion: reduce) {
  .ach-viewer, .ach-slide, .ach-card__link, .ach-circle__ring { transition: none; animation: none; }
}
.ach-page .ach-circles { margin: 8px 0 clamp(20px, 3vw, 32px); }

/* ---- additions/administration.css ---- */
/* administration group (/about/school-administration/ and /about/leadership/): extra rules.
   Prefix: .adm-. Tokens only. Rewritten 2026-10-24 for the pages redesign (group "about"): the eleven 4:5 monogram
   posters became an organisation chart, and the class table gained a finder. The portrait slot keeps its 2026-10-18
   contract (a crest-coloured monogram until the school sends a photograph, with consent). */

/* ---- portrait slot (2026-10-18, kept): a maroon field inside a paper mount with a gold hairline and the initials.
   A photograph replaces the monogram: {{img}} inside .adm-portrait plus .adm-portrait--photo. The 9.5 px "photo to be
   supplied" note is gone (2026-10-24): the gap lives in the CONFIRM comment, not on the page. */
.adm-portrait { position: relative; flex: none; width: 56px; aspect-ratio: 4 / 5; padding: 4px; background: var(--paper-3); border: 1px solid var(--clay); }
.adm-portrait::before { content: ''; position: absolute; inset: 4px; background: var(--maroon); }
.adm-portrait::after { content: ''; position: absolute; inset: 8px; border: 1px solid var(--gold-text); opacity: 0.6; pointer-events: none; }
.adm-portrait__mono { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; z-index: 1; font: italic 300 22px / 1 var(--font-serif); letter-spacing: 0.02em; color: var(--gold-text); }
.adm-portrait--m { width: 88px; padding: 5px; }
.adm-portrait--m::before { inset: 5px; }
.adm-portrait--m::after { inset: 10px; }
.adm-portrait--m .adm-portrait__mono { font-size: 30px; }
.adm-portrait--photo::before, .adm-portrait--photo::after { content: none; }
.adm-portrait--photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* review fixes 2026-10-24: in the chart (01) the chip is quiet, paper-3 with a clay hairline and the initials in maroon
   serif, so thirteen maroon squares no longer make maroon the page's colour; the solid maroon chip stays only in 02 */
.adm-chart .adm-portrait::before { background: var(--paper-3); }
.adm-chart .adm-portrait::after { border-color: var(--clay); opacity: 1; }
.adm-chart .adm-portrait__mono { color: var(--maroon); font-weight: 400; }

/* ---- organisation chart (2026-10-24): four tiers, hairline connectors drawn with borders, each person a small panel
   (the home's results-card recipe: paper-3, 1 px clay, 3 px top rule) with the initials chip top-left.
   Phones: an indented list. The hierarchy survives as indentation and a left hairline; no connectors. ---------------- */
.adm-chart { list-style: none; margin-top: clamp(28px, 3.5vw, 48px); }
.adm-chart ol, .adm-chart ul { list-style: none; }
.adm-tier { position: relative; }
.adm-tier--1 { padding-top: 0; }
.adm-tier + .adm-tier { margin-top: 22px; padding-top: 22px; }
.adm-tier__label { display: block; margin-bottom: 12px; }
.adm-tier__row { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; }
.adm-card {
  --adm-edge: var(--maroon);
  position: relative;
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr);
  column-gap: 16px;
  align-items: start;
  padding: 16px 18px 18px;
  background: var(--paper-3);
  border: 1px solid var(--clay);
  border-top: 3px solid var(--adm-edge);
  min-width: 0;
}
.adm-card--gold { --adm-edge: var(--gold); }
.adm-card--ink { --adm-edge: var(--ink); }
.adm-card__body { min-width: 0; }
.adm-card__role { font: 500 11.5px / 1.3 var(--font-sans); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); }
.adm-card__name { margin-top: 6px; font: 400 clamp(20px, 1.6vw, 26px) / 1.15 var(--font-serif); letter-spacing: -0.005em; overflow-wrap: anywhere; }
.adm-card--l .adm-card__name { font-size: clamp(24px, 2.2vw, 36px); }
.adm-card__band { margin-top: 6px; font: 400 15px / 1.45 var(--font-sans); color: var(--ink-2); }
.adm-card__note { margin-top: 10px; font-size: 16px; line-height: 1.5; max-width: 40ch; }
/* a branch: a Vice Principal with her or his Teachers-in-Charge under it. align-content: start (review fixes 2026-10-24)
   keeps the branch's own rows at their natural height, so the shorter branch's Vice Principal card is not stretched to
   fill the row the two branches share; both Vice Principal cards are then the same width and height */
.adm-branch { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; align-content: start; }
.adm-branch__kids { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; margin-left: 20px; padding-left: 18px; border-left: 1px solid var(--clay); }
.adm-branch__kids .adm-card { padding: 14px 16px 16px; }
.adm-branch__kids .adm-card__name { font-size: clamp(18px, 1.3vw, 22px); }
@media (max-width: 767px) {
  .adm-tier + .adm-tier { margin-left: 0; }
  .adm-tier--2, .adm-tier--3 { margin-left: 20px; padding-left: 18px; border-left: 1px solid var(--clay); }
  .adm-tier--3 .adm-branch__kids { margin-left: 0; }
}
@media (min-width: 768px) {
  /* the connectors: a vertical hairline drops from the centre of each tier into the next; the next tier's row carries
     a horizontal hairline across its cards' centres, and each card a short stem up to it */
  .adm-tier + .adm-tier { margin-top: 0; padding-top: 44px; }
  .adm-tier + .adm-tier::before { content: ''; position: absolute; left: 50%; top: 0; width: 1px; height: 22px; background: var(--ink-2); }
  .adm-tier__row { grid-template-columns: repeat(var(--adm-cols, 2), minmax(0, 1fr)); gap: var(--gutter); }
  .adm-tier__row--1 { --adm-cols: 1; max-width: 32rem; margin-inline: auto; }
  .adm-tier__row--2 { --adm-cols: 2; max-width: 56rem; margin-inline: auto; }
  .adm-tier--3 .adm-tier__row { --adm-cols: 2; max-width: none; }
  .adm-tier + .adm-tier .adm-tier__row { position: relative; }
  .adm-tier + .adm-tier .adm-tier__row::before { content: ''; position: absolute; left: 25%; right: 25%; top: -22px; height: 1px; background: var(--ink-2); }
  .adm-tier + .adm-tier .adm-tier__row--1::before { left: 50%; right: 50%; }
  .adm-tier + .adm-tier .adm-tier__row > li { position: relative; }
  .adm-tier + .adm-tier .adm-tier__row > li::before { content: ''; position: absolute; left: 50%; top: -22px; width: 1px; height: 22px; background: var(--ink-2); }
  .adm-branch__kids { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin-left: 0; padding-left: 0; border-left: 0; position: relative; padding-top: 18px; }
  .adm-branch__kids::before { content: ''; position: absolute; left: 50%; top: 0; width: 1px; height: 18px; background: var(--clay); }
  /* the tier label sits on paper above the connector, so the hairline never runs through its letters */
  .adm-tier__label { position: relative; z-index: 1; display: table; margin: 0 auto 12px; padding: 0 14px; background: var(--paper); text-align: center; }
}
@media (min-width: 1100px) {
  .adm-tier--3 .adm-tier__row { --adm-cols: 2; }
  .adm-branch__kids { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1400px) {
  .adm-branch__kids .adm-card { padding: 16px 18px 18px; }
}

/* ---- the Principal and the Vice Principals (2026-10-24): three larger panels in a row; the Principal's card keeps the
   maroon rule, the Vice Principals' are gold (two colours of top rule on the page, review fixes 2026-10-24) ---------- */
.adm-heads { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); }
.adm-heads .adm-card { grid-template-columns: 88px minmax(0, 1fr); padding: clamp(20px, 2vw, 28px); }
@media (min-width: 768px) { .adm-heads { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 1023px) and (min-width: 768px) { .adm-heads .adm-card { grid-template-columns: 56px minmax(0, 1fr); } .adm-heads .adm-portrait--m { width: 56px; padding: 4px; } .adm-heads .adm-portrait--m::before { inset: 4px; } .adm-heads .adm-portrait--m::after { inset: 8px; } .adm-heads .adm-portrait--m .adm-portrait__mono { font-size: 22px; } }

/* ---- message cards (2026-10-18, restyled 2026-10-24): two panels side by side from 900 px; one quiet line in place of
   the dashed slot. The whole section is hidden on the public build until the words exist (data-portal-only). ---------- */
.adm-messages { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); }
.adm-message { padding: clamp(22px, 2.6vw, 34px); background: var(--paper-3); border: 1px solid var(--clay); border-top: 3px solid var(--maroon); }
.adm-message__head { display: flex; align-items: center; gap: 20px; }
.adm-message__name { margin-top: 6px; font: 400 clamp(24px, 2.2vw, 34px) / 1.1 var(--font-serif); }
.adm-message__context { margin-top: 22px; max-width: 52ch; font-size: 17px; line-height: 1.55; }
.adm-message__wait { margin-top: 14px; max-width: 52ch; font-size: 16px; line-height: 1.5; color: var(--ink-2); }
@media (min-width: 900px) { .adm-messages { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ---- the class finder (/about/leadership/, 2026-10-24): a select on the left, the result on the right from 768 px.
   All nine results are in the HTML, hidden until chosen; without JavaScript the panel says so and the table below is
   the answer. The result is a dl: Teacher-in-Charge, Vice Principal, the line to call (large, tap-to-call). ---------- */
.adm-finder { padding: clamp(22px, 2.6vw, 36px); background: var(--paper-3); border: 1px solid var(--clay); border-top: 3px solid var(--maroon); }
.adm-finder__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(24px, 3vw, 40px) var(--gutter); align-items: start; }
.adm-finder__field label { display: block; margin-bottom: 10px; }
.adm-finder__select {
  display: block;
  width: 100%;
  min-height: 52px;
  padding: 12px 44px 12px 16px;
  font: 400 19px / 1.3 var(--font-serif);
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--ink-2);
  border-radius: 0;
  appearance: none;
  -webkit-appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--ink) 50%), linear-gradient(135deg, var(--ink) 50%, transparent 50%);
  background-position: calc(100% - 22px) 55%, calc(100% - 16px) 55%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}
.adm-finder__select:focus-visible { outline: 2px solid var(--maroon); outline-offset: 2px; }
.adm-finder__hint { margin-top: 10px; font: 400 14px / 1.5 var(--font-sans); color: var(--ink-2); }
.adm-finder__result[hidden] { display: none; }
.adm-finder__intro { font-size: 17px; line-height: 1.55; color: var(--ink-2); max-width: 44ch; }
.adm-finder__intro[hidden] { display: none; }
/* the worked example (review r3): the result column shows one answer, quietly, until a class is chosen */
.adm-finder__example { margin-top: 18px; padding-top: 18px; border-top: var(--hairline); color: var(--ink-2); }
.adm-finder__example[hidden] { display: none; }
.adm-finder__example-label { margin-bottom: 4px; }
.adm-finder__example .dl dd, .adm-finder__example .adm-result__tel { color: var(--ink-2); }
.adm-result .dl dd { font-size: 19px; }
.adm-result__tel {
  display: inline-block;
  padding: 6px 0 10px;
  font: 300 clamp(30px, 3vw, 46px) / 1.1 var(--font-serif);
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: -0.005em;
  color: var(--ink);
  text-decoration: none;
  background-image: linear-gradient(var(--gold), var(--gold));
  background-repeat: no-repeat;
  background-position: 0 calc(100% - 6px);
  background-size: 100% 1px;
}
.adm-result__tel:hover, .adm-result__tel:focus-visible { background-size: 100% 2px; }
.adm-result__for { display: block; margin-top: 2px; font: 400 14px / 1.5 var(--font-sans); color: var(--ink-2); }   /* final review 2026-10-25: always on its own line under the number (it wrapped beside it at 390 px) */
.adm-result__note { margin-top: 16px; font: 400 15px / 1.5 var(--font-sans); color: var(--ink-2); max-width: 46ch; }
@media (min-width: 768px) {
  .adm-finder__grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .adm-finder__field { grid-column: 1 / span 5; }
  .adm-finder__out { grid-column: 7 / -1; }
}
/* the table: a fourth column, the line, as a 44 px tel link */
.adm-table .adm-table__tel { display: inline-block; padding: 11px 0; margin: -11px 0; font-variant-numeric: tabular-nums lining-nums; white-space: nowrap; background-position: 0 calc(100% - 13px); }   /* the 44 px padding would otherwise carry the gold underline into the line below */
.adm-table .adm-table__tel + .adm-table__tel { margin-left: 14px; }
.adm-table .adm-table__for { display: block; font: 400 13px / 1.4 var(--font-sans); color: var(--ink-2); }

/* ---- additions/admissions-form.css ---- */
/* admissions-form: the online admission form on /admissions/how-to-apply/#forms (2026-10-22). Screen: a paper card with
   two tabs, lettered sections like the school's PDF, underlined fields (main.css .field) and a dark action bar that sticks
   to the bottom while the form is on screen. Print: html.af-printing shows only .af-print, an A4 copy of the form.
   Tokens only; 44 px targets; no motion. */

.af-lead { max-width: 46rem; margin-top: 14px; }
.af {
  margin-top: clamp(28px, 4vw, 48px);
  background: var(--paper-3);
  border: 1px solid var(--clay);
  border-radius: 6px;
  box-shadow: 0 24px 48px -32px rgba(28, 23, 21, 0.35);
}
html:not(.js) .af, .af:not(.is-ready) .af__bar { display: none; }
.af__top {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px 24px;
  padding: clamp(18px, 2.4vw, 28px) clamp(18px, 3vw, 44px);
  border-bottom: 1px solid var(--clay);
}
.af__tabs { display: inline-flex; flex-wrap: wrap; gap: 4px; padding: 4px; border-radius: 999px; background: var(--paper-2); }
.af__tab {
  min-height: 44px; padding: 0 20px; border: 0; border-radius: 999px; background: transparent;
  font: 500 15px / 1 var(--font-sans); color: var(--ink-2); cursor: pointer;
}
.af__tab:hover { color: var(--ink); }
.af__tab[aria-selected="true"] { background: var(--ink); color: var(--paper); }
.af__tab:focus-visible { outline: 2px solid var(--maroon); outline-offset: 2px; }
/* 2026-10-24: a block, not a flex row. As a flex row the bare text node and the Send-online <span> became two columns and
   broke words on a 390 px phone; the first sentence now sits in .af__privacy-text and the gold dot is inline. */
.af__privacy { display: block; max-width: 34rem; font: 400 14px / 1.45 var(--font-sans); color: var(--ink-2); }
.af__privacy::before { content: ''; display: inline-block; vertical-align: middle; width: 8px; height: 8px; margin: -2px 10px 0 0; border-radius: 50%; background: var(--gold); }
.af__privacy-text { display: inline; }

.af__form { padding: 0 clamp(18px, 3vw, 44px) 8px; }
.af__sec { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; padding: clamp(24px, 3vw, 36px) 0; border-bottom: var(--hairline); }
.af__sec:last-child { border-bottom: 0; }
.af__head { display: grid; grid-template-columns: auto minmax(0, 1fr); column-gap: 14px; align-content: start; }
.af__n {
  grid-row: span 2; display: inline-grid; place-items: center; width: 40px; height: 40px; border-radius: 50%;
  border: 1px solid var(--gold); font: 400 19px / 1 var(--font-serif); color: var(--gold);
}
.af__title { grid-column: 2; align-self: center; font: 400 clamp(20px, 1.7vw, 25px) / 1.2 var(--font-serif); }
.af__head > .af__title:first-child { grid-column: 1 / -1; }
.af__note { grid-column: 2; margin-top: 6px; font: 400 14px / 1.5 var(--font-sans); color: var(--ink-2); max-width: 34rem; }
.af__head > .af__title:first-child + .af__note { grid-column: 1 / -1; }
.af__grid { display: grid; grid-template-columns: minmax(0, 1fr); column-gap: var(--gutter); align-items: start; }
.af__grid .field { margin-bottom: 18px; }
.af__req { color: var(--maroon); }
.af__f--upper input { text-transform: uppercase; }
.af__sub {
  grid-column: 1 / -1; margin: 10px 0 12px; padding-top: 12px; border-top: 1px dashed var(--clay);
  font: 500 11.5px / 1.2 var(--font-sans); letter-spacing: 0.14em; text-transform: uppercase; color: var(--gold);
}
.af__sub:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.af .field-group { margin-bottom: 18px; }
.af .field-group legend { padding: 0; margin-bottom: 4px; font: 500 13px / 1.2 var(--font-sans); color: var(--ink-2); }
.af__choices { display: flex; flex-wrap: wrap; gap: 0 28px; }
.af__age { margin-top: 2px; font: 500 14px / 1.4 var(--font-sans); color: var(--gold); min-height: 0; }
.af__tlabel { margin-bottom: 8px; font: 500 13px / 1.2 var(--font-sans); color: var(--ink-2); }
.af__twrap { overflow-x: auto; margin-bottom: 18px; }
.af__table { width: 100%; min-width: 420px; border-collapse: collapse; }
.af__table th { padding: 8px 10px; text-align: left; font: 500 11.5px / 1.2 var(--font-sans); letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-2); border-bottom: 1px solid var(--ink); }
.af__table td { padding: 0 10px; border-bottom: var(--hairline); }
.af__table input { width: 100%; min-height: 44px; border: 0; background: transparent; font: 400 16px / 1.3 var(--font-sans); color: var(--ink); }
.af__table input:focus-visible { outline: 2px solid var(--maroon); outline-offset: -2px; }
.af__no { width: 48px; color: var(--ink-2); font: 400 14px / 1 var(--font-sans); }
.af__subjects { display: grid; grid-template-columns: minmax(0, 1fr); gap: 6px; }
.af__subj { display: flex; flex-wrap: wrap; align-items: center; gap: 0 14px; padding: 2px 12px; border-radius: 4px; }
.af__subj--or { background: var(--paper-2); }
.af__or { font: italic 400 15px / 1 var(--font-serif); color: var(--gold); }
.af__subj .choice:has(input:disabled) { color: var(--ink-2); opacity: 0.55; cursor: not-allowed; }
.af__count { margin-top: 10px; font: 500 14px / 1.4 var(--font-sans); color: var(--ink); }

.af__bar {
  position: sticky; bottom: 12px; z-index: 5;
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px 20px;
  margin: 0 clamp(10px, 1.6vw, 20px) clamp(10px, 1.6vw, 20px);
  padding: 14px clamp(14px, 2vw, 24px);
  border-radius: 6px; background: var(--night); color: var(--paper);
  box-shadow: 0 18px 36px -18px rgba(20, 17, 16, 0.6);
}
.af__bar .btn--secondary { color: var(--paper); border-color: var(--paper); }
.af__bar .btn--secondary:hover { color: var(--gold-text); border-color: var(--gold-text); }
.af__bar .btn:focus-visible { outline-color: var(--amber); }
.af__clear { min-height: 44px; padding: 0 6px; border: 0; background: none; font: 400 15px / 1 var(--font-sans); color: var(--bone-dim); text-decoration: underline; text-underline-offset: 4px; cursor: pointer; }
.af__clear:hover, .af__clear.is-armed { color: var(--gold-text); }
.af__clear:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.af__status { flex: 1 1 220px; margin: 0; font: 400 14px / 1.45 var(--font-sans); color: var(--bone-dim); }
.af__status:empty { display: none; }
.af-blank { margin-top: clamp(32px, 4vw, 56px); }
/* 2026-10-24: the bar on phones. It wrapped to three rows and, sticky, covered the fields. Under 640 px it is static,
   one column, and holds one primary action (Download filled form) plus a "More" disclosure for Print blank, Clear and,
   when the portal is on, Send online. From 640 px the disclosure's contents sit in the bar as before and "More" is hidden. */
.af__more { display: none; }
.af__more-menu, .af__more-menu[hidden] { display: contents; }   /* hidden means "closed" on phones only (pages.css data-hidden-narrow) */
@media (max-width: 639px) {
  .af__bar { position: static; flex-direction: column; align-items: stretch; gap: 10px; margin-inline: 0; border-radius: 0; }
  .af__bar .btn { width: 100%; }
  .af__more { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 18px; border: 1px solid var(--bone-dim); border-radius: 999px; background: transparent; color: var(--paper); font: 500 15px / 1 var(--font-sans); cursor: pointer; }
  .af__more[aria-expanded="true"] { border-color: var(--gold-text); color: var(--gold-text); }
  .af__more:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
  .af__more-menu { display: flex; flex-direction: column; gap: 10px; }
  .af__more-menu[hidden] { display: none; }
  .af__clear { align-self: center; }
  /* the sibling table (section H) as stacked rows, not a sideways scroll */
  .af__twrap { overflow: visible; }
  .af__table { min-width: 0; }
  .af__table thead { display: none; }
  .af__table, .af__table tbody, .af__table tr, .af__table td { display: block; width: 100%; }
  .af__table tr { padding: 8px 0 10px; border-bottom: var(--hairline); }
  .af__table td { padding: 0; border: 0; }
  .af__table td.af__no { color: var(--gold); font: 500 12.5px / 1 var(--font-sans); letter-spacing: 0.14em; padding-bottom: 4px; }
  .af__table td[data-label]::before { content: attr(data-label); display: block; font: 500 12px / 1.3 var(--font-sans); color: var(--ink-2); }
}

/* Send online (website portal, 2026-10-23): contact choices, the read-the-privacy tick, the code panel */
.af__online { padding: 18px clamp(18px, 3vw, 44px) 4px; border-top: 1px solid var(--clay); }
.af__consent { margin-bottom: 6px; }
.af__agree { margin-top: 2px; }
.af__agree .link { color: var(--ink); }
.af__sent { padding: 0 clamp(10px, 1.6vw, 20px) clamp(10px, 1.6vw, 20px); }
.af__sent .pp-code { margin-top: 0; max-width: none; }
.af__bar .btn--primary:disabled { opacity: 0.6; cursor: progress; }

@media (min-width: 720px) {
  .af__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .af__f--wide { grid-column: 1 / -1; }
  .af__subjects { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1100px) {
  .af__sec { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: var(--gutter); }
}

/* ---- the printed A4 copy ---- */
.af-print { display: none; }
@media print {
  html.af-printing body > *:not(.af-print) { display: none !important; }
  html.af-printing .af-print { display: block; color: var(--ink); font: 400 9.5pt / 1.35 var(--font-sans); }
  .afp__head { display: grid; grid-template-columns: 52px minmax(0, 1fr) auto; gap: 10pt; align-items: center; padding-bottom: 8pt; border-bottom: 1.5pt solid var(--maroon); }
  .afp__head img { width: 52px; height: auto; }
  .afp__school { font: 400 16pt / 1.1 var(--font-serif); }
  .afp__addr { font-size: 8pt; color: var(--ink-2); }
  .afp__title { text-align: right; }
  .afp__t { font: 500 13pt / 1.1 var(--font-serif); text-transform: uppercase; letter-spacing: 0.06em; color: var(--maroon); }
  .afp__s { font-size: 9pt; }
  .afp__receipt { margin-top: 4pt; font-size: 8pt; }
  .afp__receipt span { display: inline-block; width: 70pt; border-bottom: 0.75pt solid var(--ink); }
  .afp__code { margin: 6pt 0 0; padding: 3pt 6pt; border: 0.75pt solid var(--ink); font: 600 10pt / 1.3 var(--font-sans); letter-spacing: 0.04em; }
  .afp__hint { margin: 6pt 0 2pt; font-size: 8pt; font-style: italic; color: var(--ink-2); }
  .afp__sec { padding-top: 6pt; break-inside: avoid; }
  .afp__h { margin-bottom: 3pt; font: 600 8.5pt / 1.2 var(--font-sans); letter-spacing: 0.1em; text-transform: uppercase; color: var(--maroon); }
  .afp__note { font-size: 7.5pt; color: var(--ink-2); margin-bottom: 3pt; }
  .afp__grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 14pt; }
  .afp__sub { grid-column: 1 / -1; margin-top: 3pt; font-weight: 600; font-size: 8.5pt; }
  .afp__row { display: flex; align-items: flex-end; gap: 6pt; min-height: 17pt; }
  .afp__row--wide { grid-column: 1 / -1; }
  .afp__k { flex: none; font-size: 8pt; color: var(--ink-2); }
  .afp__v { flex: 1; min-height: 13pt; padding: 0 2pt 1pt; border-bottom: 0.6pt dotted var(--ink); font-size: 9.5pt; }
  .afp__opts { display: inline-flex; align-items: center; gap: 4pt; }
  .afp__box { display: inline-grid; place-items: center; width: 9pt; height: 9pt; margin-right: 3pt; border: 0.75pt solid var(--ink); font-size: 8pt; line-height: 1; }
  .afp__table { grid-column: 1 / -1; width: 100%; margin: 3pt 0; border-collapse: collapse; }
  .afp__table th, .afp__table td { height: 15pt; padding: 1pt 5pt; border: 0.6pt solid var(--ink-2); text-align: left; font-size: 8.5pt; }
  .afp__table th { background: var(--paper-2); font-weight: 600; }
  .afp__subjects { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 3pt 14pt; margin-bottom: 3pt; }
  .afp__subjects em { font-style: italic; color: var(--ink-2); }
  .afp__docs { padding-left: 14pt; font-size: 8.5pt; }
  .afp__office { margin-top: 10pt; padding: 6pt 8pt; border: 0.75pt solid var(--ink); break-inside: avoid; font-size: 8.5pt; }
  .afp__office p { margin-top: 3pt; }
  .afp__signs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 30pt; margin-top: 26pt; }
  .afp__signs--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20pt; }
  .afp__signs span { padding-top: 3pt; border-top: 0.75pt solid var(--ink); text-align: center; font-size: 8pt; }
  .afp__foot { margin-top: 6pt; font-size: 8pt; font-weight: 600; }
  .afp__made { margin-top: 6pt; font-size: 7pt; color: var(--ink-2); }
}

/* ---- additions/admissions.css ---- */
/* admissions: /admissions/, /admissions/how-to-apply/, /admissions/fees/, /admissions/visit/, /admissions/enquire/,
   /admissions/starting-at-playpen/, /admissions/faq/ (2026-10-11; redesigned 2026-10-24 to the home's grammar).
   Every admissions page carries body_class "adm", so the group's restyles are scoped to .adm and touch no other group.
   Components (each documented in docs/additions/admissions.md):
     .adm-head / .adm-foot / .adm-panel      the home's sheet head grid, sheet foot and 3 px-ruled panel (kit fallback, adm- prefix)
     .adm-open / .adm-plate / .adm-hero-actions   the opening plate on a paper mount under the shell's hero, art-directed, with a button row
     .adm-cover                              the hub's photographic cover (the home's cover at page scale)
     .adm-picker / .adm-entries              the shared class picker: tiles -> one entry card + the highlighted call line; remembered
     .call-lines / .call-band (kept)         the three admissions lines set large; .call-line.is-chosen is new
     .adm-check                              a tickable, printable checklist (ticks remembered per device)
     .adm-forms                              the collapsed online-form panel on How to apply
     .adm-search / .adm-jump                 the FAQ's search box and topic links
     .adm-topics / .venue                    the Enquire topic chips and their one-paragraph answers
     .route-hint, .print-only, .print-btn-row (kept)
   Review r1 (2026-10-24): entry__facts dt/dd styled; guardian tick box height; hints above inputs; the hub's six cards stacked under
     640 px; the inset plate centred.
   Review r2 (2026-10-24): the hub cover on phones puts the copy and the button on paper above a mounted 4:5 photograph (the fixed
     consent toast covered the button on the picture); .adm-row--centre (a lone panel on ten columns); .adm-entries align to the top
     and show title-only cards on phones until a class is chosen (.adm-entries--brief); the Enquire call band's H2 at display-m under
     the plate; .adm-form-layout__after (the after-send list closes the right column level with the form); 44 px standalone links;
     .adm .tag-list as paper chips; the Enquire crest tile rules removed.
   Tokens only; 44 px targets; every motion has a prefers-reduced-motion rule and obeys the footer switch (html[data-motion="reduced"]). */

/* ---- 0. the H2 voice: the home's display-l on every admissions section title (2026-10-24) ---------------------------- */
.adm .section-title { font-size: clamp(36px, 4.8vw, 96px); line-height: 0.98; letter-spacing: -0.012em; max-width: 18ch; }
.adm .section-title em { color: var(--maroon); font-style: italic; }
.adm .is-night .section-title em { color: var(--gold-text); }
/* the H2 rises through a mask once, like the home's headline lines (kit [data-pk-split] fallback). Before it is on screen it
   waits at opacity 0 (never clipped to nothing: an element clipped to zero area is never "intersecting", so the reveal
   observer would not fire); when .is-in arrives the shell's own pp-title-rise keyframes run once. */
.adm .section-title[data-reveal] { transition: none; }
html.js-reveal .adm .section-title[data-reveal]:not(.is-in) { opacity: 0; transform: none; }
html.js-reveal .adm .section-title[data-reveal].is-in { opacity: 1; animation: pp-title-rise 1100ms var(--ease-mask) both; }
@media (prefers-reduced-motion: reduce) { .adm .section-title[data-reveal] { animation: none !important; clip-path: none !important; opacity: 1 !important; } }
html[data-motion="reduced"] .adm .section-title[data-reveal] { animation: none !important; clip-path: none !important; opacity: 1 !important; }

/* ---- 1. adm-head: the home's sheet head (H2 on 10 of 12 columns, lead on 7) ---------------------------------------- */
.adm-head { display: grid; grid-template-columns: minmax(0, 1fr); row-gap: clamp(20px, 2.6vw, 36px); margin-bottom: clamp(36px, 4.5vw, 64px); }
.adm-head > .section-title + * { margin-top: 0; }
.adm-head > .lead { max-width: 54ch; }
.adm-head > .lead a { color: inherit; }
@media (min-width: 1024px) {
  .adm-head { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); }
  .adm-head > .section-title { grid-column: 1 / span 10; }
  .adm-head > .lead { grid-column: 1 / span 7; }
}
.adm-head--tight { margin-bottom: clamp(24px, 3vw, 40px); }

/* ---- 2. adm-foot: the sheet foot (hairline, a sentence, an action, a source caption) --------------------------------- */
.adm-foot { display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px var(--gutter); margin-top: clamp(36px, 4.5vw, 64px); padding-top: 24px; border-top: var(--hairline); }
.adm-foot__text { font-size: 18px; line-height: 1.55; max-width: 62ch; }
.adm-foot__action { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 28px; }
.adm-foot__source { grid-column: 1 / -1; max-width: 80ch; }
@media (min-width: 1024px) {
  .adm-foot { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .adm-foot__text { grid-column: 1 / span 8; }
  .adm-foot__action { grid-column: 10 / -1; justify-content: flex-end; }
  /* review r2: a foot that closes with three routes gives its action five columns, so the links sit on one or two lines, not three */
  .adm-foot--links .adm-foot__text { grid-column: 1 / span 6; }
  .adm-foot--links .adm-foot__action { grid-column: 8 / -1; }
}
.is-night .adm-foot { border-top-color: var(--night-line); }
.is-night .adm-foot__source { color: var(--bone-dim); }

/* ---- 3. adm-panel: the home's card recipe (paper-3, 1 px clay, 3 px coloured top rule) ------------------------------ */
.adm-panel { --adm-edge: var(--maroon); background: var(--paper-3); border: 1px solid var(--clay); border-top: 3px solid var(--adm-edge); padding: clamp(20px, 2.2vw, 32px); }
.adm-panel--gold { --adm-edge: var(--gold); }
.adm-panel--ink { --adm-edge: var(--ink); }
.adm-panel__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 6px 24px; padding-bottom: 14px; margin-bottom: 16px; border-bottom: var(--hairline); }
.adm-panel__title { font: 400 clamp(22px, 1.8vw, 32px) / 1.12 var(--font-serif); letter-spacing: -0.005em; text-wrap: balance; }
.adm-panel__title a { color: inherit; text-decoration: none; background-image: linear-gradient(var(--gold), var(--gold)); background-repeat: no-repeat; background-position: 0 100%; background-size: 100% 1px; }
.adm-panel__title a:hover, .adm-panel__title a:focus-visible { color: var(--maroon); background-size: 100% 2px; }
.adm-panel__body > * + * { margin-top: 12px; }
.adm-panel p { font-size: 17px; line-height: 1.55; max-width: 52ch; }
.adm-panel .label + p { margin-top: 6px; }
.adm-panel__foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 24px; margin-top: 18px; padding-top: 14px; border-top: var(--hairline); }
.adm-panel__foot .small-print { flex: 1 1 24ch; }
.adm-panel__go { margin-top: 16px; font: 500 15px / 1.3 var(--font-sans); }
.adm-panel .call-lines { margin-top: 18px; }
.adm-panel .checklist li:last-child { border-bottom: 0; }
.adm-panels { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); }
.adm-panels > li { display: flex; flex-direction: column; }
.adm-panels > li > .adm-panel { flex: 1 1 auto; display: flex; flex-direction: column; }
.adm-panels .adm-panel__head, .adm-panels .adm-panel__body, .adm-panels .doc-list, .adm-panels .small-print { flex: 0 0 auto; }
/* review r2: the card's action (link or button) sits at the foot of an equal-height card, so the spare paper is between body and action */
.adm-panels .adm-panel__go { margin-top: auto; padding-top: 16px; }
@media (min-width: 640px) { .adm-panels { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) {
  .adm-panels--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .adm-panels--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .adm-panels--4 .adm-panel { padding: clamp(18px, 1.6vw, 24px); }
  .adm-panels--4 .adm-panel__title { font-size: clamp(20px, 1.5vw, 24px); }
}

/* ---- 4. adm-row: the 7 / 5 (or 8 / 4) two-part sheet, the home's achievement split -------------------------------- */
.adm-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(32px, 4vw, 56px) var(--gutter); align-items: start; }
@media (min-width: 1024px) {
  .adm-row { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .adm-row__main { grid-column: 1 / span 7; }
  .adm-row__side { grid-column: 9 / -1; }
  .adm-row--8 .adm-row__main { grid-column: 1 / span 8; }
  .adm-row--8 .adm-row__side { grid-column: 10 / -1; }
  /* review r2: a panel with nothing beside it takes ten columns, centred, like .adm-plate--inset (no half-band left blank) */
  .adm-row--centre .adm-row__main { grid-column: 2 / span 10; }
  .adm-row__side--sticky { position: sticky; top: calc(var(--nav-h) + 24px); }
}
.adm-row--after-steps { margin-top: clamp(36px, 4.5vw, 64px); }

/* ---- 5. the opening: a button row and a mounted, art-directed plate right under the shell's hero (2026-10-24) -------
   The shell writes the breadcrumb, the rule, the H1 and the standfirst; this first body section continues the first screen:
   .adm-hero-actions (one primary button at most) and .adm-plate, a figure.plate on the paper-3 mount with two pictures,
   .adm-plate__wide (from 768 px) and .adm-plate__tall (phones), each its own crop of the same frame. The hidden one is
   display:none and lazy, so a browser fetches only the one it shows. The curtain comes from pages.css (figure.plate[data-reveal]). */
.adm-open { padding-top: 0; }
.adm-hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 28px; }
.adm-hero-actions + .adm-plate { margin-top: clamp(28px, 4vw, 56px); }
.adm-plate { margin: 0; }
.adm-plate__wide { display: none; }
.adm-plate__tall { display: block; }
.adm-plate img { display: block; width: 100%; height: auto; object-fit: cover; }
.adm-plate__tall img { aspect-ratio: 4 / 5; }
.adm-plate--4x3 .adm-plate__tall img { aspect-ratio: 4 / 3; }
.adm-plate--3x2 .adm-plate__tall img { aspect-ratio: 3 / 2; }
@media (min-width: 768px) {
  .adm-plate__wide { display: block; }
  .adm-plate__tall { display: none; }
  .adm-plate__wide img { aspect-ratio: 16 / 9; }
  .adm-plate--21x9 .adm-plate__wide img { aspect-ratio: 21 / 9; }
  .adm-plate--3x2 .adm-plate__wide img { aspect-ratio: 3 / 2; }
  /* round-2 fixes (2026-10-25): 3:2 from 768 px only, the phone keeps its own 4:5 crop (Book a visit) */
  .adm-plate--w3x2 .adm-plate__wide img { aspect-ratio: 3 / 2; }
}
@media (min-width: 1024px) { .adm-plate--16x9 .adm-plate__wide img { aspect-ratio: 16 / 9; } }
/* a plate whose source is 1440 wide stays inside nine columns rather than stretching across the band */
.adm-plate--inset { max-width: min(100%, 72rem); margin-inline: auto; }   /* review r1: inset on both sides equally, not only the right */
@media (max-width: 479px) {
  .adm-hero-actions .btn--primary, .adm-hero-actions .btn--secondary { width: 100%; }
}

/* ---- 6. adm-cover: the hub's photographic cover, the home's cover at page scale (2026-10-24) -----------------------
   The breadcrumb (shell) and the rule stay on paper above the photograph; the H1, the lead and one primary button sit
   bottom-left on the picture, in paper, over the home's two-direction ink scrim (0.86 from the bottom, 0.34 from the left).
   Two crops: 16:9 from 768 px, 4:5 on phones. Contrast measured on the brightest frame: the copy sits on the lawn, the
   darkest part of the frame, under the 86 % scrim. */
.adm-cover .band + .adm-cover__media { margin-top: clamp(14px, 2vw, 28px); }
.adm-cover__media { position: relative; max-width: var(--band-max); margin-inline: auto; background: var(--night); }
.adm-cover__wide { display: none; }
.adm-cover__tall { display: block; }
.adm-cover__media img { display: block; width: 100%; height: min(92svh, 640px); object-fit: cover; object-position: 50% 45%; }
.adm-cover__scrim { position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(to top, color-mix(in srgb, var(--ink) 86%, transparent) 0%, color-mix(in srgb, var(--ink) 55%, transparent) 38%, transparent 72%),
    linear-gradient(to right, color-mix(in srgb, var(--ink) 34%, transparent) 0%, transparent 60%); }
.adm-cover__copy { position: absolute; inset: auto 0 0 0; padding-bottom: clamp(24px, 4vw, 56px); color: var(--paper); }
.adm-cover__title { font: 300 clamp(40px, 5.4vw, 104px) / 0.98 var(--font-serif); letter-spacing: -0.015em; text-wrap: balance; max-width: 14ch; color: var(--paper); }
.adm-cover__title em { color: var(--gold-text); font-style: italic; font-weight: inherit; }
.adm-cover__lead { margin-top: clamp(14px, 2vw, 28px); max-width: 44ch; color: var(--paper); }
.adm-cover__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 28px; margin-top: clamp(20px, 2.4vw, 32px); }
.adm-cover .btn--text { color: var(--paper); background-image: linear-gradient(var(--gold-text), var(--gold-text)); }
.adm-cover .btn:focus-visible { outline: 2px solid var(--amber); outline-offset: 3px; }
@media (max-width: 479px) {
  .adm-cover__actions .btn--primary { width: 100%; }
}
/* review r2 (2026-10-24): on phones the copy block (H1, lead, the one button) sits on paper above the photograph, as the other six
   pages open (H1, standfirst, buttons, then the plate), so the button lands in the first screen at about y 400, clear of the fixed
   consent toast (y 628 to 828 on a 390 x 844 phone, portal.css, N7); the 4:5 crop then follows on a paper mount. No scrim: the
   type is ink on paper. Replaces the r1 phone scrim (78 % ink to 45 % of the height). */
@media (max-width: 767px) {
  .adm-cover__media { display: flex; flex-direction: column; background: none; }
  .adm-cover__copy { order: -1; position: static; color: var(--ink); padding: 0 0 clamp(24px, 5vw, 36px); }
  .adm-cover__title, .adm-cover__lead { color: var(--ink); }
  .adm-cover__title em { color: var(--maroon); }
  .adm-cover .btn--text { color: var(--ink); background-image: linear-gradient(var(--gold), var(--gold)); }
  .adm-cover .btn:focus-visible { outline-color: var(--maroon); }
  .adm-cover__scrim { display: none; }
  .adm-cover__tall { display: block; margin-inline: var(--margin); padding: 10px; background: var(--paper-3); border: 1px solid var(--clay); }
  .adm-cover__media img { height: auto; aspect-ratio: 4 / 5; }
}
@media (min-width: 768px) {
  .adm-cover__wide { display: block; }
  .adm-cover__tall { display: none; }
  .adm-cover__media img { height: min(78svh, 760px); object-position: 55% 45%; }
}
@media (min-width: 1840px) { .adm-cover__media { border-inline: 1px solid var(--clay); } }
/* the H1 rises through a mask as the shell's does; the lead and buttons fade up after it */
html.js:not([data-motion="reduced"]) .adm-cover__title { animation: pp-title-rise 1100ms var(--ease-mask) both; }
html.js:not([data-motion="reduced"]) .adm-cover__lead, html.js:not([data-motion="reduced"]) .adm-cover__actions { animation: pp-fade-rise 900ms var(--ease-out) 250ms both; }
@media (prefers-reduced-motion: reduce) { .adm-cover__title, .adm-cover__lead, .adm-cover__actions { animation: none !important; } }
@media (forced-colors: active) { .adm-cover__scrim { display: none; } .adm-cover__copy { position: static; color: CanvasText; padding-top: 16px; } .adm-cover__title { color: CanvasText; } }

/* ---- 7. the home's steps, feats and event cards on an inner page (small fits only) ----------------------------------- */
.adm .steps { margin-top: 0; }
.adm .step h3 { font-size: clamp(21px, 1.6vw, 28px); }
.adm .step p { max-width: 34ch; }
.adm .step p + p { margin-top: 10px; }
.adm .step__go { font: 500 15px / 1.3 var(--font-sans); }
@media (min-width: 640px) { .adm .adm-steps--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1024px) {
  .adm .adm-steps--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* review r2: every short standalone link in the group is a 44 px target (the site-wide rows give 27 to 38 px); the lists lose their
   22 px gap because the link itself now carries the height */
.adm .link--arrow, .adm .link-list a, .adm .where-next__col a, .adm .adm-check__go a { min-height: 44px; display: inline-flex; align-items: center; }
.adm .link-list, .adm .where-next__col ul { gap: 2px; }
.adm .adm-check__go a { padding: 0; }
.adm .where-next .section-title { margin-bottom: 0; }
/* review r2: the payment channels as paper chips, not dash lists (Fees, section 04) */
.adm .tag-list { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; font: 400 16px / 1.3 var(--font-sans); }
.adm .tag-list li { min-height: 44px; padding: 0 16px; align-items: center; border: 1px solid var(--clay); background: var(--paper-3); }
.adm .tag-list li::before { display: none; }
/* the ink line of each step draws as it comes into view (the home's step draw, kit .pk-steps-draw fallback) */
.adm .step::before { transition: transform 700ms var(--ease-out); }
html.js-reveal .adm .step:not(.is-in)::before { transform: scaleX(0); }
@media (prefers-reduced-motion: reduce) { .adm .step::before { transform: none !important; transition: none !important; } }
html[data-motion="reduced"] .adm .step::before { transform: none !important; transition: none !important; }
.adm .step .venue { margin-top: 14px; }

.adm .feats { margin-top: 0; }
.adm-feats { display: grid; grid-template-columns: minmax(0, 1fr); column-gap: var(--gutter); }
.adm-feats .feat__t { font-size: 15.5px; max-width: 34ch; }
@media (max-width: 639px) { .adm-feats .feat { grid-template-columns: 72px minmax(0, 1fr); } .adm-feats .feat__n { font-size: 36px; } }
@media (min-width: 1024px) {
  .adm-feats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .adm-feats .feat:nth-child(2) { border-top: var(--hairline); }
}
.adm-feats .feat__n small { font-size: 0.5em; letter-spacing: 0; }

.adm .ev-grid { margin-top: 0; }
.adm .ev__media img { object-position: 50% 50%; }
/* review r2: the Book a visit card shows the Visit page's own plate. Round-2 fixes (2026-10-25): the plate is now 3:2 like the card,
   so the card shows all of it; in the 96 px square on phones the window sits at the right, where the crest and the entrance are */
.adm .ev__card[href*="/visit/"] img { object-position: 100% 50%; }
@media (min-width: 1024px) {
  .adm .ev-grid--6 { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .adm .ev-grid--6 .ev { grid-column: span 4; }
}
/* review r1 (2026-10-24): under 640 px the home's swipe row showed 1.2 of the six cards with no cue; the hub's main navigation
   is a stacked list instead, 96 px square thumbnails on the left, every page visible without a gesture */
@media (max-width: 639px) {
  .adm .ev-grid--6 { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0; margin-inline: 0; padding: 0; overflow: visible; scroll-snap-type: none; border-bottom: var(--hairline); }
  .adm .ev-grid--6 .ev { flex: none; scroll-snap-align: none; }
  .adm .ev-grid--6 .ev__card { display: grid; grid-template-columns: 96px minmax(0, 1fr); column-gap: 16px; row-gap: 4px; align-items: start; padding: 16px 0; border-top: var(--hairline); }
  .adm .ev-grid--6 .ev__media { grid-column: 1; grid-row: 1 / span 4; margin: 0; padding: 4px; }
  .adm .ev-grid--6 .ev__media img { aspect-ratio: 1; }
  .adm .ev-grid--6 .ev__n, .adm .ev-grid--6 .ev__name, .adm .ev-grid--6 .ev__text, .adm .ev-grid--6 .ev__more { grid-column: 2; }
  .adm .ev-grid--6 .ev__name { font-size: 22px; }
  .adm .ev-grid--6 .ev__text { font-size: 15.5px; line-height: 1.45; }
  .adm .ev-grid--6 .ev__more { margin-top: 2px; padding: 8px 0 4px; }
}

/* the one highlighted statement: the home's .venue (paper-2, 3 px gold left rule) used in flow, not in the results grid */
.adm .venue { grid-column: auto; max-width: 62ch; }
.adm .venue__text { font-size: clamp(18px, 1.3vw, 22px); }
.adm .venue__text a { color: inherit; }
.adm .venue--note .venue__text { font-size: 17.5px; line-height: 1.55; }
.adm .venue + .venue { margin-top: 16px; }
.adm .is-night .venue { background: var(--night-2); border-left-color: var(--gold-text); }

/* ---- 8. the class picker (hub, How to apply; 2026-10-24) ------------------------------------------------------------
   role="group" with a visible label; sixteen tiles in three brackets; under 480 px the select takes over; without
   JavaScript the picker is hidden and every entry card shows. The chosen class is remembered on the device (pp:adm-class). */
.adm-picker { padding-bottom: 8px; }
.adm-picker__label { font: 400 17px / 1.4 var(--font-serif); color: var(--ink); margin-bottom: 14px; }
.adm-picker__group + .adm-picker__group { margin-top: 14px; }
.adm-picker__group .label { margin-bottom: 8px; }
.adm-picker .chips { gap: 8px; }
.adm-picker .chip { min-width: 52px; padding: 0 14px; font-variant-numeric: tabular-nums lining-nums; }
.adm-picker .chip[aria-pressed="true"] { border-color: var(--maroon); background: var(--maroon); color: var(--paper); }
.adm-picker__select { display: none; max-width: 24rem; }
.adm-picker .chips__status { margin: 14px 0 0; }
@media (max-width: 479px) {
  .adm-picker__tiles { display: none; }
  .adm-picker__select { display: flex; }
}
html:not(.js) .adm-picker { display: none; }
.adm-entries { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); align-items: start; margin-top: clamp(20px, 2.4vw, 32px); }
/* until a class is chosen (and without JavaScript) all four cards show: two columns from 640 px so the page stays short;
   with one card left it takes the whole column. Review r2: the cards align to the top (align-items: start), so the short gold
   card is not stretched half empty */
@media (min-width: 640px) { .adm-entries:not(:has(> [hidden])) { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
html:not(.js) .adm-entries { margin-top: 0; }
/* review r2: on phones, until a class is chosen the four cards show their title and the first fact only (admissions.js adds
   .adm-entries--brief while nothing is chosen), so the call sheet is one scroll away; without JavaScript every card is complete */
@media (max-width: 639px) {
  .adm-entries--brief .adm-entry .entry__facts > div:not(:first-child),
  .adm-entries--brief .adm-entry .adm-panel__body,
  .adm-entries--brief .adm-entry .adm-entry__go { display: none; }
  .adm-entries--brief .adm-entry { padding-top: 16px; padding-bottom: 16px; }
  .adm-entries--brief .adm-entry .adm-panel__head { padding-bottom: 10px; margin-bottom: 10px; }
  .adm-entries--brief .adm-entry .adm-panel__head:last-child { padding-bottom: 0; margin-bottom: 0; border-bottom: 0; }
  /* round-2 fixes (2026-10-25): the gold Class X and XII card has no facts, only a body (hidden here), so its head closes the card */
  .adm-entries--brief .adm-entry:not(:has(.entry__facts)) .adm-panel__head { padding-bottom: 0; margin-bottom: 0; border-bottom: 0; }
  .adm-entries--brief .adm-entry .entry__facts > div:first-child { padding-bottom: 0; }
}
/* review r1 (2026-10-24): dl.entry__facts had no dt/dd rule anywhere (pages.css lost .entry with the old entry points), so every card
   read as ten identical serif lines. The home's nb-card label/value grammar: a small-caps sans label over a 17 px serif value, one
   hairline row per fact. Used by the entry cards (hub, How to apply) and the arrival card (Book a visit). */
.adm .entry__facts { margin: 0; }
.adm .entry__facts > div { padding: 12px 0; border-top: var(--hairline); }
.adm .entry__facts dt { font: 500 11.5px / 1.3 var(--font-sans); letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-2); margin-bottom: 4px; }
.adm .entry__facts dd { margin: 0; font-size: 17px; line-height: 1.5; max-width: 52ch; }
.adm-entry .entry__facts { margin-top: 0; }
.adm-entry .entry__facts > div:first-child { border-top: 0; padding-top: 0; }
.adm-entry .entry__facts dd { max-width: 44ch; }
.adm-entry__go { margin-top: 18px; font: 500 15px / 1.3 var(--font-sans); }
/* round-2 fixes (2026-10-25): under a panel head the first fact loses its own rule (the arrival card drew two hairlines) */
.adm-panel__head + .entry__facts > div:first-child { border-top: 0; padding-top: 0; }
.adm-entries + .small-print { margin-top: 18px; }

/* ---- 9. call sheet: the three admissions lines set large (2026-10-11; is-chosen added 2026-10-24) ------------------
   A list of rows: the section on the left, the number in Newsreader on the right (stacked on a phone). The number is a
   {{phone:key class="call-line__tel"}} link. On the night ground the rules and the numbers turn paper and gold.
   Rule since 2026-10-24: one call sheet per page; the picker's chosen line carries a 3 px gold left rule (.is-chosen). */
.call-lines { list-style: none; border-top: 1px solid var(--ink); }
.call-line { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 2px 24px; padding: 14px 0 12px; border-bottom: var(--hairline); border-left: 3px solid transparent; transition: padding-left 300ms var(--ease-out), border-color 300ms var(--ease-out); }
.call-line.is-chosen { padding-left: 14px; border-left-color: var(--gold); }
.call-line.is-chosen .call-line__who { color: var(--ink); }
.call-line__who { font: 500 12.5px / 1.3 var(--font-sans); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); }
.call-line__tel {
  display: inline-block;
  padding: 8px 0 12px;                              /* a 44 px target; the hairline stays 4 px under the digits */
  color: var(--ink);
  font: 300 clamp(28px, 2.8vw, 44px) / 1.1 var(--font-serif);
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: -0.005em;
  text-decoration: none;
  background-image: linear-gradient(var(--gold), var(--gold));
  background-repeat: no-repeat;
  background-position: 0 calc(100% - 7px);
  background-size: 100% 1px;
}
.call-line__tel:hover, .call-line__tel:focus-visible { background-size: 100% 2px; }
.call-lines__hours { margin-top: 14px; font: 400 14px / 1.5 var(--font-sans); color: var(--ink-2); }
.call-lines__hours a { color: inherit; }
.is-night .call-lines { border-top-color: var(--paper); }
.is-night .call-line { border-bottom-color: var(--night-line); }
.is-night .call-line.is-chosen { border-left-color: var(--gold-text); }
.is-night .call-line.is-chosen .call-line__who { color: var(--paper); }
.is-night .call-line__who { color: var(--gold-text); }
.is-night .call-line__tel { color: var(--paper); background-image: linear-gradient(var(--gold-text), var(--gold-text)); }
.is-night .call-lines__hours { color: var(--bone-dim); }
@media (max-width: 479px) { .call-line { flex-direction: column; align-items: flex-start; } }
@media (min-width: 640px) { .call-line { padding: 16px 0 14px; } }
@media (prefers-reduced-motion: reduce) { .call-line { transition: none; } }
html[data-motion="reduced"] .call-line { transition: none; }
.adm-call .label { margin-bottom: 12px; }
.adm-call .call-lines__hours { max-width: 36ch; }
/* a two-column band on the night ground or a light one: the statement left, the lines right */
.call-band { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 4vw, 56px); align-items: start; }
.call-band__text > * + * { margin-top: clamp(16px, 2vw, 24px); }
.call-band__text .section-title { max-width: 14ch; }
.call-band__text p { max-width: 38ch; font: 400 clamp(18px, 1.4vw, 22px) / 1.45 var(--font-serif); }
.call-band__text .small-print { font: 400 14px / 1.5 var(--font-sans); }
.call-band__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 28px; }
.is-night .call-band .btn--text { color: var(--paper); background-image: linear-gradient(var(--gold-text), var(--gold-text)); }
.is-night .call-band .btn:focus-visible { outline-color: var(--amber); }
@media (min-width: 900px) { .call-band { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); column-gap: var(--gutter); } .call-band__text { padding-right: var(--gutter); } }
/* the Enquire call band (review r2, 2026-10-24): it follows the opening plate as its own sheet; its H2 runs at the home's medium
   size (display-m) under the "Prefer to call?" eyebrow, so the page's H1 leads the first screen and the numbers are the object.
   The r1 crest tile and its phone grid are gone. */
.adm-callband .section-title { font-size: clamp(28px, 2.9vw, 54px); line-height: 1.05; letter-spacing: -0.005em; max-width: 16ch; }
.adm-callband-section { padding-top: clamp(40px, 5vw, 72px); }

/* ---- 10. route hint (visit and enquire; 2026-10-11) ------------------------------------------------------------------
   The class chosen in the form picks the admissions line to show under it (js: build/additions/admissions.js). The box is a
   polite live region that is always in the page and empty (no size) until a class is chosen. */
.route-hint { font: 400 16px / 1.5 var(--font-sans); color: var(--ink-2); }
.route-hint.is-on { margin: -6px 0 24px; padding: 12px 16px 14px; border-left: 2px solid var(--gold); background: var(--paper-3); }
.route-hint__line { color: var(--ink); }
.route-hint__line a { display: inline-block; padding: 8px 0 10px; }

/* ---- 11. form layout: the call sheet (or the answers) before the form in the DOM, beside it from 1024 px (2026-10-24)
   The DOM is in the phone order (WCAG 1.3.2, 2.4.3); the desktop places the two with grid rows, not CSS order. */
.adm-form-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(36px, 5vw, 64px); align-items: start; }
.adm-form-layout__side > * + * { margin-top: 28px; }
/* review r2: the fields run in one column (no two-column first row), and the after-send list (.adm-form-layout__after, after the
   form in the DOM) takes the foot of the right-hand column on a desktop, aligned to the end of the form, so the section closes level */
@media (min-width: 1024px) {
  .adm-form-layout { grid-template-columns: repeat(12, minmax(0, 1fr)); grid-template-rows: auto minmax(0, 1fr); column-gap: var(--gutter); row-gap: 0; }
  .adm-form-layout__side { grid-column: 10 / -1; grid-row: 1; }
  .adm-form-layout__main { grid-column: 1 / span 8; grid-row: 1 / span 2; }
  .adm-form-layout__after { grid-column: 10 / -1; grid-row: 2; align-self: end; margin-top: 0; padding-top: 40px; }
}
.adm-form-layout__side .call-line__tel { font-size: clamp(26px, 2vw, 32px); }
.adm-after { list-style: none; counter-reset: after; border-top: 1px solid var(--ink); }
.adm-after li { position: relative; counter-increment: after; padding: 12px 0 12px 40px; border-bottom: var(--hairline); font-size: 16px; line-height: 1.5; }
.adm-after li::before { content: counter(after, decimal-leading-zero); position: absolute; left: 0; top: 15px; font: 500 12.5px / 1 var(--font-sans); letter-spacing: 0.14em; color: var(--gold); font-variant-numeric: tabular-nums; }
/* the guardian and join ticks read at 17 px serif like the WhatsApp/SMS ticks (pages.css gives every label inside .field 13 px sans
   and the field's column layout, which stacked the words above the box) */
.adm .page-form .field.page-form__guardian, .adm .page-form .field.page-form__join { display: block; }
.adm .page-form .field.page-form__guardian .choice, .adm .page-form .field.page-form__join .choice { display: flex; flex-direction: row; align-items: flex-start; gap: 12px; min-height: 44px; font: 400 17px / 1.5 var(--font-serif); color: var(--ink); cursor: pointer; }
/* review r1: main.css gives every input inside .field min-height 48px, which drew the 22 px box in the middle of a 48 px row, a line
   below its words; min-height 0 and max-height 22px put the box on the first line of the label */
.adm .page-form .field.page-form__guardian .choice input, .adm .page-form .field.page-form__join .choice input { flex: none; width: 22px; height: 22px; min-height: 0; max-height: 22px; padding: 0; margin: 3px 0 0; }
/* the hints sit above their input line (the .field is a flex column, so the source order is the visual order), never between an
   input and the next label; the "after you press send" list follows the form */
.adm .page-form .field__hint + input, .adm .page-form .field__hint + select { margin-top: 2px; }
.adm-after-wrap { margin-top: clamp(28px, 3.5vw, 44px); max-width: 40rem; }
.adm-after-wrap .label { margin-bottom: 10px; }
.adm .form-note:focus { outline: none; }
.adm .form-note:focus-visible { outline: 2px solid var(--maroon); outline-offset: 3px; }
.page-form .field__hint { max-width: 46ch; }

/* ---- 12. Enquire topic chips and their answers (2026-10-24) ------------------------------------------------------------
   Single-choice chips (aria-pressed); the matching .venue answer shows under them and the question box is pre-filled.
   #topic-<key> in the URL presses a chip (the Fees page links that way). Hidden without JavaScript. */
.adm-topics { margin-bottom: 18px; }
.adm-topics .chips__status { margin: 10px 0 0; min-height: 0; }
.adm-answer { margin: 18px 0 28px; }
.adm-answer[hidden] { display: none; }
html:not(.js) .adm-topics { display: none; }
/* quick picks above a free-text box (Book a visit, "A time that suits you"; 2026-10-26) */
.adm-picks { margin: 10px 0 12px; }
html:not(.js) .adm-picks { display: none; }
.adm-topics .chip[aria-pressed="true"] { border-color: var(--maroon); background: var(--maroon); color: var(--paper); }

/* ---- 13. adm-check: a tickable, printable list (What to bring, fee questions, before the first day; 2026-10-24) -------
   Real checkboxes; the ticks are remembered on the device (data-adm-store), a convenience the list never needs. */
.adm-check { list-style: none; }
.adm-check__item { display: grid; grid-template-columns: 22px minmax(0, 1fr); column-gap: 14px; row-gap: 2px; align-items: start; min-height: 44px; padding: 10px 0; border-bottom: var(--hairline); }
.adm-check__item:first-child { border-top: var(--hairline); }
.adm-check__item input { width: 22px; height: 22px; margin: 5px 0 0; accent-color: var(--maroon); cursor: pointer; }
.adm-check__item input:focus-visible { outline: 2px solid var(--maroon); outline-offset: 2px; }
.adm-check__item label { font: 400 17.5px / 1.5 var(--font-serif); color: var(--ink); cursor: pointer; padding: 3px 0; }
.adm-check__item input:checked + label { color: var(--ink-2); }
.adm-check__go { grid-column: 2; font: 500 14px / 1.4 var(--font-sans); }
.adm-check__go a { display: inline-block; padding: 6px 0; }
.adm-panel .adm-check__item:last-child { border-bottom: 0; }
.adm-panel__head + .adm-check .adm-check__item:first-child, .adm-panel__head + .adm-check--cols .adm-check__item:nth-child(2) { border-top: 0; }
@media (min-width: 640px) {
  .adm-check--cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gutter); }
  .adm-check--cols .adm-check__item:nth-child(2) { border-top: var(--hairline); }
}
html.print-list .print-sheet .adm-check__item { break-inside: avoid; }

/* ---- 14. the collapsed online-form panel on How to apply (2026-10-24) ----------------------------------------------
   [data-adm-toggle] opens #forms-panel (aria-expanded); a link to #forms opens it too. Without JavaScript the panel is open. */
.adm-forms[hidden] { display: none; }
html:not(.js) .adm-forms[hidden] { display: block; }
html:not(.js) [data-adm-toggle] { display: none; }
.adm-forms { margin-top: clamp(32px, 4vw, 56px); }
.adm-forms:focus { outline: none; }
.adm-forms__close { margin-top: 18px; }
.adm-forms__tabnote { flex: 1 1 100%; margin: 12px 0 0; max-width: 62ch; }
.adm-forms-cards .adm-panel .doc-list { margin-top: 14px; border-top-color: var(--clay); }
.adm-forms-cards .adm-panel .doc-list a { font-size: clamp(17px, 1.3vw, 20px); }

/* ---- 15. the FAQ: search box, topic links, most-asked cards (2026-10-24) ---------------------------------------------- */
.adm-search { max-width: 36rem; }
.adm-search .field { margin-bottom: 0; }
.adm-search input { min-height: 44px; }
.adm-search__status { margin: 12px 0 0; }
html:not(.js) .adm-search { display: none; }
.adm-jump { margin-top: 22px; }
.adm-jump .label { margin-bottom: 10px; }
.adm-jump .chip { display: inline-flex; align-items: center; text-decoration: none; color: var(--ink); }
.adm-jump .chip:hover, .adm-jump .chip:focus-visible { border-color: var(--ink); color: var(--maroon); }
.adm-faq .accordion-group[hidden], .adm-faq .accordion__item[hidden] { display: none; }
.adm-faq .accordion__controls { margin-bottom: 14px; }
@media (max-width: 1023px) { .adm-faq .chapter-nav { display: none; } }
.adm-faq .chapter-nav a { min-height: 44px; }

/* ---- 16. printable list (how to apply, starting at Playpen, fees, visit; 2026-10-11) ----------------------------------
   The button copies the list into .print-sheet, prints only that, and removes it. Nothing shows on screen. */
.print-sheet, .print-only { display: none; }
.print-btn-row { margin-top: 18px; display: flex; flex-wrap: wrap; align-items: center; gap: 12px 28px; }
.is-night .print-btn-row .btn--secondary { color: var(--paper); border-color: var(--paper); }
.is-night .print-btn-row .btn--secondary:hover { color: var(--gold-text); border-color: var(--gold-text); }
.is-night .print-btn-row .btn--secondary:focus-visible { outline-color: var(--amber); }
html:not(.js) [data-print-list] { display: none; }
@media print {
  html.print-list body > *:not(.print-sheet) { display: none !important; }
  html.print-list .print-sheet { display: block; padding: 0; color: var(--ink); }
  html.print-list .print-sheet .print-only { display: block; margin-bottom: 10pt; font: 400 10pt / 1.4 var(--font-sans); }
  html.print-list .print-sheet [data-print-skip] { display: none !important; }
  html.print-list .print-sheet .checklist li { border-bottom: 1px solid var(--ink-2); break-inside: avoid; }
  html.print-list .print-sheet .checklist li::before { border-color: var(--ink); }
  html.print-list .print-sheet .label, html.print-list .print-sheet h2, html.print-list .print-sheet h3 { color: var(--ink); }
  html.print-list .print-sheet .adm-panel { border: 0; padding: 0; background: none; }
  html.print-list .print-sheet .adm-panel__foot, html.print-list .print-sheet .print-btn-row { display: none !important; }
}

/* ---- 17. small spacing for the lists this group uses (2026-10-11) ---------------------------------------------------- */
.label + .checklist { margin-top: 14px; }
.label + .small-print { margin-top: 10px; }
.small-print + .contact-cards { margin-top: 18px; }
.layout__aside .contact-cards { grid-template-columns: minmax(0, 1fr); gap: 16px; }
.adm .layout__aside .label + .link-list { margin-top: 14px; }
.adm .checklist--cols { display: grid; grid-template-columns: minmax(0, 1fr); column-gap: var(--gutter); }
@media (min-width: 640px) { .adm .checklist--cols { grid-template-columns: repeat(2, minmax(0, 1fr)); } .adm .checklist--cols li:nth-child(2) { border-top: var(--hairline); } }
.adm .tag-list + .label { margin-top: 24px; }
.adm-notice { max-width: 46rem; }
.adm .nb-card { background: var(--paper-3); }
.adm-reviewed { margin-top: 16px; }

/* ---- final review 2026-10-25 ----------------------------------------------------------------------------------------------------
   1. The "Prefer to call?" label inside a call band is the standard small sans label (the band's serif paragraph rule reached it).
   2. Enquire: under 1024 px the form comes first and the "Answers already on this site" list follows it (it pushed the form about
      one screen down on a phone); on a desktop it stays the aside.
   3. Visit: the crest frame in the 21:9 band sits on the crest, not on the middle of the door. */
.call-band__text p.label { font: 500 11.5px / 1.2 var(--font-sans); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); max-width: none; }
@media (max-width: 1023px) {
  .adm-form-layout--form-first .adm-form-layout__main { order: 1; }
  .adm-form-layout--form-first .adm-form-layout__side { order: 2; }
  .adm-form-layout--form-first .adm-form-layout__after { order: 3; }
}
@media (min-width: 768px) { .adm-plate--crest .adm-plate__wide img { object-position: 50% 8%; } }
/* 4. How to apply: the class cards have no line sidebar beside them (the lines are at the foot of the page), so the row takes
      the full band and the four cards stand in one row from 1200 px instead of a 2 x 2 block in the left two thirds. */
@media (min-width: 900px) {
  .adm-row:not(:has(> .adm-row__side)) > .adm-row__main { grid-column: 1 / -1; }
}
@media (min-width: 1200px) {
  .adm-row:not(:has(> .adm-row__side)) .adm-entries:not(:has(> [hidden])) { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .adm-row:not(:has(> .adm-row__side)) .adm-entries:has(> [hidden]) { max-width: 62%; }
}
/* 5. How to apply, the online-form card: its three steps as a short numbered list, so the card is not an empty box beside the
      taller PDF card */
.adm-panel__steps { list-style: decimal; padding-left: 1.3em; margin: 0 0 12px; }
.adm-panel__steps li + li { margin-top: 6px; }
.adm-panel__steps li::marker { color: var(--maroon); font-variant-numeric: tabular-nums; }

/* ---- additions/alumni-form.css ---- */
/* alumni-form: "Join the alumni community" on /community/alumni/ (2026-10-27). A paper card like the careers form
   (.cf); fields use main.css .field. Prefix alf (af belongs to the admission form). Tokens only; 44 px targets; no motion. */

.alf__intro { max-width: 46rem; margin-top: 14px; color: var(--ink-2); }
.alf {
  max-width: 52rem;
  padding: clamp(20px, 3vw, 40px);
  background: var(--paper-3);
  border: 1px solid var(--clay);
  border-radius: 6px;
}
/* the ticks: no fieldset border, one row of at least 44 px each, the box on the first line of its words
   (main.css gives every input inside .field min-height 48 px and full width) */
.alf__ticks { display: grid; gap: 12px; margin: 8px 0 18px; padding: 0; border: 0; min-width: 0; }
.alf__ticks legend { padding: 0; margin-bottom: 4px; }
.alf .alf__tick { display: block; margin: 0; }
.alf .alf__tick .choice { display: flex; flex-direction: row; align-items: flex-start; gap: 12px; min-height: 44px; font: 400 17px / 1.5 var(--font-serif); color: var(--ink); cursor: pointer; }
.alf .alf__tick .choice input { flex: none; width: 22px; height: 22px; min-height: 0; max-height: 22px; padding: 0; margin: 3px 0 0; border: 0; }
.alf .alf__tick .choice .link { color: var(--ink); }
.alf .alf__tick .field__error { margin: 4px 0 0 34px; }
.alf button[type="submit"][disabled] { opacity: 0.6; cursor: progress; }
.alf__status { margin-top: 14px; font: 500 15px / 1.45 var(--font-sans); color: var(--ink-2); }
.alf__status:empty { display: none; }
.alf__status--fail { color: var(--maroon); }
.alf__done { max-width: 52rem; margin-top: 24px; }
/* the telephone panel below the form: two lines, one shown at a time */
[data-alumni-when][hidden] { display: none; }
#alumni-online + .cc-panel { margin-top: clamp(24px, 3vw, 36px); }

/* ---- additions/careers-form.css ---- */
/* careers-form: "Apply online" on /about/careers/ (2026-10-23). The form sits on a paper card like the admission form;
   fields use main.css .field. Tokens only; 44 px targets; no motion. */

.cf__intro { max-width: 46rem; margin-top: 14px; color: var(--ink-2); }
.cf {
  max-width: 52rem;
  padding: clamp(20px, 3vw, 40px);
  background: var(--paper-3);
  border: 1px solid var(--clay);
  border-radius: 6px;
}
.cf__file input[type="file"] {
  display: block; width: 100%; min-height: 44px; padding: 8px 0;
  font: 400 15px / 1.4 var(--font-sans); color: var(--ink-2); background: transparent; border: 0;
}
.cf__file input[type="file"]::file-selector-button {
  min-height: 40px; margin-right: 12px; padding: 0 18px; border: 1px solid var(--ink); border-radius: 999px;
  background: transparent; font: 500 14px / 1 var(--font-sans); color: var(--ink); cursor: pointer;
}
.cf__file input[type="file"]::file-selector-button:hover { background: var(--ink); color: var(--paper); }
.cf__file input[type="file"]:focus-visible { outline: 2px solid var(--maroon); outline-offset: 2px; }
.cf button[type="submit"][disabled] { opacity: 0.6; cursor: progress; }
.cf__status { margin-top: 14px; font: 500 15px / 1.45 var(--font-sans); color: var(--ink-2); }
.cf__status:empty { display: none; }
.cf__status--fail { color: var(--maroon); }
.cf__done { max-width: 52rem; margin-top: 24px; }

/* ---- additions/community.css ---- */
/* community group: /community/parents/, /community/alumni/, /news/, /events/, /notices/, /gallery/ (2026-10-11).
   Components: empty note (.empty-note), filter group (.filter-group), news feed (.news-feed, .news-item), notice date and
   validity line (.row__day--text, .row__valid), photo album (.album). Each is documented in docs/additions/community.md.
   Tokens only; 44 px targets; the one transition (the arrow) is switched off by the reduced-motion rule at the end. */

/* ---- empty note (events, notices, news, alumni; 2026-10-11) ---------------------------------------------------------
   A calm statement where the school has not yet given the site anything to list. A label, a plain sentence, then what
   to do instead. It carries the same ink rule as .rows and .timeline, so it sits in the column like a list that has not
   been filled. Replace it with the real rows the day the school supplies them. */
.empty-note { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; padding: 22px 0 28px; border-top: 1px solid var(--ink); border-bottom: var(--hairline); }
.empty-note .label { display: block; margin-bottom: 12px; }
.empty-note__title { font: 400 clamp(24px, 2.3vw, 38px) / 1.12 var(--font-serif); letter-spacing: -0.006em; max-width: 24ch; text-wrap: balance; }
.empty-note__body > * + * { margin-top: 0.8em; }
.empty-note__body p { max-width: 58ch; font-size: 17.5px; line-height: 1.6; }
.empty-note__body .phones { margin-top: 18px; }
@media (min-width: 900px) {
  .empty-note { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); column-gap: var(--gutter); padding: 30px 0 36px; }
}

/* ---- filter group (news, notices; 2026-10-11) -----------------------------------------------------------------------
   A heading and its list inside a [data-filter-scope]. js/pages-additions.js hides the whole group, heading included,
   when the chips leave nothing in it, so a heading is never left over an empty list. */
.filter-group + .filter-group { margin-top: clamp(48px, 6vw, 88px); }
.filter-group__title { margin-bottom: 14px; }
.filter-group__more { margin-top: 22px; }

/* ---- news feed (news; 2026-10-11) ----------------------------------------------------------------------------------
   Event reports with a photograph: a rule, the picture, a dated kicker, a title and one plain sentence. The title's link
   is stretched over the card, as in .chapter-card and .row. The first card (--lead) is larger; --side and the plain
   cards fill a twelve-column row: 7 + 5, then 6 + 6. */
.news-feed { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(32px, 4vw, 56px) var(--gutter); }
.news-item { position: relative; display: flex; flex-direction: column; gap: 14px; padding-top: 16px; border-top: 1px solid var(--ink); scroll-margin-top: calc(var(--nav-h) + 24px); }
.news-item .plate { margin: 0; }
.news-item .plate img { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; object-position: var(--pos, 50% 50%); }
.news-item--lead .plate img { aspect-ratio: 16 / 9; }
.news-item__meta { display: flex; flex-wrap: wrap; gap: 4px 16px; font: 500 11.5px / 1.2 var(--font-sans); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.news-item__title { font: 400 clamp(26px, 2.2vw, 38px) / 1.08 var(--font-serif); letter-spacing: -0.005em; text-wrap: balance; }
.news-item--lead .news-item__title { font-size: clamp(32px, 3.4vw, 56px); }
.news-item__title a { color: inherit; text-decoration: none; transition: color var(--t-micro); }
.news-item__title a::after { content: ''; position: absolute; inset: 0; }
.news-item__title a:focus-visible { outline: none; }
.news-item__title a:focus-visible::after { outline: 2px solid var(--maroon); outline-offset: 4px; }
.news-item:hover .news-item__title a { color: var(--maroon); }
.news-item__text { max-width: 52ch; font-size: 17px; line-height: 1.55; color: var(--ink-2); }
.news-item__go { position: relative; display: block; flex: none; width: 36px; height: 1px; margin-top: auto; background: var(--ink); transition: width var(--t-hover) var(--ease-out), background var(--t-ui); }
.news-item__go::after { content: ''; position: absolute; right: 0; top: -3px; width: 7px; height: 7px; border-top: 1px solid currentColor; border-right: 1px solid currentColor; transform: rotate(45deg); color: var(--ink); }
.news-item:hover .news-item__go { width: 64px; background: var(--maroon); }
.news-item:hover .news-item__go::after { color: var(--maroon); }
@media (min-width: 640px) {
  .news-feed { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .news-item--lead { grid-column: 1 / -1; }
}
@media (min-width: 1024px) {
  .news-feed { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .news-item { grid-column: span 6; }
  .news-item--lead { grid-column: span 7; }
  .news-item--side { grid-column: span 5; }
  /* 7 + 5 columns: 19:10 against 4:3 gives the two pictures the same height, so the dates and titles below them line up (review, 2026-10-11) */
  .news-item--lead .plate img { aspect-ratio: 19 / 10; }
}

/* ---- notice date and validity line (notices, news; 2026-10-11) -------------------------------------------------------
   .row__day is a large number. A notice with no single day ("Standing", "2026 to 27") sets its word in a smaller size so it
   stays on one line beside the date column; .row__valid says in words what period the notice covers. */
.row__body { min-width: 0; }
.row__day--text { font-size: clamp(22px, 2vw, 30px); line-height: 1.1; letter-spacing: -0.005em; }
.row__valid { margin-top: 10px; font: 500 12.5px / 1.45 var(--font-sans); letter-spacing: 0.06em; color: var(--ink-2); }

/* ---- photo album (gallery; 2026-10-11) -------------------------------------------------------------------------------
   One event or one subject: a rule, the title and what it shows, then the .gallery grid with its own lightbox (the viewer
   steps through one album at a time). The chips show or hide whole albums. */
.album { scroll-margin-top: calc(var(--nav-h) + 24px); }
.album + .album { margin-top: clamp(48px, 6vw, 96px); }
.album__head { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px 32px; padding-top: 16px; margin-bottom: 24px; border-top: 1px solid var(--ink); }
.album__title { font: 400 clamp(28px, 2.8vw, 46px) / 1.08 var(--font-serif); letter-spacing: -0.006em; text-wrap: balance; }
.album__meta { margin-top: 10px; font: 500 11.5px / 1.2 var(--font-sans); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.album__note { max-width: 56ch; font-size: 17px; line-height: 1.55; color: var(--ink-2); }
@media (min-width: 900px) {
  .album__head { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); align-items: start; }
}

/* ---- album grid (gallery; review 2026-10-11) -------------------------------------------------------------------------
   The shared .gallery is a three-column masonry, which leaves ragged columns and gaps when the frames differ in shape. In an
   album the frames sit in an even grid instead: from 560 px every thumbnail is cut to 4:3 (the lightbox still shows the whole
   photograph); --pos on the item (a custom property, set in the page) says which part of a tall or wide frame to keep.
     .gallery__item--wide        spans two columns from 1024 px and the full row from 560 px; beside another frame it takes that
                                 frame's height, so the row stays level
     .gallery__item--tablet-wide the third frame of a three-frame album: the full row at 560 to 1023 px, an ordinary tile above
   Under 560 px each frame keeps its own proportions, one to a row. */
.album .gallery { columns: auto; display: grid; grid-template-columns: minmax(0, 1fr); gap: 28px var(--gutter); }
.album .gallery__item { margin: 0; min-width: 0; display: flex; flex-direction: column; break-inside: auto; }
.album .gallery__link { display: block; }
@media (min-width: 560px) {
  .album .gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .album .gallery__frame img { aspect-ratio: 4 / 3; object-fit: cover; object-position: var(--pos, 50% 50%); }
  .album .gallery__item--wide, .album .gallery__item--tablet-wide { grid-column: 1 / -1; }
  .album .gallery__item--wide .gallery__frame img { aspect-ratio: 2 / 1; }
  .album .gallery__item--tablet-wide .gallery__frame img { aspect-ratio: 2 / 1; }
}
@media (min-width: 1024px) {
  .album .gallery { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .album .gallery__item--tablet-wide { grid-column: auto; }
  .album .gallery__item--tablet-wide .gallery__frame img { aspect-ratio: 4 / 3; }
  .album .gallery__item--wide { grid-column: span 2; }
  .album .gallery__item--wide .gallery__link { flex: 1 1 0; min-height: 0; position: relative; }
  .album .gallery__item--wide .gallery__frame { position: absolute; inset: 8px; }
  .album .gallery__item--wide .gallery__frame img { position: absolute; inset: 0; width: 100%; height: 100%; aspect-ratio: auto; }
}

@media (prefers-reduced-motion: reduce) {
  .news-item__go, .news-item__title a { transition: none; }
}
html[data-motion="reduced"] .news-item__go, html[data-motion="reduced"] .news-item__title a { transition: none !important; }


/* ======================================================================================================================
   community-contact redesign, Parents and Alumni pieces (2026-10-24). The shared cc- kit (cc-head, cc-foot, cc-panel,
   cc-plate, cc-lines, cc-chips) lives in contact-legal.css; here are the pieces only these two pages use. Tokens only;
   44 px targets; the tile arrow is the one transition and stops under reduced motion (last block). */

/* ---- cc-tiles: Parents' four start-here tiles (2026-10-24) ----------------------------------------------------------------------
   Four doors a current parent opens most, 2 x 2 from 0 px so all four sit in one phone screen (the four stacked chapter cards
   ran about 1,400 px), four across from 1024 px. The whole tile is one link (the title's link stretched over it, as .chapter-card
   does). A tile that opens the school's current website carries the "current site" tag under its title. */
.cc-tiles { list-style: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.cc-tile { position: relative; display: flex; flex-direction: column; gap: 10px; min-height: 150px; min-width: 0; padding: 16px 14px 18px; background: var(--paper-3); border: 1px solid var(--clay); border-top: 3px solid var(--maroon); }
.cc-tile__n { display: block; }
.cc-tile__title { font: 400 clamp(19px, 1.9vw, 28px) / 1.1 var(--font-serif); letter-spacing: -0.005em; text-wrap: balance; transition: color var(--t-micro); }
.cc-tile__link { color: inherit; text-decoration: none; }
.cc-tile__link::after { content: ''; position: absolute; inset: 0; }
.cc-tile__link:focus-visible { outline: none; }
.cc-tile__link:focus-visible::after { outline: 2px solid var(--maroon); outline-offset: 4px; }
.cc-tile__link .link__site { display: block; width: fit-content; margin: 8px 0 0; }
.cc-tile__text { font-size: 15px; line-height: 1.45; color: var(--ink-2); max-width: 30ch; }
.cc-tile__go { position: relative; display: block; flex: none; width: 36px; height: 1px; margin-top: auto; background: var(--ink); transition: width var(--t-hover) var(--ease-out), background var(--t-ui); }
.cc-tile__go::after { content: ''; position: absolute; right: 0; top: -3px; width: 7px; height: 7px; border-top: 1px solid currentColor; border-right: 1px solid currentColor; transform: rotate(45deg); color: var(--ink); }
.cc-tile:hover .cc-tile__title { color: var(--maroon); }
.cc-tile:hover .cc-tile__go { width: 60px; background: var(--maroon); }
.cc-tile:hover .cc-tile__go::after { color: var(--maroon); }
.cc-tile__short { display: none; }
@media (max-width: 479px) {
  /* the smallest phones: each tile shows its own short line instead of the sentence (review r2, 2026-10-25: the two-line clamp of
     r1 cut sentences mid-phrase, which read as a rendering fault); the four tiles still sit in one phone screen */
  .cc-tile { min-height: 132px; gap: 8px; padding: 14px 12px 16px; }
  .cc-tile__text { font-size: 13.5px; line-height: 1.35; }
  .cc-tile__long { display: none; }
  .cc-tile__short { display: inline; }
}
@media (min-width: 720px) {
  .cc-tiles { gap: var(--gutter); }
  .cc-tile { min-height: 210px; padding: clamp(18px, 2vw, 28px); gap: 12px; }
  .cc-tile__text { font-size: 16.5px; }
}
@media (min-width: 1024px) {
  .cc-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ---- cc-notices: Parents' Notices-now sheet (review r1, 2026-10-24) ------------------------------------------------------------------
   The same nb-cards as /notices/, feed-synced; content.js adds nb-card--feature to a pinned notice, and main.css then spans it over
   both columns (the board's sticky nb-ask fills the space beside the second card on /notices/; here nothing would). On this page the
   cards sit as two equal columns, the feature card keeps the ordinary title size and fact grid, and every card action keeps the
   secondary (outlined) button, so a current-parent page does not end up with one filled admissions button as its only priority. */
.cc-notices .nb-card--feature { grid-column: auto; }
.cc-notices .nb-card--feature .nb-card__title { font-size: clamp(22px, 2vw, 30px); max-width: none; }
.cc-notices .nb-card--feature .nb-fact { grid-template-columns: minmax(0, 1fr); gap: 4px; align-items: start; }
.cc-notices .nb-card .btn { background: transparent; color: var(--ink); border: 1px solid var(--ink); box-shadow: none; }
.cc-notices .nb-card .btn:hover, .cc-notices .nb-card .btn:focus-visible { color: var(--maroon); border-color: var(--maroon); background: transparent; }
.cc-notices .nb-card .btn::after { content: none; }
/* phones (review r2, 2026-10-25): each card shows its tile, chips, title and one action; the For / What to do / When facts and the
   source line are left to the Notices page, which the card's action and the sheet's "All notices" open. Two full cards ran about
   1,750 px before the accounts a parent came for. */
@media (max-width: 639px) {
  .cc-notices .nb-card__facts, .cc-notices .nb-card__source { display: none; }
}

/* ---- cc-callrow: Parents' phone sheet (review r2, 2026-10-25) ------------------------------------------------------------------
   The phone list on 7 columns and the Book Fair plate (moved from the day-to-day aside) on the right 4, so the row is not half
   empty at 1366 px; one column on phones, the plate after the numbers, with its caption. */
.cc-callrow { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(32px, 4vw, 56px) var(--gutter); align-items: start; }
.cc-callrow .plate { margin: 0; }
@media (min-width: 1024px) {
  .cc-callrow { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .cc-callrow .cc-lines { grid-column: 1 / span 7; }
  .cc-callrow__plate { grid-column: 9 / -1; }
}

/* ---- cc-faq: Parents' day-to-day sheet (2026-10-24) -----------------------------------------------------------------------------
   Written in phone order: the safeguarding statement (.venue) first, then the jump chips and the grouped questions, then the
   plate and the document links. From 1024 px the questions take 8 columns over two rows and the statement and the aside sit
   on the right, so the reading order and the focus order are the DOM order at every width (WCAG 1.3.2, 2.4.3; no CSS order). */
.cc-faq { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(32px, 4vw, 56px) var(--gutter); align-items: start; }
.cc-faq__worried .venue { max-width: none; }
.cc-faq__main .chips { margin-bottom: 12px; }
.cc-faq__main .accordion__controls { margin-top: 8px; }
.cc-faq__aside > * + * { margin-top: 28px; }
.cc-faq__aside .plate { margin: 0; }
@media (min-width: 1024px) {
  .cc-faq { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .cc-faq__main { grid-column: 1 / span 7; grid-row: 1 / span 2; }
  .cc-faq__worried { grid-column: 9 / -1; grid-row: 1; }
  .cc-faq__aside { grid-column: 9 / -1; grid-row: 2; }
}

/* ---- cc-aside-first: the checklist before the form (Alumni, Register; 2026-10-24) -------------------------------------------
   Replaces .layout--aside-first (2026-10-11), which moved the aside with CSS order. The aside is now first in the DOM (the phone
   order); from 1024 px both columns are pinned to the same grid row, so .layout's column rules place them side by side. */
@media (min-width: 1024px) {
  .cc-aside-first .layout__aside, .cc-aside-first .layout__main { grid-row: 1; }
}

/* ---- cc-years: Alumni's four graduation albums (2026-10-24) -------------------------------------------------------------------
   The home's .ev-grid photo cards, one per year, each card the link to that year's album: a stack on phones (the home's
   snapping row would hide the fourth card), 2 x 2 from 640 px, four across from 1200 px. */
.cc-years .ev-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(28px, 3.5vw, 48px) var(--gutter); margin-inline: 0; padding: 0; overflow: visible; }
.cc-years .ev, .cc-years .ev:first-child { grid-column: auto; flex: none; }
.cc-years .ev__media img { aspect-ratio: 16 / 9; object-position: 50% 50%; }
.cc-years .ev__name { font-size: clamp(22px, 1.7vw, 30px); }
.cc-years .ev__card:focus-visible { outline: 2px solid var(--maroon); }
/* phones (review r2, 2026-10-25): 2 x 2 from 0 px, as from 640 px, so four tall pictures do not run 1,900 px in a row; the
   pictures are for looking, and the year label stays on one line; the card text gives way to the name */
@media (max-width: 639px) {
  .cc-years .ev-grid { gap: 24px 12px; }
  .cc-years .ev__name { font-size: 19px; }
  .cc-years .ev__text { display: none; }
  .cc-years .ev__n { white-space: nowrap; }
}
@media (min-width: 1200px) {
  .cc-years .ev-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ---- cc-dates: Alumni's night timeline with its sticky plate (2026-10-24; review r1 the same day) -----------------------------------
   Phone order: the plate under the lead, then the timeline. From 1024 px the timeline takes 7 columns and the plate column on the
   right stretches to the timeline's height: the plate sticks at the top as the reader scrolls, and .cc-dates__more (two in-page
   links) sits at the foot of the column, so the column is not empty paper under a short plate in a full-page view.
   Review r2 (2026-10-25): the plate is a 4:5 cut at the full width of a five-column right column (about 440 px), the two links
   sit directly under it, and the plate and the links stick together, so the dark sheet is not half empty. */
.cc-dates { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(32px, 4vw, 56px) var(--gutter); align-items: start; }
.cc-dates__plate { display: flex; flex-direction: column; gap: 28px; }
.cc-dates__plate .plate { margin: 0; }
.cc-dates__more .label { display: block; margin-bottom: 14px; }
.cc-dates__more .link-list { gap: 16px; }
.is-night .cc-dates__more .link { color: var(--paper); }
@media (max-width: 1023px) {
  .cc-dates__more { display: none; }   /* on a phone the two sheets it points to are one scroll away; the plate alone follows the lead */
}
@media (min-width: 1024px) {
  .cc-dates { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .cc-dates__list { grid-column: 1 / span 6; grid-row: 1; }
  .cc-dates__plate { grid-column: 8 / -1; grid-row: 1; align-self: start; position: sticky; top: calc(var(--nav-h) + 24px); }
}

@media (prefers-reduced-motion: reduce) {
  .cc-tile__go, .cc-tile__title { transition: none; }
}
html[data-motion="reduced"] .cc-tile__go, html[data-motion="reduced"] .cc-tile__title { transition: none !important; }

/* ---- additions/contact-legal.css ---- */
/* contact-legal: /contact/, /privacy/, /terms/ (2026-10-11), and since 2026-10-24 the cc- kit shared by the seven pages of the
   community-contact redesign (/community/parents/, /community/alumni/, /contact/, /privacy/, /terms/, /search/, /404/; each
   carries body_class: cc-page). The old night call sheet (.contact-lines, 2026-10-11) was retired on 2026-10-24: the numbers
   moved onto paper as .cc-lines (below), so /contact/ has one dark block, the Find-the-school sheet, like the home's find-us panel. */

/* .form-notice__text: the first line of the prototype notice, which COMPONENTS.md documents and the form script fills
   (the stylesheet had no rule for the class); and room above the quiet closing line (2026-10-11) */
.form-notice__text { margin: 0; }
.form-notice .small-print { margin-top: 14px; }

/* .legal-table: a stacked table (table--stack) on /contact/ and /privacy/. Under 640 px pages.css turns the table into a
   block, and its <caption> then collapses to the width of its longest word and runs down the page one word to a line;
   the caption is made a block of its own. (2026-10-11) */
@media (max-width: 639px) {
  .legal-table caption { display: block; width: 100%; }
}

/* the night fact strip: the small line under a fact is the quiet cream of the night ground, not the paper-ground grey
   (pages.css leaves it at --ink-2, which disappears on --night). Used on /privacy/. (2026-10-11) */
.is-night .fact dd small { color: var(--bone-dim); }

/* touch targets (review, 2026-10-11): a link that stands alone in a table cell, a definition or a callout keeps its look and
   gets the invisible 44 px hit area the footer and the where-next columns have (pages.css only gives it to those lists).
   Used on /contact/ (the "Read first" column, the Find-the-school rows and the sticky note) and /privacy/ (the table). */
.legal-table td a, .contact-find dd a, .legal-more a { position: relative; }
.legal-table td a::before, .contact-find dd a::before, .legal-more a::before { content: ''; position: absolute; inset: -8px -4px; }
.contact-find dd a::before, .legal-more a::before { inset: -10px -4px; }

/* .legal-chapter: a chapter of a long legal page (/privacy/) sets its heading one step below the home's section title, so
   seven chapters in a row read as chapters of one document and not as seven competing headlines. (2026-10-11 review) */
.legal-chapter .section-title { font-size: clamp(30px, 3.1vw, 46px); line-height: 1.1; }


/* ======================================================================================================================
   cc- kit (community-contact group, 2026-10-24). The home's sheet grammar at page scale, from research/design-language.md
   section 3: a head grid, a foot row, a top-ruled panel, a mounted opening plate, the phone list set large, and the small
   page pieces (Contact's first screen and drawn map, Search's suggestions and empty state, the 404 brick mark). Tokens only;
   44 px targets; every motion stops under prefers-reduced-motion and the footer switch (the last block). When the Foundation's
   0-kit ships pk-head / pk-foot / pk-panel / pk-plate, each cc- piece below is replaced by its pk- twin and deleted here. */

/* ---- cc-page: the scope hook every page of the group carries (body_class) ---------------------------------------------------
   One custom property, so the group's panels and tiles share their default edge colour; the class also lets a later rule target
   these seven pages without touching the others. */
.cc-page { --cc-edge: var(--maroon); }

/* ---- cc-head: the sheet head (every content sheet; 2026-10-24) -------------------------------------------------------------
   The home's .results__head: the H2 (display-l) on 10 of 12 columns at 18ch, the lead on 7 columns at 54ch. One column on phones. */
.cc-head { display: grid; grid-template-columns: minmax(0, 1fr); row-gap: clamp(20px, 2.6vw, 36px); margin-bottom: clamp(36px, 4.5vw, 64px); }
.cc-head__title { max-width: 18ch; text-wrap: balance; }
.cc-head .lead { max-width: 54ch; }
.cc-head .lead a { color: inherit; }
@media (min-width: 1024px) {
  .cc-head { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); }
  .cc-head__title { grid-column: 1 / span 10; }
  .cc-head .lead { grid-column: 1 / span 7; }
}
/* the H2 rises through a mask as the home's headlines do (one block, not line by line: no GSAP on the inner pages). The
   heading keeps its box and hides its overflow; the inner .cc-head__line starts below the box and rises when the reveal script
   adds .is-in. (A clip-path on the heading itself was tried first: Chrome counts a fully clipped box as not intersecting, so the
   IntersectionObserver never revealed it.) Without JavaScript, with reduced motion and in print the title is simply there. */
.cc-head__title { overflow: hidden; padding: 0.12em 0 0.18em; margin: -0.12em 0 -0.18em; }
.cc-head__line { display: block; }
html.js-reveal .cc-head__title[data-reveal], html.js-reveal .cc-head__title[data-reveal]:not(.is-in) { opacity: 1; transform: none; transition: none; }
html.js-reveal .cc-head__title[data-reveal] .cc-head__line { transition: transform var(--t-mask) var(--ease-mask); }
html.js-reveal .cc-head__title[data-reveal]:not(.is-in) .cc-head__line { transform: translateY(115%); }

/* ---- cc-foot: the sheet foot (the end of every fact-heavy sheet; 2026-10-24) -----------------------------------------------
   The home's .top-events__foot: a hairline, a plain sentence on 8 columns, the one action end-aligned on the right, and the
   source line (where the sheet's facts come from) as a caption under both. Sources move out of comments onto the page. */
.cc-foot { display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px var(--gutter); margin-top: clamp(36px, 4.5vw, 64px); padding-top: 22px; border-top: var(--hairline); }
.cc-foot__text { font-size: 18px; line-height: 1.55; max-width: 62ch; }
.cc-foot__text a { color: inherit; }
.cc-foot__action { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; }
.cc-foot__source { grid-column: 1 / -1; }
/* the one action gets the invisible 44 px hit area every shared link has (review r2, 2026-10-25: the links measured 36 px) */
.cc-foot__action .link { position: relative; }
.cc-foot__action .link::before { content: ''; position: absolute; inset: -4px; }
@media (min-width: 900px) {
  .cc-foot { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .cc-foot__text { grid-column: 1 / span 8; }
  .cc-foot__action { grid-column: 10 / -1; justify-content: flex-end; }
}
.is-night .cc-foot { border-top-color: var(--night-line); }
.is-night .cc-foot__text { color: var(--paper); }
.is-night .cc-foot__source { color: var(--bone-dim); }

/* ---- cc-panel: a top-ruled panel (the accounts on Parents, the three ways to write on Contact, Your choices on Privacy,
   Ask the school on Terms, the old addresses on 404; 2026-10-24) ---------------------------------------------------------
   The home's .result recipe as a general panel: paper-3, a 1 px clay border, a 3 px coloured top rule (maroon; --gold and
   --ink variants), a head on a hairline (serif name, label right), a body, one action at the foot. */
.cc-panel { --cc-edge: var(--maroon); position: relative; display: flex; flex-direction: column; gap: 18px; min-width: 0; padding: clamp(22px, 2.2vw, 34px); background: var(--paper-3); border: 1px solid var(--clay); border-top: 3px solid var(--cc-edge); }
.cc-panel--gold { --cc-edge: var(--gold); }
.cc-panel--ink { --cc-edge: var(--ink); }
.cc-panel__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 10px 20px; padding-bottom: 14px; border-bottom: var(--hairline); }
.cc-panel__name { font: 400 clamp(24px, 2vw, 34px) / 1.08 var(--font-serif); letter-spacing: -0.005em; text-wrap: balance; }
.cc-panel__body > * + * { margin-top: 0.85em; }
.cc-panel__body p:not(.label) { font-size: 17px; line-height: 1.55; max-width: 58ch; }
.cc-panel__body .label { display: block; margin-top: 1.2em; }
.cc-panel__body .label + .tag-list { margin-top: 8px; }
.cc-panel__body .tag-list { font-size: 16.5px; }
.cc-panel__body .small-print { max-width: 58ch; }
.cc-panel .dl { border-top: 0; }
.cc-panel .dl dd { font-size: 17px; max-width: none; }
.cc-panel .dl dd a { position: relative; }
.cc-panel .dl dd a::before { content: ''; position: absolute; inset: -10px -4px; }
.cc-panel__tel { margin: 0; }
.cc-panel__action { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; margin-top: auto; padding-top: 4px; }
.cc-panel__action .link { position: relative; }
.cc-panel__action .link::before { content: ''; position: absolute; inset: -10px -4px; }
.page-section--tint .cc-panel, .is-night .cc-panel { background: var(--paper-3); }
.cc-panels { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); align-items: stretch; }
/* a pair of panels of unequal length (Parents' portal and fees) starts at the top and keeps its own height, so the shorter one does
   not end in blank paper (review r1, 2026-10-24); a row of three equal panels (Contact) still stretches so its buttons line up */
.cc-panels--2 { align-items: start; }
@media (min-width: 720px) {
  .cc-panels--2, .cc-panels--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .cc-panels--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ---- cc-opening and cc-plate: the mounted opening plate (Parents, Alumni; 2026-10-24) ----------------------------------------
   The page's first photograph on a paper mount inside the band, directly under the type hero (no bare bleed plate, no text on
   the picture). .cc-plate--switch holds two crops of one frame: the wide one from 720 px, the tall one on phones. Both pictures
   are lazy, so the hidden one is not fetched. The curtain comes from figure.plate[data-reveal] in pages.css. */
.cc-opening { padding-top: 0; }
.cc-plate { margin: 0; }
.cc-plate .plate__frame img { display: block; width: 100%; height: auto; }
.cc-plate__tall { display: none; }
@media (max-width: 719px) {
  .cc-plate--switch .cc-plate__wide { display: none; }
  .cc-plate--switch .cc-plate__tall { display: block; }
  .cc-plate--switch .cc-plate__tall img { aspect-ratio: 4 / 5; object-fit: cover; }
}
/* cc-split: the opening plate beside the first statement (Alumni): the photograph on 7 columns, the words on 5 */
.cc-split { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 4vw, 56px) var(--gutter); align-items: start; }
.cc-split .plate { margin: 0; }
.cc-split__text > * + * { margin-top: clamp(24px, 3vw, 40px); }
.cc-split__text .venue { max-width: none; }
@media (min-width: 900px) {
  .cc-split { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .cc-split__figure { grid-column: 1 / span 7; }
  .cc-split__text { grid-column: 8 / -1; }
}

/* ---- cc-lines: the phone list set large on paper (Contact's first screen, Parents' phone sheet; 2026-10-24) ----------------
   {{phones:all}} as it is, restyled: the section as a tracked label, the number in Newsreader 300 at 30 to 44 px on a gold
   hairline, every number a 44 px tel: target. One column under 640 px, label left and number right above it. The old night
   version (.contact-lines, 2026-10-11) is retired; the night rules stay for a future dark sheet. */
.cc-lines .phones { margin-top: 0; max-width: 820px; border-top: 1px solid var(--ink); }
.cc-lines .phones__row { max-width: none; flex-direction: column; align-items: flex-start; gap: 2px; padding: 16px 0 18px; border-bottom: var(--hairline); }
.cc-lines .phones__who { font: 500 12.5px / 1.3 var(--font-sans); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); }
.cc-lines .phones a { display: inline-block; padding: 6px 0 10px; color: var(--maroon); font: 300 clamp(30px, 2.8vw, 44px) / 1.1 var(--font-serif); font-variant-numeric: tabular-nums lining-nums; letter-spacing: -0.005em; background-image: linear-gradient(var(--gold), var(--gold)); background-position: 0 calc(100% - 6px); }
.cc-lines .phones__nums { align-items: flex-start; gap: 8px; }
.cc-lines .phones a:focus-visible { outline: 2px solid var(--maroon); outline-offset: 3px; }
@media (min-width: 640px) {
  .cc-lines .phones__row { flex-direction: row; align-items: baseline; justify-content: space-between; gap: 16px 32px; }
  .cc-lines .phones__nums { align-items: flex-end; }
}
.is-night .cc-lines .phones { border-top-color: var(--paper); }
.is-night .cc-lines .phones__row { border-bottom-color: var(--night-line); }
.is-night .cc-lines .phones__who { color: var(--gold-text); }
.is-night .cc-lines .phones a { color: var(--paper); background-image: linear-gradient(var(--gold-text), var(--gold-text)); }
.is-night .cc-lines .phones a:focus-visible { outline-color: var(--amber); }
.cc-lines .venue { margin-top: clamp(24px, 3vw, 40px); max-width: none; }

/* ---- cc-first: Contact's first screen (2026-10-24) ----------------------------------------------------------------------------
   Everything a parent came for, in one screen: the four lines set large on 7 columns; on the right the crest at the gate on a
   4:5 mount, the address, the map link and the one primary button. Written in phone order (lines, hours, plate, address, button). */
.cc-first { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(32px, 4vw, 56px) var(--gutter); align-items: start; }
.cc-first__side { display: grid; gap: 22px; align-content: start; }
.cc-first__side .plate { margin: 0; }
.cc-first__side .dl dd { max-width: none; }
.cc-first__side .dl dd a { position: relative; }
.cc-first__side .dl dd a::before { content: ''; position: absolute; inset: -10px -4px; }
.cc-first__side .btn { justify-self: start; }
@media (min-width: 560px) and (max-width: 899px) {
  .cc-first__side { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); column-gap: var(--gutter); align-items: start; }
  .cc-first__side .plate { grid-row: 1 / span 2; }
  .cc-first__side .btn { grid-column: 2; }
}
@media (min-width: 900px) {
  .cc-first { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .cc-first__lines { grid-column: 1 / span 7; }
  .cc-first__side { grid-column: 9 / -1; }
}

/* ---- cc-find and cc-map: Contact's dark find-us sheet with the drawn map (2026-10-24) -------------------------------------------
   The map is an inline SVG drawn by Defined Solution from the address in nav.json: the block, the road the school stands on
   and the pin, and the words "Not to scale". No north arrow, no scale bar, no landmarks (none is published: CONFIRM on the page),
   nothing loaded from Google; the one-tap Google Maps link sits under it. The SVG takes its colours from the classes below, so
   it prints and sits on the paper mount like the photographs do. */
.cc-find { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(32px, 4vw, 56px) var(--gutter); align-items: start; }
.cc-find__map .plate { margin: 0; max-width: 560px; }
.cc-find__map .dl { margin-top: 22px; max-width: 560px; }
.cc-find .dl { border-top-color: var(--paper); }
.cc-find .dl dt { color: var(--gold-text); }
.cc-find .dl dd { color: var(--paper); max-width: none; }
.cc-find .dl dd a { position: relative; }
.cc-find .dl dd a::before { content: ''; position: absolute; inset: -10px -4px; }
@media (min-width: 900px) {
  .cc-find { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .cc-find__map { grid-column: 1 / span 6; }
  .cc-find__rows { grid-column: 8 / -1; }
}
.cc-map svg { display: block; width: 100%; height: auto; }
.cc-map__ground { fill: var(--paper); }
.cc-map__block { fill: var(--paper-2); stroke: var(--clay); stroke-width: 1.5; }
.cc-map__road { fill: none; stroke: var(--clay); stroke-width: 10; stroke-linecap: round; }
.cc-map__road--main { stroke: var(--ink-2); stroke-width: 3; }
.cc-map__pin { fill: var(--maroon); }
.cc-map__pin-dot { fill: var(--paper-3); }
.cc-map__text { font: 500 12px / 1 var(--font-sans); letter-spacing: 0.14em; text-transform: uppercase; fill: var(--ink-2); }
.cc-map__text--name { font: 400 19px / 1 var(--font-serif); letter-spacing: 0; text-transform: none; fill: var(--ink); }
/* review r1 (2026-10-24): texture and a readable label. Lanes inside the blocks (thin clay, unnamed), the school's own plot (a maroon
   tint under a diagonal hatch), the name and house number on a small paper label above the road with a short leader to the pin,
   and the road and block named from the address. */
.cc-map__lane { fill: none; stroke: var(--clay); stroke-width: 3; stroke-linecap: round; opacity: 0.75; }
.cc-map__plot { fill: var(--maroon); fill-opacity: 0.1; stroke: var(--maroon); stroke-width: 1.5; }
.cc-map__plot-hatch { stroke: none; }
.cc-map__hatch { stroke: var(--maroon); stroke-width: 1; opacity: 0.5; }
.cc-map__label { fill: var(--paper-3); stroke: var(--clay); stroke-width: 1; }
.cc-map__leader { fill: none; stroke: var(--ink-2); stroke-width: 2.5; }
/* review r2 (2026-10-25): every map word sits on a thin paper halo, so a label that crosses a lane stays readable; the label is lifted
   6 units clear of the road and "Not to scale" sits inside the frame with BLOCK J. On phones the SVG scales to about 317 px, so the
   words are set larger in viewBox units (about 11 px and 14 px on screen) and the label widens to hold the name. "Not to scale"
   stays inside the frame on phones too, a size smaller so it clears BLOCK J (round-2 fixes, 2026-10-25: the build strips every
   plate caption, founder decision 2026-10-18, so the caption cannot carry it). */
.cc-map__text { paint-order: stroke; stroke: var(--paper); stroke-width: 4px; stroke-linejoin: round; }
.cc-map__text--name { stroke: var(--paper-3); }
.cc-map__text--house { stroke: var(--paper-3); }
@media (max-width: 639px) {
  .cc-map__text { font-size: 20px; letter-spacing: 0.1em; }
  .cc-map__text--name { font-size: 24px; letter-spacing: 0; transform: translate(-18px, -14px); }
  .cc-map__text--house { transform: translate(-18px, 0); }
  .cc-map__text--scale { font-size: 16px; letter-spacing: 0.08em; }
  /* final review 2026-10-25: the label and ROAD 19 ran into the right edge of the block at 390 px; both now end inside it */
  .cc-map__label { x: 280px; y: 100px; width: 212px; height: 76px; }
  .cc-map__text--road { transform: translate(-14px, 0); }
  .cc-map__leader { stroke-width: 4; }
}

/* ---- cc-chips: chips that are links (Parents' jump row, Search's suggestions; 2026-10-24) -----------------------------------------
   The .chip look of pages.css on an <a>: 44 px tall, inline-flex so the label centres, no underline, maroon on hover. */
.cc-chips a.chip { display: inline-flex; align-items: center; min-height: 44px; color: var(--ink); text-decoration: none; }
.cc-chips a.chip:hover, .cc-chips a.chip:focus-visible { border-color: var(--ink-2); color: var(--maroon); }
.cc-chips a.chip:focus-visible { outline: 2px solid var(--maroon); outline-offset: 2px; }
.cc-chips--after { margin-top: 22px; }

/* ---- cc-empty: Search's empty state (2026-10-24) ---------------------------------------------------------------------------------
   Shown while the box is empty or nothing matched; contact-legal.js sets hidden as soon as there are results. The empty note on
   7 columns, the "no result? call" line and the phone list on the right. */
.cc-empty { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 3.5vw, 48px) var(--gutter); align-items: start; }
.cc-empty[hidden] { display: none; }
.cc-empty .empty-note { grid-template-columns: minmax(0, 1fr); }
.cc-empty__start, .cc-empty__none { display: inline; }
.cc-empty__start[hidden], .cc-empty__none[hidden] { display: none; }
.cc-empty .link-list { margin-top: 18px; }
.cc-empty__call .venue { max-width: none; }
.cc-empty__call .phones { margin-top: 22px; }
/* the results list's top rule is drawn only when there are results: empty, it was a dark hairline under the chips with nothing
   beneath it (review r1, 2026-10-24) */
.cc-page .search-results:empty { border-top: 0; margin-top: 0; }
@media (min-width: 900px) {
  .cc-empty { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .cc-empty__note { grid-column: 1 / span 7; }
  .cc-empty__call { grid-column: 9 / -1; }
}

/* ---- cc-mark: the 404's brick band above its H2 (2026-10-24; review r1 the same day) -------------------------------------------------
   A 3:1 band of brick on a paper mount above the heading: the full width of the column on phones, 480 px from 1024 px. (The first
   version was a 1:1 swatch at 112 to 200 px beside the heading, which read as an orphan thumbnail.) */
.cc-mark { display: flex; flex-direction: column; align-items: flex-start; gap: clamp(24px, 3vw, 36px); }
.cc-mark .plate { width: 100%; max-width: none; margin: 0; }
.cc-mark .plate img { width: 100%; height: auto; aspect-ratio: 3 / 1; object-fit: cover; }
.cc-mark .section-title { max-width: 16ch; }
.cc-mark + * { margin-top: clamp(24px, 3vw, 40px); }
/* review r2 (2026-10-25): from 1024 px the band is as wide as the search box under it (40rem, the shared .search-form measure), so
   the two share one left edge and one width instead of a 480 px orphan beside empty paper */
@media (min-width: 1024px) {
  .cc-mark .plate { width: 100%; max-width: 40rem; }
}

/* ---- legal-chapter run-in labels (/privacy/ "Your visit code"; review r2, 2026-10-25) ----------------------------------------------
   The shipped Newsreader covers weights 300 to 400, so <strong> (500) showed as plain text and the chapter read as eight equal
   paragraphs. Each label is set as a small sans run-in heading instead (the font-weight gap itself is a Foundation item). */
.legal-chapter .prose strong { font: 600 0.8em / 1.3 var(--font-sans); letter-spacing: 0.05em; text-transform: uppercase; color: var(--ink-2); margin-right: 0.4em; }

/* ---- legal-code: a storage note's code name under its plain name (/privacy/ table; 2026-10-24) ------------------------------------- */
.legal-code { display: block; margin-top: 4px; font: 400 12.5px / 1.3 var(--font-sans); letter-spacing: 0.02em; color: var(--ink-2); }

/* ---- motion off: the H2 mask stands still (2026-10-24) -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .cc-head__line { transform: none !important; transition: none !important; }
  .cc-chips a.chip { transition: none; }
}
html[data-motion="reduced"] .cc-head__line { transform: none !important; transition: none !important; }

/* Final review 2026-10-25: a code or a telephone number never breaks across two lines on a phone (the privacy page broke
   "V-7K3Q9M" after the hyphen and the further-queries number between its groups) */
.legal-nowrap, body.cc-page .story-chapter a[href^="tel:"], body.cc-page .dl__row a[href^="tel:"] { white-space: nowrap; overflow-wrap: normal; }

/* ---- additions/events.css ---- */
/* events group (/events/ and the fifteen /events/<slug>/ pages): extra rules.
   Prefix: .ev-. Tokens only. Written 2026-10-18, group "events" (pages redesign). */

/* all inner pages, 2026-10-18: photographs carry no name caption any more (media.strip_captions). The lightbox still
   draws its caption element; with no text it must not leave a gap under the picture. */
.dialog__cap:empty { display: none; }

/* /events/, featured events, 2026-10-18: five cards, the whole card one link. Phones: one column. Tablet: two. From
   1100 px a six-column grid: the first card takes four columns and two rows of height, the rest two columns each. */
.ev-feature { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 3vw, 40px) var(--gutter); }
.ev-card { position: relative; display: flex; flex-direction: column; }
.ev-card__frame { position: relative; overflow: hidden; aspect-ratio: 4 / 3; padding: 10px; background: var(--paper-3); border: 1px solid var(--clay); }
.ev-card__frame picture, .ev-card__frame img { display: block; width: 100%; height: 100%; }
.ev-card__frame img { object-fit: cover; transition: transform var(--t-reveal) var(--ease-out); }
.ev-card__meta { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-top: 16px; font: 500 11.5px / 1.3 var(--font-sans); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); }
.ev-card__title { margin-top: 10px; font: 400 clamp(26px, 2.3vw, 38px) / 1.08 var(--font-serif); letter-spacing: -0.005em; }
.ev-card__link { color: inherit; text-decoration: none; transition: color var(--t-micro); }
.ev-card__link::after { content: ''; position: absolute; inset: 0; }
.ev-card__link:focus-visible { outline: none; }
.ev-card__link:focus-visible::after { outline: 2px solid var(--maroon); outline-offset: 4px; }
.ev-card__text { margin-top: 8px; max-width: 42ch; font-size: 17px; line-height: 1.5; color: var(--ink-2); }
.ev-card__go { display: block; position: relative; width: 40px; height: 1px; margin-top: 18px; background: var(--ink); transition: width var(--t-hover) var(--ease-out), background-color var(--t-micro); }
.ev-card__go::after { content: ''; position: absolute; right: 0; top: -4px; width: 8px; height: 8px; border-top: 1px solid currentColor; border-right: 1px solid currentColor; transform: rotate(45deg); color: var(--ink); }
.ev-card:hover .ev-card__link, .ev-card:focus-within .ev-card__link { color: var(--maroon); }
.ev-card:hover .ev-card__go { width: 64px; background: var(--maroon); }
.ev-card:hover .ev-card__go::after { color: var(--maroon); }
.ev-card:hover .ev-card__frame img { transform: scale(1.03); }
@media (min-width: 640px) { .ev-feature { grid-template-columns: repeat(2, minmax(0, 1fr)); } .ev-card--lead { grid-column: 1 / -1; } .ev-card--lead .ev-card__frame { aspect-ratio: 2 / 1; } }
@media (min-width: 1100px) {
  .ev-feature { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .ev-card { grid-column: span 2; }
  .ev-card--lead { grid-column: span 4; grid-row: span 2; }
  .ev-card--lead .ev-card__frame { aspect-ratio: auto; flex: 1 1 auto; min-height: 420px; }
  .ev-card--lead .ev-card__title { font-size: clamp(34px, 3vw, 52px); }
  .ev-card:nth-child(n+4) { grid-column: span 3; }
  .ev-card:nth-child(n+4) .ev-card__frame { aspect-ratio: 16 / 9; }
}
/* inside a card the typographic plate's word is set smaller, and never broken mid-word */
.ev-card__frame .ev-type__word { font-size: clamp(32px, 3vw, 46px); overflow-wrap: normal; }

/* the typographic plate, 2026-10-18: an event with no photograph we may show gets its name (or its date) set large on a
   maroon field inside the paper mount, with a gold hairline frame. No photograph is faked. Decorative: aria-hidden,
   because the same words are in the heading next to it. Used inside .ev-card__frame and as .ev-mark on an event page. */
.ev-type { position: relative; display: flex; flex-direction: column; justify-content: space-between; width: 100%; height: 100%; min-height: 200px; padding: clamp(18px, 2.4vw, 32px); background: var(--maroon); color: var(--paper); }
.ev-type::before { content: ''; position: absolute; inset: 8px; border: 1px solid var(--gold-text); opacity: 0.55; pointer-events: none; }
.ev-type__kicker { position: relative; font: 500 11.5px / 1.3 var(--font-sans); letter-spacing: 0.16em; text-transform: uppercase; color: var(--paper); }
.ev-type__word { position: relative; margin-top: 24px; font: italic 300 clamp(40px, 5.2vw, 84px) / 0.98 var(--font-serif); letter-spacing: -0.015em; color: var(--paper); overflow-wrap: anywhere; }
.ev-type__word small { display: block; margin-top: 10px; font: inherit; font-size: 0.42em; letter-spacing: 0; color: var(--gold-text); }
.ev-type__rule { position: relative; display: block; width: 56px; height: 1px; margin-top: 22px; background: var(--gold-text); }

/* an event page's own typographic plate, 2026-10-18: the band-wide version of .ev-type, on the paper mount */
.ev-mark { padding: 12px; background: var(--paper-3); border: 1px solid var(--clay); }
.ev-mark .ev-type { min-height: clamp(220px, 30vw, 440px); }
.ev-mark .ev-type__word { font-size: clamp(48px, 8vw, 132px); }

/* /events/, the index of every event, 2026-10-18: .rows with a "when" column that holds a fixed date or "Each year" */
.ev-when { font-variant-numeric: tabular-nums; }
.ev-when__yearly { font: italic 400 clamp(19px, 1.5vw, 22px) / 1.2 var(--font-serif); letter-spacing: 0; text-transform: none; color: var(--ink-2); }

/* an event page, photographs, 2026-10-18: two or three plates side by side, no captions */
.ev-photos { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); }
.ev-photos .plate__frame { aspect-ratio: 3 / 2; }
.ev-photos .plate__frame picture, .ev-photos .plate__frame img { display: block; width: 100%; height: 100%; object-fit: cover; }
@media (min-width: 640px) { .ev-photos { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .ev-photos--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* an event page, the portrait figure beside the text (the Cultural Programme's 4:5 frame), capped so it never fills a phone */
.ev-figure--tall { max-width: 26rem; }

/* an event page, the back link above the pager */
.ev-back { margin-bottom: clamp(20px, 2.6vw, 32px); }

@media (prefers-reduced-motion: reduce) {
  .ev-card__frame img, .ev-card__go { transition: none; }
  .ev-card:hover .ev-card__frame img { transform: none; }
}
html[data-motion="reduced"] .ev-card__frame img, html[data-motion="reduced"] .ev-card__go { transition: none; }
html[data-motion="reduced"] .ev-card:hover .ev-card__frame img { transform: none; }

/* =====================================================================================================================
   2026-10-24, pages redesign, group events-gallery-news (/events/, the 15 event pages, /news/; also used by /gallery/ and
   /notices/). The inner page kit (design-language.md section 3) has not landed as build/additions/0-kit.css, so the
   pieces this group needs are here under the prefix .egn- (events, gallery, news): sheet head, sheet foot, panel,
   headline rise, counter and the mounted hero plate. When 0-kit.css lands, these map one to one onto pk-head, pk-foot,
   pk-panel, [data-pk-split], pk-count and pk-plate and can be deleted. Tokens only; 44 px targets; reduced motion at the end.
   Documented in docs/additions/events.md. */

/* ---- egn-head: the home's sheet head grid (H2 on 10 of 12 columns, the lead on 7) ----------------------------------- */
.egn-head { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); row-gap: clamp(20px, 2.6vw, 36px); margin-bottom: clamp(36px, 4.5vw, 64px); }
.egn-head > h2 { grid-column: 1 / span 10; max-width: 18ch; text-wrap: balance; }
.egn-head > .lead { grid-column: 1 / span 7; max-width: 54ch; }
.egn-head > .lead a { color: inherit; }
.egn-head--tight { margin-bottom: clamp(24px, 3vw, 44px); }
@media (max-width: 1023px) { .egn-head > h2, .egn-head > .lead { grid-column: 1 / -1; } }

/* ---- egn-rise: the H2 rises through a mask when its block is revealed (js/inner.js adds .is-in to [data-reveal]) ------ */
@keyframes egn-rise { from { clip-path: inset(0 0 100% 0); transform: translateY(0.35em); } to { clip-path: inset(-0.2em 0 -0.3em 0); transform: none; } }
html.js-reveal .egn-rise[data-reveal].is-in { animation: egn-rise 1100ms var(--ease-mask) both; }
/* (the resting state stays pages.css's: opacity 0 and a 28 px rise; a clip-path at rest would hide the heading from
   IntersectionObserver, which applies clip-path to the target's box, and it would never be revealed) */

/* ---- egn-foot: every fact-heavy sheet closes on a hairline: a sentence, an action, a source caption ------------------ */
.egn-foot { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 18px var(--gutter); align-items: end; margin-top: clamp(36px, 4.5vw, 64px); padding-top: 24px; border-top: var(--hairline); }
.egn-foot__text { grid-column: 1 / span 8; max-width: 62ch; font-size: 18px; line-height: 1.55; }
.egn-foot__text a { color: inherit; }
.egn-foot__action { grid-column: 10 / -1; justify-self: end; display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 12px 24px; }
.egn-foot__source { grid-column: 1 / -1; }
@media (max-width: 1023px) {
  .egn-foot__text, .egn-foot__action { grid-column: 1 / -1; }
  .egn-foot__action { justify-self: start; justify-content: flex-start; }
}
@media (max-width: 639px) { .egn-foot__action .btn { width: 100%; } }

/* ---- egn-panel: the results-card recipe as a general panel (paper-3, clay border, 3 px coloured top rule) ------------ */
.egn-panel { --egn-edge: var(--maroon); display: flex; flex-direction: column; min-width: 0; padding: clamp(22px, 2.2vw, 34px); background: var(--paper-3); border: 1px solid var(--clay); border-top: 3px solid var(--egn-edge); }
.egn-panel--gold { --egn-edge: var(--gold); }
.egn-panel--ink { --egn-edge: var(--ink); }
.egn-panel__head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 8px 20px; padding-bottom: 14px; margin-bottom: 18px; border-bottom: var(--hairline); }
.egn-panel__name { font: 400 clamp(24px, 2.1vw, 34px) / 1.1 var(--font-serif); letter-spacing: -0.005em; text-wrap: balance; }
.egn-panel__sub { font: 400 15px / 1.45 var(--font-sans); color: var(--ink-2); }
.egn-panel p, .egn-panel li { font-size: 17px; line-height: 1.55; }
.egn-panel p + p { margin-top: 10px; }
.egn-panel__list { list-style: none; }
.egn-panel__list li + li { margin-top: 10px; padding-top: 10px; border-top: var(--hairline); }
.egn-panel__foot { margin-top: auto; padding-top: 16px; }
.egn-panel .label + * { margin-top: 10px; }
.egn-panels { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); }
@media (min-width: 720px) { .egn-panels--2, .egn-panels--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .egn-panels--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* ---- egn-count: a number that counts up once when it comes on screen (build/additions/events.js); the final number is in
   the markup, so no JavaScript, reduced motion and print all show it as it is ------------------------------------------- */
.egn-count { font-variant-numeric: tabular-nums lining-nums; }

/* ---- the mounted hero plate (the kit's pk-plate), only on this group's pages (body.egn-page): the shell's bleed plate is
   put back on the paper mount inside the band, with the home's curtain on load; a wide crop is cut to 16:9 on a phone, not
   4:3, so a 21:9 frame keeps its sides. Album pages (body.egn-album) use 2:1 and stop at 1200 px: their frames are 1200 px wide. */
body.egn-page .page-hero__plate { width: min(100% - 2 * var(--margin), var(--band-max)); margin-inline: auto; padding: 12px; border: 1px solid var(--clay); background: var(--paper-3); }
body.egn-page .page-hero__plate img { aspect-ratio: 16 / 9; }
@media (min-width: 1024px) { body.egn-page .page-hero__plate img { aspect-ratio: 21 / 9; } }
body.egn-album .page-hero__plate { width: min(100% - 2 * var(--margin), 1200px); margin-inline: auto; }
@media (min-width: 1024px) { body.egn-album .page-hero__plate img { aspect-ratio: 2 / 1; } }
@media (min-width: 1840px) { body.egn-page .page-hero__plate { border-inline: 1px solid var(--clay); } }
@keyframes egn-curtain { from { clip-path: inset(100% 0 0 0); } to { clip-path: inset(0); } }
@keyframes egn-settle { from { transform: scale(1.08); } to { transform: none; } }
html.js:not([data-motion="reduced"]) body.egn-page .page-hero__plate .plate__frame { animation: egn-curtain 1100ms var(--ease-wipe) 200ms both; }
html.js:not([data-motion="reduced"]) body.egn-page .page-hero__plate img { animation: egn-settle 1400ms var(--ease-out) 200ms both; }

/* ---- /events/ sheet 01: the five big-day cards keep .ev-feature; the lead card is 3:2 on tablets (was 2:1, which cut the
   from-above formation) ------------------------------------------------------------------------------------------------ */
@media (min-width: 640px) and (max-width: 1099.98px) { .ev-card--lead .ev-card__frame { aspect-ratio: 3 / 2; } }
.ev-card__frame img { object-position: var(--pos, 50% 50%); }

/* ---- /events/ sheet 02, ev-year: the school year as one object. Two semesters side by side from 900 px, each a row of six
   month columns under a maroon or gold bar that draws left to right when the strip is revealed; every mark is a link with a
   44 px target. On a phone the semesters stack and each month is a row: name left, marks right. No horizontal scroll. ---- */
.ev-year { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 4vw, 48px) var(--gutter); }
.ev-year__sem { --ev-edge: var(--maroon); min-width: 0; }
.ev-year__sem--1 { --ev-edge: var(--maroon); }
.ev-year__sem--2 { --ev-edge: var(--gold); }
.ev-year__sem-head { position: relative; display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 6px 20px; padding-top: 16px; margin-bottom: 18px; }
.ev-year__bar { position: absolute; top: 0; left: 0; width: 100%; height: 3px; background: var(--ev-edge); transform-origin: left center; transition: transform 1100ms var(--ease-out); }
html.js-reveal .ev-year:not(.is-in) .ev-year__bar { transform: scaleX(0); }
.ev-year__sem-title { font: 400 clamp(22px, 1.9vw, 30px) / 1.15 var(--font-serif); letter-spacing: -0.005em; }
.ev-year__sem-when { font: 500 11.5px / 1.3 var(--font-sans); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); }
.ev-year__months { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); border-top: 1px solid var(--ink); }
.ev-year__month { display: grid; grid-template-columns: 64px minmax(0, 1fr); column-gap: 16px; align-items: start; min-height: 44px; padding: 10px 0; border-bottom: var(--hairline); }
.ev-year__name { padding-top: 6px; font: 500 12.5px / 1.3 var(--font-sans); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.ev-year__month--quiet .ev-year__name { opacity: 0.7; }
.ev-year__marks { list-style: none; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.ev-year__mark { position: relative; display: block; min-height: 44px; padding: 8px 0; font: 400 17px / 1.35 var(--font-serif); color: var(--ink); text-decoration: none; text-wrap: pretty; overflow-wrap: normal; hyphens: manual; }
.ev-year__month, .ev-year__marks li { overflow-wrap: normal; }
.ev-year__mark b { display: inline-block; min-width: 2ch; margin-right: 6px; font: 300 clamp(26px, 2vw, 34px) / 0.9 var(--font-serif); color: var(--maroon); font-variant-numeric: tabular-nums lining-nums; vertical-align: -0.08em; }
.ev-year__mark .label { display: block; margin-bottom: 4px; color: var(--gold); }
a.ev-year__mark { background-image: linear-gradient(var(--gold), var(--gold)); background-repeat: no-repeat; background-position: 0 calc(100% - 6px); background-size: 0 1px; transition: background-size var(--t-micro) var(--ease-soft), color var(--t-micro); }
a.ev-year__mark:hover, a.ev-year__mark:focus-visible { color: var(--maroon); background-size: 100% 1px; }
a.ev-year__mark:focus-visible { outline: 2px solid var(--maroon); outline-offset: 2px; }
.ev-year__mark--fixed { font-weight: 400; }
.ev-year__mark--exam { color: var(--ink-2); font-style: italic; }
.ev-year__mark--exam::before { content: ''; display: inline-block; width: 18px; height: 1px; margin-right: 10px; background: var(--ink-2); vertical-align: middle; }
@media (min-width: 1280px) { .ev-year__mark { font-size: 16px; } }
@media (min-width: 900px) {
  .ev-year { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ev-year__months { grid-template-columns: repeat(6, minmax(0, 1fr)); border-top: 0; }
  .ev-year__month { grid-template-columns: minmax(0, 1fr); row-gap: 10px; min-height: 180px; padding: 12px 10px 14px 0; border-bottom: 0; border-top: 1px solid var(--ink); }
  .ev-year__month + .ev-year__month { border-left: var(--hairline); padding-left: 10px; }
  .ev-year__name { padding-top: 0; }
  .ev-year__mark { font-size: 15px; line-height: 1.3; }
  .ev-year__mark b { display: block; margin: 0 0 4px; font-size: clamp(30px, 2.4vw, 40px); }
  .ev-year__month { padding-right: 6px; }
  .ev-year__mark--exam::before { display: block; width: 24px; margin: 0 0 8px; }
}
.ev-year__announced { margin-top: clamp(24px, 3vw, 40px); }
.ev-year__pills { list-style: none; display: flex; flex-wrap: wrap; gap: 10px; }
.ev-year__pill { display: inline-flex; align-items: center; min-height: 44px; padding: 8px 16px; border: 1px solid var(--clay); border-radius: 999px; font: 400 15px / 1.2 var(--font-sans); color: var(--ink); text-decoration: none; transition: border-color var(--t-micro), color var(--t-micro); }
.ev-year__pill:hover, .ev-year__pill:focus-visible { border-color: var(--maroon); color: var(--maroon); }
.ev-year__pill:focus-visible { outline: 2px solid var(--maroon); outline-offset: 2px; }
.ev-year__panels { margin-top: clamp(36px, 4.5vw, 64px); }

/* ---- /events/ sheet 03, ev-index: the fifteen events in four short columns, grouped by kind. One link per entry, the whole
   entry the target (44 px or more); the chips and filters are gone: grouping replaces filtering ------------------------- */
.ev-index { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 3.5vw, 48px) var(--gutter); }
.ev-index__group { min-width: 0; padding-top: 14px; border-top: 1px solid var(--ink); }
.ev-index__kind { color: var(--gold); }
.ev-index__count { margin-left: 8px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.ev-index__list { list-style: none; margin-top: 10px; }
.ev-index__item { display: block; position: relative; min-height: 44px; padding: 14px 0 16px; border-bottom: var(--hairline); color: inherit; text-decoration: none; }
.ev-index__list li:last-child .ev-index__item { border-bottom: 0; }
.ev-index__name { display: block; font: 400 clamp(20px, 1.6vw, 24px) / 1.15 var(--font-serif); letter-spacing: -0.004em; transition: color var(--t-micro); }
.ev-index__when { display: block; margin-top: 5px; font: 500 11.5px / 1.3 var(--font-sans); letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.ev-index__when b { font-weight: 500; color: var(--maroon); }
.ev-index__line { display: block; margin-top: 7px; font: 400 15px / 1.45 var(--font-sans); color: var(--ink-2); max-width: 36ch; }
.ev-index__item:hover .ev-index__name, .ev-index__item:focus-visible .ev-index__name { color: var(--maroon); }
.ev-index__item:focus-visible { outline: 2px solid var(--maroon); outline-offset: 2px; }
@media (min-width: 640px) { .ev-index { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .ev-index { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* ---- an event page: the facts strip keeps only facts that say something; a fixed date is a maroon numeral -------------- */
.fact--num dd { color: var(--maroon); }
.fact--num dd small { color: var(--ink-2); }
@media (min-width: 1024px) { .fact-strip--2 { --cols: 2; } }

/* ---- an event page, sheet 03, ev-album: three plates from the event's own album, each opening the viewer; the Graduation
   page shows four album covers as the home's .ev-grid cards instead ------------------------------------------------------ */
.ev-album { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); }
.ev-album .gallery__link { display: block; padding: 10px; }
.ev-album .gallery__frame { display: block; overflow: hidden; }
.ev-album .gallery__frame picture, .ev-album .gallery__frame img { display: block; width: 100%; }
.ev-album .gallery__frame img { aspect-ratio: 3 / 2; height: auto; object-fit: cover; object-position: var(--pos, 50% 50%); }
@media (min-width: 640px) { .ev-album { grid-template-columns: repeat(2, minmax(0, 1fr)); } .ev-album--3 > li:first-child:nth-last-child(3) { grid-column: 1 / -1; } }
@media (min-width: 1024px) { .ev-album--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } .ev-album--3 > li:first-child:nth-last-child(3) { grid-column: auto; } }
.ev-years .ev__n { margin-top: 2px; }
.ev-years .ev__media img { aspect-ratio: 3 / 2; object-position: var(--pos, 50% 45%); }
@media (min-width: 1024px) { .ev-years .ev { grid-column: span 3; } }
@media (min-width: 1280px) { .ev-years--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } .ev-years--4 .ev { grid-column: auto; } }

/* ---- an event page, sheet 04, ev-hook: one admissions moment, the home's .venue panel in a 12-column grid (7 of 12 from
   1024 px, full width below), one arrow link and the secondary "Book a visit" ------------------------------------------- */
.ev-hook { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); }
.ev-hook .venue { display: flex; flex-direction: column; }
.ev-hook .venue__text { margin-top: 8px; }
.ev-hook__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 28px; margin-top: 22px; font: 400 16px / 1.4 var(--font-sans); }
.ev-hook__actions .link--arrow { position: relative; }
.ev-hook__actions .link--arrow::before { content: ''; position: absolute; inset: -10px -4px; }
@media (max-width: 1023px) { .ev-hook .venue { grid-column: 1 / -1; } }
@media (max-width: 639px) { .ev-hook__actions .btn { width: 100%; } }

/* ---- an event page with no cleared frame: the typographic plate as a band-wide mark (an honest line under the word says
   the school's photographs come when it agrees to them) ------------------------------------------------------------------ */
.ev-mark--band { margin-top: clamp(28px, 3.6vw, 52px); }
.ev-mark--band .ev-type { min-height: clamp(220px, 28vw, 400px); }
.ev-mark--band .ev-type__word { font-size: clamp(44px, 7vw, 120px); }
.ev-mark__line { margin-top: 14px; font: 400 15px / 1.5 var(--font-sans); color: var(--ink-2); max-width: 62ch; }
.ev-mark__line a { color: inherit; }

/* ---- /news/ (no additions file of its own; its rules sit with the events group) ----------------------------------------
   news-status: the first sheet's one highlighted statement with its links. news-ledger: the eleven competition results as
   a ledger: the home's .feats row, then one gold-ruled panel per kind with its rows inside (date column 96 px from 768 px). */
.news-status { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 24px var(--gutter); align-items: start; }
.news-status .venue { display: flex; flex-direction: column; }
.news-status__links { grid-column: 9 / -1; align-self: end; }
.news-status__call { grid-column: 1 / -1; max-width: 62ch; font-size: 17px; line-height: 1.55; color: var(--ink-2); }
.news-status__call .phones { margin-top: 14px; }
@media (max-width: 1023px) { .news-status .venue, .news-status__links { grid-column: 1 / -1; } }
.news-ledger { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); margin-top: clamp(28px, 3.5vw, 48px); }
.news-ledger .rows { border-top: 0; }
.news-ledger .row { padding: 14px 0 16px; }
.news-ledger .row:last-child { border-bottom: 0; padding-bottom: 4px; }
.news-ledger .row__day { font-size: clamp(26px, 2vw, 34px); }
.news-ledger .row__title { font-size: clamp(19px, 1.5vw, 23px); }
.news-ledger .row__text { font-size: 16px; }
@media (min-width: 768px) { .news-ledger .row { grid-template-columns: 96px minmax(0, 1fr); column-gap: 20px; } }
@media (min-width: 1024px) { .news-ledger { grid-template-columns: repeat(2, minmax(0, 1fr)); } .news-ledger .egn-panel--span { grid-column: 1 / -1; } }
.news-feats { margin-top: 0; }
.news-feats .feat__n { font-size: clamp(32px, 2.6vw, 44px); }
.news-feed .plate--flat { padding: 10px; background: var(--paper-3); border: 1px solid var(--clay); }
.news-feed .news-item .plate img { aspect-ratio: 3 / 2; }
@media (min-width: 1024px) { .news-feed .news-item--lead .plate img { aspect-ratio: 16 / 9; } }

@media (prefers-reduced-motion: reduce) {
  .ev-year__bar, a.ev-year__mark, .ev-year__pill, .ev-index__name, .ev-index__item { transition: none !important; }
  html.js-reveal .egn-rise[data-reveal].is-in { animation: none !important; clip-path: none; }
  html.js-reveal .ev-year:not(.is-in) .ev-year__bar { transform: none; }
  body.egn-page .page-hero__plate .plate__frame, body.egn-page .page-hero__plate img { animation: none !important; }
}
html[data-motion="reduced"] .ev-year__bar { transition: none !important; }
html[data-motion="reduced"] .egn-rise[data-reveal].is-in { animation: none !important; clip-path: none !important; }
html[data-motion="reduced"] .ev-year:not(.is-in) .ev-year__bar { transform: none; }
html[data-motion="reduced"] body.egn-page .page-hero__plate .plate__frame, html[data-motion="reduced"] body.egn-page .page-hero__plate img { animation: none !important; }
@media print {
  .egn-rise[data-reveal] { animation: none !important; clip-path: none !important; transform: none !important; }
  body.egn-page .page-hero__plate .plate__frame, body.egn-page .page-hero__plate img { animation: none !important; }
}

/* =====================================================================================================================
   2026-10-24, review r1 of the events-gallery-news group (see redesign-2026-10-24-pages/build/events-gallery-news.md). */

/* ---- the hero plate's focal point, set per page by a body class (the shell has no hero_pos key yet): /news/ opens on
   img/gal-nasa-soyuz, whose projected screen carries a Windows taskbar along its bottom edge; anchored to the top, the
   2:1 and 16:9 cuts take the bottom of the frame off ---------------------------------------------------------------- */
body.egn-hero-top .page-hero__plate img { object-position: 50% 0%; }
body.egn-hero-bottom .page-hero__plate img { object-position: 50% 100%; }

/* ---- the hubs' phone hero: events.js adds the 4:5 -tall source for screens up to 639 px and marks the body ---------- */
@media (max-width: 639px) { body.egn-hero-tall .page-hero__plate img { aspect-ratio: 4 / 5; } }

/* ---- /events/ sheet 01, the lead card from 1100 px: the frame no longer grows to match the two cards beside it (it
   reached about 900 x 860 and the wave formation became grey sand); it stays 3:2, the frame's own ratio, and the card
   aligns to the top of its two rows ---------------------------------------------------------------------------------- */
@media (min-width: 1100px) {
  .ev-card--lead { align-self: start; }
  .ev-card--lead .ev-card__frame { aspect-ratio: 3 / 2; flex: 0 0 auto; min-height: 0; }
}

/* ---- /events/ sheet 02, the year strip from 900 px: 14 px marks, balanced over two lines, no soft hyphens in the
   markup, so "Independence Day" and "Science and Technology Fair" never break inside a word ------------------------------ */
@media (min-width: 900px) {
  .ev-year__month { min-width: 0; }
  .ev-year__mark { font-size: 14px; line-height: 1.3; text-wrap: balance; overflow-wrap: normal; hyphens: manual; }
  .ev-year__mark b { font-size: clamp(28px, 2.2vw, 36px); }
}
@media (min-width: 1280px) { .ev-year__mark { font-size: 14px; } }

/* ---- an event page, sheet 01, ev-glance: the typographic plate (or the one cleared frame) on 5 of 12 columns beside the
   fact strip from 1024 px, instead of a band-wide plate that repeated the H1 under the H1. The facts take two columns in
   their 7; the honest line sits under them. Below 1024 px the plate stacks over the facts ------------------------------ */
.ev-glance { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: clamp(24px, 3vw, 40px) var(--gutter); align-items: start; }
.ev-glance__mark { grid-column: 1 / -1; margin: 0; }
.ev-glance__facts { grid-column: 1 / -1; min-width: 0; }
.ev-glance__facts .ev-mark__line { margin-top: 18px; }
@media (min-width: 1024px) {
  .ev-glance__mark { grid-column: 1 / span 5; }
  .ev-glance__facts { grid-column: 7 / -1; }
  .ev-glance__facts .fact-strip { --cols: 2; }
}
.ev-mark--side .ev-type { min-height: clamp(220px, 24vw, 320px); }
.ev-mark--side .ev-type__word { font-size: clamp(36px, 3.6vw, 60px); }
.ev-glance__photo { padding: 10px; background: var(--paper-3); border: 1px solid var(--clay); }
.ev-glance__photo .plate__frame picture, .ev-glance__photo .plate__frame img { display: block; width: 100%; }
.ev-glance__photo .plate__frame img { height: auto; object-fit: cover; object-position: var(--pos, 50% 50%); }
.ev-glance__photo.plate--4x5 { max-width: 24rem; }
.ev-glance__photo.plate--4x5 .plate__frame img { aspect-ratio: 4 / 5; }

/* ---- /news/ sheet 03: the panels keep their own height (the Olympiads panel stretched to the Language panel's with a
   third of it empty); the three numbers are set at the home's size; the third is a span of dates, not a count of one ---- */
.news-ledger { align-items: start; }
.news-feats .feat__n { font-size: clamp(44px, 4vw, 64px); }
.news-feat__span { font-size: clamp(26px, 2.2vw, 40px); line-height: 1.05; white-space: normal; }
.news-feat__span small { display: block; margin: 4px 0; font: 500 11.5px / 1.3 var(--font-sans); letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-2); }

/* =====================================================================================================================
   2026-10-24, review r2 of the events-gallery-news group (see redesign-2026-10-24-pages/build/events-gallery-news.md). */

/* ---- /news/ sheet 03, the third feat: main.css gives .feat a fixed 92 px first column, and "Aug 2023 to Apr 2024" at 40 px
   broke letter by letter into a 600 px column. The first column now grows to the numeral's width; the span stays on one
   line from 640 px (the "to" inline) and takes three short lines on a phone ---------------------------------------- */
.news-feats .feat { grid-template-columns: minmax(92px, max-content) minmax(0, 1fr); }
.news-feat__span { white-space: normal; }
.news-feat__span small { display: block; margin: 4px 0; }
@media (min-width: 640px) {
  .news-feat__span { white-space: nowrap; }
  .news-feat__span small { display: inline; margin: 0 0.4em; vertical-align: 0.35em; }
}

/* ---- the mounted hero plate's curtain: fill-mode backwards and no delay, so the resting state is always the whole frame
   (with "both" and a 200 ms delay, a capture or a restarted animation left the plate blank, as the H2 was once) ---- */
html.js:not([data-motion="reduced"]) body.egn-page .page-hero__plate .plate__frame { animation: egn-curtain 1100ms var(--ease-wipe) 0ms backwards; }
html.js:not([data-motion="reduced"]) body.egn-page .page-hero__plate img { animation: egn-settle 1400ms var(--ease-out) 0ms backwards; }

/* ---- the hero plate's focal point, one more position: the Graduation 2023 album opens on the stage frame cut from the
   bottom, so the crest ribbon above the title ("Established in 1977", decision A1) leaves the 2:1 plate ------------ */
body.egn-hero-right .page-hero__plate img { object-position: 72% 50%; }

/* ---- /events/ sheet 03, the index from 1100 px: four equal columns with 7 / 4 / 3 / 1 entries left the right half of the
   band empty under the first row. Academic takes two columns with its seven entries in two sub-columns (four and three,
   read down), Culture the third, and National days and Sports share the fourth, so the sheet ends roughly level ---- */
@media (min-width: 1100px) {
  .ev-index { grid-template-rows: auto auto; align-items: start; }
  .ev-index__group--academic { grid-column: 1 / span 2; grid-row: 1 / span 2; }
  .ev-index__group--academic .ev-index__list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-flow: column; grid-template-rows: repeat(4, auto); column-gap: var(--gutter); }
  .ev-index__group--academic .ev-index__list li:nth-child(4) .ev-index__item { border-bottom: 0; }
  .ev-index__group--culture { grid-column: 3; grid-row: 1 / span 2; }
  .ev-index__group--national { grid-column: 4; grid-row: 1; }
  .ev-index__group--sports { grid-column: 4; grid-row: 2; }
}

/* ---- the Science and Technology Fair page, sheet 01 (AI plates round, 2026-10-25): media/swatch-4 (a soft 720 px square
   that also shows two students in lab coats) left the page for the sharp AI plate img/ev-science-still at the group's
   usual 3:2, so the 360 px cap (.ev-glance__photo--small) it needed is gone ---- */

/* ---- final review 2026-10-25: the gold labels of /events/ ("On record, 2024", the kind headings of the index) measured 4.0:1
   on paper at 11.5 to 12.5 px; they take a deeper gold (5.8:1 on --paper), still read as gold beside the maroon. */
.ev-year__mark .label, .ev-index__kind { color: color-mix(in srgb, var(--gold) 72%, var(--ink)); }

/* ---- additions/gallery.css ---- */
/* gallery group: /gallery/ and the album pages /gallery/<slug>/ (2026-10-22). Documented in docs/additions/gallery.md.
   .alb-filters   the two chip rows (kind, year) with their labels
   .alb-cards     the album cards on /gallery/: cover (or an empty tile), kind and year, title, how many photographs are shown
   .alb-grid      an album's frames: an even grid of 4:3 thumbnails (the viewer shows the whole frame)
   .alb-empty     "Photographs added when the school agrees": the tile of an album with no safe frame yet
   .alb-source    the line under an album's grid that sends parents to the school's own gallery
   body.gallery-page .lightbox   the viewer, full screen on these pages (dark, the whole photograph, 44 px controls) */

.alb-section { padding-block: clamp(40px, 5vw, 72px); }

/* ---- filters ---- */
.alb-filters { display: grid; gap: 10px; }
.alb-filters .label { margin-top: 8px; }
.alb-filters .label:first-child { margin-top: 0; }
@media (max-width: 559.98px) {     /* a phone: each chip row scrolls sideways instead of taking seven lines */
  .alb-filters .chips { flex-wrap: nowrap; overflow-x: auto; margin-inline: calc(var(--margin) * -1); padding: 4px var(--margin); scrollbar-width: none; scroll-padding-inline: var(--margin); }
  .alb-filters .chips::-webkit-scrollbar { display: none; }
  .alb-filters .chips li { flex: 0 0 auto; }
}

/* ---- album cards ---- */
.alb-cards { list-style: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(24px, 3vw, 40px) var(--gutter); }
@media (min-width: 900px) { .alb-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1200px) { .alb-cards { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.alb-card { position: relative; display: flex; flex-direction: column; min-width: 0; }
.alb-card[hidden] { display: none; }
.alb-card__frame { position: relative; overflow: hidden; aspect-ratio: 4 / 3; padding: 8px; background: var(--paper-3); border: 1px solid var(--clay); }
.alb-card__frame picture, .alb-card__frame img { display: block; width: 100%; height: 100%; }
.alb-card__frame img { object-fit: cover; object-position: var(--pos, 50% 50%); transition: transform var(--t-reveal) var(--ease-out); }
.alb-card__frame--empty {
  display: flex; flex-direction: column; justify-content: space-between; padding: 14px;
  background: var(--paper-2);
  background-image: repeating-linear-gradient(135deg, transparent 0 14px, rgba(138, 2, 4, 0.05) 14px 15px);
}
.alb-card__mark { font: 300 clamp(44px, 6vw, 84px) / 0.9 var(--font-serif); color: var(--maroon); opacity: 0.55; }
.alb-card__wait { max-width: 22ch; font: 500 12px / 1.35 var(--font-sans); letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-2); }
.alb-card__meta { display: flex; flex-wrap: wrap; gap: 2px 12px; margin-top: 14px; font: 500 11px / 1.3 var(--font-sans); letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-2); }
.alb-card__title { margin-top: 8px; font: 400 clamp(20px, 1.7vw, 27px) / 1.12 var(--font-serif); letter-spacing: -0.004em; overflow-wrap: anywhere; hyphens: auto; }
.alb-card__link { color: inherit; text-decoration: none; transition: color var(--t-micro); }
.alb-card__link::after { content: ''; position: absolute; inset: 0; }
.alb-card__link:focus-visible { outline: none; }
.alb-card__link:focus-visible::after { outline: 2px solid var(--maroon); outline-offset: 4px; }
.alb-card__count { margin-top: 6px; font-size: 15px; line-height: 1.4; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.alb-card:hover .alb-card__link, .alb-card:focus-within .alb-card__link { color: var(--maroon); }
.alb-card:hover .alb-card__frame img { transform: scale(1.03); }
@media (max-width: 559.98px) {
  .alb-card__frame { padding: 5px; }
  .alb-card__frame--empty { padding: 10px; }
  .alb-card__wait { font-size: 10.5px; letter-spacing: 0.04em; }
  .alb-card__title { font-size: 19px; }
  .alb-card__count { font-size: 14px; }
}

/* ---- an album's frames ---- */
.gallery.alb-grid { columns: auto; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gutter); }
@media (max-width: 559.98px) { .alb-grid .gallery__link { padding: 5px; } }
.alb-grid .gallery__item { margin: 0; min-width: 0; }
.alb-grid .gallery__frame img { aspect-ratio: 4 / 3; object-fit: cover; object-position: var(--pos, 50% 50%); }
@media (min-width: 1024px) { .gallery.alb-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.alb-empty {
  max-width: 60ch; padding: clamp(24px, 3vw, 40px);
  border: 1px dashed var(--clay); background: var(--paper-2);
  background-image: repeating-linear-gradient(135deg, transparent 0 18px, rgba(138, 2, 4, 0.04) 18px 19px);
}
.alb-empty__title { font: 400 clamp(24px, 2.2vw, 34px) / 1.15 var(--font-serif); color: var(--ink); }
.alb-empty p + p { margin-top: 12px; font-size: 17px; line-height: 1.55; color: var(--ink-2); }
.alb-source { max-width: 62ch; margin-top: clamp(24px, 3vw, 40px); font-size: 16px; line-height: 1.55; color: var(--ink-2); }

/* ---- the viewer, full screen on the gallery pages ---- */
body.gallery-page .lightbox.dialog {
  width: 100vw; height: 100vh; height: 100dvh; max-width: 100vw; max-height: 100vh; max-height: 100dvh;
  margin: 0; padding: 16px 16px 12px; border: 0;
  background: var(--night); color: var(--paper);
  overscroll-behavior: contain; touch-action: pan-y pinch-zoom;
}
body.gallery-page .lightbox.dialog[open] { display: flex; flex-direction: column; }
body.gallery-page .lightbox .dialog__figure { flex: 1 1 auto; min-height: 0; justify-content: center; }
body.gallery-page .lightbox .dialog__img {
  max-width: 100%; max-height: calc(100vh - 110px); max-height: calc(100dvh - 110px);
  user-select: none; -webkit-user-drag: none;
}
body.gallery-page .lightbox .dialog__nav { justify-content: center; align-items: center; padding-top: 8px; }
body.gallery-page .lightbox .dialog__count { margin-left: 8px; color: var(--bone-dim); }
body.gallery-page .lightbox .dialog__btn,
body.gallery-page .lightbox .dialog__close { background: transparent; color: var(--paper); border-color: var(--night-line); }
body.gallery-page .lightbox .dialog__btn:hover,
body.gallery-page .lightbox .dialog__close:hover { border-color: var(--paper); }
body.gallery-page .lightbox .dialog__btn:focus-visible,
body.gallery-page .lightbox .dialog__close:focus-visible { outline: 2px solid var(--gold-text); outline-offset: 2px; }
body.gallery-page .lightbox .dialog__close { top: 16px; right: 16px; z-index: 1; }
body.gallery-page .lightbox.lightbox--single [data-lb] { display: none; }
body.gallery-page .lightbox::backdrop { background: var(--night); }

@media (prefers-reduced-motion: reduce) {
  .alb-card__frame img, .alb-card__link { transition: none; }
  .alb-card:hover .alb-card__frame img { transform: none; }
}
html[data-motion="reduced"] .alb-card__frame img, html[data-motion="reduced"] .alb-card__link { transition: none !important; }
html[data-motion="reduced"] .alb-card:hover .alb-card__frame img { transform: none; }


/* =====================================================================================================================
   2026-10-24, pages redesign, group events-gallery-news: the gallery hub and the album pages. New here: gal-high (the
   highlights slider in the home's maroon .frame), alb-more (the folded list of albums without a safe frame), the album
   grid shapes by count (alb-grid--1 to --5), the album meta line (alb-meta), the "About this event" panel (alb-about) and
   a fade on the phone's scrolling chip rows. Documented in docs/additions/gallery.md. */

/* ---- phones: the chip rows scroll sideways; a fade on the right edge says so (the only hint used to be a cut-off chip) */
@media (max-width: 559.98px) {
  .alb-filters .chips { -webkit-mask-image: linear-gradient(to right, black calc(100% - var(--margin) - 36px), transparent calc(100% - var(--margin) + 2px)); mask-image: linear-gradient(to right, black calc(100% - var(--margin) - 36px), transparent calc(100% - var(--margin) + 2px)); }
}

/* ---- gal-high: six of the strongest cleared frames in the home's ceremonial .frame (maroon mount, gold inner line,
   paper-3 mat). The slides are stacked in a 16:9 window (3:2 on phones) and cross-dissolve with a slow settle;
   build/additions/gallery.js drives it: previous, next and pause (WCAG 2.2.2), Left and Right arrows, swipe, a gold
   progress line, the counter and the album link of the current frame. Without JavaScript the first frame shows on its own
   with its link; the controls stay hidden until the script is ready. Reduced motion and phones: no autoplay, no dissolve. */
.gal-high { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); row-gap: clamp(18px, 2vw, 26px); }
.gal-high .frame { grid-column: 1 / span 9; margin: 0; }
.gal-high__mat { position: relative; }
.gal-high__slides { list-style: none; position: relative; aspect-ratio: 3 / 2; overflow: hidden; background: var(--paper-2); touch-action: pan-y; }
@media (min-width: 640px) { .gal-high__slides { aspect-ratio: 16 / 9; } }
.gal-high__slide { position: absolute; inset: 0; opacity: 0; visibility: hidden; z-index: 0; transition: opacity 1200ms var(--ease-soft), visibility 0s linear 1200ms; }
.gal-high__slide.is-active { opacity: 1; visibility: visible; z-index: 1; transition-delay: 0s; }
.gal-high__link { display: block; width: 100%; height: 100%; cursor: zoom-in; }
.gal-high__link:focus-visible { outline: 2px solid var(--gold-text); outline-offset: -4px; }
.gal-high__slide picture, .gal-high__slide img { display: block; width: 100%; height: 100%; }
.gal-high__slide img { object-fit: cover; object-position: var(--pos, 50% 50%); transform: scale(1.06); transition: transform 5600ms var(--ease-out); }
.gal-high__slide.is-active img { transform: none; }
.gal-high.is-still .gal-high__slide, .gal-high.is-still .gal-high__slide img { transition: none; }
.gal-high.is-still .gal-high__slide img { transform: none; }
.gal-high__side { grid-column: 10 / -1; align-self: end; display: flex; flex-direction: column; gap: 18px; min-width: 0; }
.gal-high__bar { position: relative; padding-top: 16px; }
.gal-high__track { position: absolute; top: 0; left: 0; right: 0; height: 1px; background: var(--clay); }
.gal-high__fill { position: absolute; top: -0.5px; left: 0; width: 100%; height: 2px; background: var(--gold); transform: scaleX(0); transform-origin: 0 50%; }
.gal-high__fill.is-run { transition: transform var(--gal-hold, 4500ms) linear; transform: scaleX(1); }
.gal-high.is-still .gal-high__fill, .gal-high:not(.is-ready) .gal-high__fill { display: none; }
.gal-high__count { display: block; font: 300 clamp(28px, 2.4vw, 40px) / 1 var(--font-serif); font-variant-numeric: tabular-nums lining-nums; letter-spacing: 0.01em; color: var(--ink-2); }
.gal-high__now { font-weight: 300; color: var(--maroon); }
.gal-high__sep { margin: 0 0.3em; color: var(--clay); }
.gal-high__status { position: absolute; }
.gal-high__caps { list-style: none; position: relative; margin-top: 12px; min-height: 3.2em; }
.gal-high__cap { display: none; }
.gal-high__cap.is-active { display: block; }
.gal-high__cap .label { display: block; margin-bottom: 6px; }
.gal-high__album { font: 400 clamp(20px, 1.6vw, 26px) / 1.2 var(--font-serif); letter-spacing: -0.004em; }
.gal-high__album a { color: inherit; position: relative; }
.gal-high__album a::before { content: ''; position: absolute; inset: -10px -4px; }
.gal-high__nav { display: flex; gap: 8px; }
.gal-high:not(.is-ready) .gal-high__nav { visibility: hidden; }
.gal-high__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); }
.gal-high__btn svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.25; stroke-linecap: round; stroke-linejoin: round; transition: transform var(--t-hover) var(--ease-out); }
.gal-high__btn:hover { border-color: var(--maroon); color: var(--maroon); background-color: var(--paper-3); }
.gal-high__btn:focus-visible { outline: 2px solid var(--maroon); outline-offset: 2px; }
.gal-high__btn--prev:hover svg { transform: translateX(-2px); }
.gal-high__btn--next:hover svg { transform: translateX(2px); }
.gal-high__btn--toggle .gal-high__ico-play { display: none; }
.gal-high__btn--toggle[data-state="paused"] .gal-high__ico-play { display: inline; }
.gal-high__btn--toggle[data-state="paused"] .gal-high__ico-pause { display: none; }
.gal-high.is-still .gal-high__btn--toggle, .gal-high__btn[hidden] { display: none; }
@media (max-width: 1023px) {
  .gal-high .frame, .gal-high__side { grid-column: 1 / -1; }
  .gal-high__side { flex-direction: row; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 16px 24px; }
  .gal-high__bar { flex: 1 1 260px; }
}

/* ---- alb-card: the count line reads positively ("5 photographs shown") and the covers take a focus point ------------ */
.alb-card__count b { font-weight: 400; color: var(--ink); }

/* ---- alb-more: the albums without a safe frame yet, folded in a native details under the covers (the same summary as the
   notices page's ended list: a 22 px serif line and a round 44 px marker pushed right with margin-left: auto) --------- */
.alb-more { margin-top: clamp(32px, 4vw, 48px); border-top: 1px solid var(--ink); }
.alb-more__summary { position: relative; display: flex; align-items: center; gap: 16px; min-height: 56px; padding: 12px 0; font: 400 22px / 1.2 var(--font-serif); color: var(--ink); list-style: none; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.alb-more__label { flex: 1 1 auto; min-width: 0; }
.alb-more__summary::-webkit-details-marker { display: none; }
.alb-more__summary::marker { content: ''; }
.alb-more__summary::after { content: '+'; flex: none; display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; margin-left: auto; border: 1px solid var(--ink-2); border-radius: 999px; font: 400 24px / 1 var(--font-sans); color: var(--ink); }
.alb-more[open] > .alb-more__summary::after { content: '\2212'; }
.alb-more__summary:hover { color: var(--maroon); }
.alb-more__summary:hover::after { border-color: var(--maroon); color: var(--maroon); }
.alb-more__summary:focus-visible { outline: 2px solid var(--maroon); outline-offset: 2px; }
.alb-more__note { max-width: 62ch; margin: 6px 0 18px; font-size: 16px; line-height: 1.55; color: var(--ink-2); }
.alb-more__list { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); border-top: var(--hairline); }
.alb-more__item { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 16px; align-items: baseline; min-height: 44px; padding: 12px 0; border-bottom: var(--hairline); }
.alb-more__name { font: 400 clamp(18px, 1.4vw, 21px) / 1.2 var(--font-serif); }
.alb-more__name a { color: inherit; text-decoration: none; background-image: linear-gradient(var(--gold), var(--gold)); background-repeat: no-repeat; background-position: 0 100%; background-size: 100% 1px; transition: color var(--t-micro); position: relative; }
.alb-more__name a::before { content: ''; position: absolute; inset: -12px -4px; }
.alb-more__name a:hover, .alb-more__name a:focus-visible { color: var(--maroon); }
.alb-more__meta { font: 500 11.5px / 1.4 var(--font-sans); letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-2); font-variant-numeric: tabular-nums; text-align: right; }
@media (min-width: 900px) { .alb-more__list { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gutter); } }
@media (max-width: 559.98px) { .alb-more__item { grid-template-columns: minmax(0, 1fr); row-gap: 4px; } .alb-more__meta { text-align: left; } }

/* ---- an album page: the meta line over the grid, and grid shapes by how many frames the album has -------------------- */
.alb-meta { display: flex; flex-wrap: wrap; gap: 6px 10px; margin-bottom: clamp(20px, 2.4vw, 32px); }
.alb-meta span + span::before { content: '\00b7'; margin-right: 10px; color: var(--clay); }
.gallery.alb-grid--1 { grid-template-columns: minmax(0, 1fr); }
.gallery.alb-grid--1 .gallery__frame img { aspect-ratio: 3 / 2; }
.gallery.alb-grid--2 { grid-template-columns: minmax(0, 1fr); }
.gallery.alb-grid--3 { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 640px) {
  .gallery.alb-grid--1 { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .gallery.alb-grid--1 .gallery__item { grid-column: 1 / span 10; }
  .gallery.alb-grid--2, .gallery.alb-grid--3, .gallery.alb-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gallery.alb-grid--2 .gallery__frame img { aspect-ratio: 3 / 2; }
  .gallery.alb-grid--5 .gallery__item:first-child { grid-column: 1 / -1; }
  .gallery.alb-grid--5 .gallery__item:first-child .gallery__frame img { aspect-ratio: 2 / 1; }
}
@media (min-width: 1024px) {
  .gallery.alb-grid--1 .gallery__item { grid-column: 1 / span 8; }
  .gallery.alb-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gallery.alb-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .gallery.alb-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gallery.alb-grid--4 .gallery__frame img { aspect-ratio: 3 / 2; }
  .gallery.alb-grid--5 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gallery.alb-grid--5 .gallery__item:first-child { grid-column: 1 / -1; }
  .gallery.alb-grid--5 .gallery__item:first-child .gallery__frame img { aspect-ratio: 21 / 9; }
  .gallery.alb-grid--5 .gallery__item:not(:first-child) .gallery__frame img { aspect-ratio: 3 / 2; }
}
@media (min-width: 1200px) { .gallery.alb-grid--5 { grid-template-columns: repeat(4, minmax(0, 1fr)); } .gallery.alb-grid--5 .gallery__item:first-child { grid-column: 1 / -1; } }

/* ---- an album page, sheet 02, alb-about: the event this album records (a gold-ruled panel) and the other albums of the
   same kind (a link list); stacked on phones, 7 + 4 columns from 1024 px -------------------------------------------------- */
.alb-about { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 4vw, 48px) var(--gutter); align-items: start; }
.alb-about__event .egn-panel__name a { color: inherit; text-decoration: none; transition: color var(--t-micro); }
.alb-about__event .egn-panel__name a:hover, .alb-about__event .egn-panel__name a:focus-visible { color: var(--maroon); }
.alb-about__more .label { margin-bottom: 14px; }
@media (min-width: 1024px) {
  .alb-about { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .alb-about__event { grid-column: 1 / span 7; }
  .alb-about__more { grid-column: 9 / -1; }
  .alb-about__more:first-child { grid-column: 1 / span 6; }
}

/* ---- an album without frames yet: the one highlighted statement instead of the hatched tile --------------------------- */
.alb-wait { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); }
.alb-wait .venue { grid-column: 1 / span 8; }
.alb-wait .venue__text a { color: inherit; }
@media (max-width: 1023px) { .alb-wait .venue { grid-column: 1 / -1; } }

@media (prefers-reduced-motion: reduce) {
  .gal-high__slide, .gal-high__slide img, .gal-high__fill, .gal-high__btn, .gal-high__btn svg, .alb-more__summary, .alb-more__name a { transition: none !important; }
  .gal-high__slide img { transform: none !important; }
  .gal-high__fill { display: none; }
}
html[data-motion="reduced"] .gal-high__slide, html[data-motion="reduced"] .gal-high__slide img, html[data-motion="reduced"] .gal-high__fill { transition: none !important; }
html[data-motion="reduced"] .gal-high__slide img { transform: none !important; }
@media (forced-colors: active) {
  .alb-more__summary::after, .gal-high__btn { border-color: CanvasText; color: CanvasText; }
}
@media print {
  .gal-high__slide { position: static; opacity: 1; visibility: visible; }
  .gal-high__slides { aspect-ratio: auto; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  .gal-high__nav, .gal-high__track { display: none; }
}

/* =====================================================================================================================
   2026-10-24, review r1 of the events-gallery-news group: the album grids. (1) The cover is the hero plate and is left
   out of the grid (gallery_albums.py), so the grid now also has seven-frame and eight-frame shapes with no hole in the
   last row. (2) A one-frame album shows the frame at its own ratio and never wider than its source: the generator sets
   --alb-max to the source width and a shape class from the frame's ratio (wide 2:1 and over, portrait under 9:10, square,
   landscape), so a 3:1 banner runs across the band, a 480 px board stays 480 px, and a 2:3 sign is not cut to 3:2. */
.gallery.alb-grid--1 .gallery__item { max-width: var(--alb-max, none); }
.gallery.alb-grid--1.alb-shape--land .gallery__frame img { aspect-ratio: 3 / 2; }
.gallery.alb-grid--1.alb-shape--wide .gallery__item,
.gallery.alb-grid--1.alb-shape--portrait .gallery__item,
.gallery.alb-grid--1.alb-shape--square .gallery__item { grid-column: 1 / -1; }
.gallery.alb-grid--1.alb-shape--wide .gallery__frame img,
.gallery.alb-grid--1.alb-shape--portrait .gallery__frame img,
.gallery.alb-grid--1.alb-shape--square .gallery__frame img { aspect-ratio: auto; height: auto; object-fit: contain; }
.gallery.alb-grid--1.alb-shape--portrait .gallery__item { max-width: min(var(--alb-max, 520px), 520px); }
.gallery.alb-grid--1.alb-shape--square .gallery__item { max-width: min(var(--alb-max, 560px), 560px); }
@media (min-width: 640px) {
  .gallery.alb-grid--1.alb-shape--wide .gallery__item { grid-column: 1 / -1; }
  .gallery.alb-grid--1.alb-shape--portrait .gallery__item, .gallery.alb-grid--1.alb-shape--square .gallery__item { grid-column: 1 / span 7; }
}
@media (min-width: 1024px) {
  .gallery.alb-grid--1.alb-shape--wide .gallery__item { grid-column: 1 / -1; }
  .gallery.alb-grid--1.alb-shape--portrait .gallery__item, .gallery.alb-grid--1.alb-shape--square .gallery__item { grid-column: 1 / span 5; }
}
/* seven frames: a wide lead, then two rows of three; eight frames: two rows of four from 1024 px */
.gallery.alb-grid--7, .gallery.alb-grid--8 { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 640px) {
  .gallery.alb-grid--7, .gallery.alb-grid--8 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gallery.alb-grid--7 .gallery__item:first-child { grid-column: 1 / -1; }
  .gallery.alb-grid--7 .gallery__item:first-child .gallery__frame img { aspect-ratio: 2 / 1; }
}
@media (min-width: 1024px) {
  .gallery.alb-grid--7 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .gallery.alb-grid--7 .gallery__item:first-child .gallery__frame img { aspect-ratio: 21 / 9; }
  .gallery.alb-grid--8 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ---- round-2 fixes (2026-10-25): the folded list is the last item of the card grid (gallery_albums.py writes where it sits:
   --more-c2/3/4, the free cells of the last row of covers when two or more are free, else a whole row). Inside a row of
   covers it sits on the cards' top line; once a filter hides cards it takes a whole row again ------------------------ */
.alb-cards__more { grid-column: var(--more-c2, 1 / -1); min-width: 0; }
.alb-cards__more .alb-more { margin-top: 0; }
@media (min-width: 900px) { .alb-cards__more { grid-column: var(--more-c3, 1 / -1); } }
@media (min-width: 1200px) { .alb-cards__more { grid-column: var(--more-c4, 1 / -1); } }
.alb-cards:has(> .alb-card[hidden]) > .alb-cards__more { grid-column: 1 / -1; }

/* ---- final review 2026-10-25: no photograph alone on the last row of a two-column album grid on a phone (the NASA album's
   fifth frame): in the five-frame grid the first frame spans the row, as it does from 640 px; in the default grid an odd last
   frame spans both columns. */
@media (max-width: 639.98px) {
  .gallery.alb-grid--5 .gallery__item:first-child { grid-column: 1 / -1; }
  .gallery.alb-grid:not([class*="alb-grid--"]) .gallery__item:last-child:nth-child(odd) { grid-column: 1 / -1; }
}
/* single-photo albums (Bangla Olympiad, Book Fair, Mathematical Olympiad): the frame is centred in the band, not left at a third */
.gallery.alb-grid--1.alb-shape--portrait .gallery__item, .gallery.alb-grid--1.alb-shape--square .gallery__item { justify-self: center; width: 100%; }
@media (min-width: 640px) {
  .gallery.alb-grid--1.alb-shape--portrait .gallery__item, .gallery.alb-grid--1.alb-shape--square .gallery__item { grid-column: 1 / -1; }
  .gallery.alb-grid--1.alb-shape--portrait .gallery__frame img { max-height: 70vh; width: auto; margin-inline: auto; }
}

/* ---- additions/illustration.css ---- */
/* ---- the Illustration tag (AI plates round, 2026-10-25): the paper label of the Campus pool plate (.abt-plate__tag),
   shared so every page that carries one of the four people-free AI plates labels it the same way. It sits top left on
   the picture itself, inside any positioned frame (.plate__frame, .ev-card__frame), so a parent skimming the page never
   takes the render for the school. The alt and the caption line say the same, so the tag is aria-hidden. ------------- */
.ill-tag {
  position: absolute;
  top: 12px; left: 12px;
  z-index: 1;
  padding: 6px 10px 5px;
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--clay);
  font: 500 11.5px / 1.2 var(--font-sans);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  pointer-events: none;
}
.ev-card__frame .ill-tag { top: 20px; left: 20px; }
/* the visible line under a plate that carries the tag: a figcaption with this class (not .plate__cap, which the build
   removes from inner pages), so the words "Illustration, not a photograph of the school" stay on the page */
.ill-note { margin-top: 10px; max-width: 46ch; }
@media print {
  .ill-tag { position: static; display: inline-block; margin-bottom: 6px; }
}

/* ---- additions/learning.css ---- */
/* ==========================================================================
   Learning group (page group "learning"): extra components
   Pages: /learning/, /learning/elementary/ ... /learning/student-support/
   Written 2026-10-11; redesigned 2026-10-24 to the new home's language (redesign-2026-10-24-pages/plans/learning.md).
   Tokens only; mobile first. Every page of the group carries body_class "lr-page", so the restyles below touch
   no other group. Prefix: lr- (the shared "pk-" kit was not built; these are this group's own copies, see
   docs/additions/learning.md). Motion: the step line, the ring and the counter in learning.js, all off under
   prefers-reduced-motion and the footer switch (PP.reduced()).
   ========================================================================== */

/* --- 1. The hero plate, mounted (all learning pages, 2026-10-24)
   The shell writes the hero photograph as a bare full-bleed plate. The home never shows a bare photograph:
   every picture sits on a paper-3 mount with a clay hairline. The plate is pulled back into the band and mounted.
   On phones it is 3:2 (not the 4:3 strip), so a 21:9 frame keeps more of its width. lr-hero-3x2 keeps a 3:2 frame
   at 3:2 on every screen (the hub, Examinations and Results open on 3:2 photographs with no 1920 px file). */
.lr-page .page-hero__plate {
  width: min(100% - 2 * var(--margin), var(--band-max));
  margin-inline: auto;
  padding: 12px;
  border: 1px solid var(--clay);
  background: var(--paper-3);
}
.lr-page .page-hero__plate img { aspect-ratio: 3 / 2; object-fit: cover; width: 100%; }
@media (min-width: 768px) { .lr-page .page-hero__plate img { aspect-ratio: 16 / 9; } }
@media (min-width: 1024px) { .lr-page .page-hero__plate img { aspect-ratio: 21 / 9; } }
.lr-page.lr-hero-3x2 .page-hero__plate img { aspect-ratio: 3 / 2; }
/* Final review 2026-10-25: one hero ratio for the whole group on a desktop. The 3:2 pages used a 16:9 frame (653 px tall
   at 1366) beside the 21:9 band (498 px) of their siblings, so paging through the section made the layout jump. Every
   page is now 21:9 from 1024 px. lr-hero-cap keeps a frame whose largest file is 960 px (A Level) at that width, centred,
   so it is never scaled up on a standard screen. */
@media (min-width: 1024px) {
  .lr-page.lr-hero-3x2 .page-hero__plate img { aspect-ratio: 21 / 9; }
  .lr-page.lr-hero-cap .page-hero__plate { max-width: 986px; }
  /* a frame whose subject fills its 16:9 height (the Book Fair lettering) keeps 16:9 but at the band's 21:9 height
     (about 498 px at 1366), so the page lines up with its siblings without cutting the words */
  .lr-page.lr-hero-169 .page-hero__plate { max-width: calc(min(100vw - 2 * var(--margin), var(--band-max)) * 9 / 21 * 16 / 9 + 26px); }
  .lr-page.lr-hero-169 .page-hero__plate img { aspect-ratio: 16 / 9; }
}

/* --- 2. One H2 voice with the home (all learning pages, 2026-10-24)
   The home sets every sheet H2 in .display-l (36 to 96 px, 300 from 1715 px); pages.css sets .section-title smaller.
   Inside the group the two are made the same, so a parent who clicks from the home reads the same headline size. */
.lr-page .section-title {
  font-size: clamp(36px, 4.8vw, 96px);
  font-weight: 400;
  line-height: 0.98;
  letter-spacing: -0.012em;
  max-width: 18ch;
}
@media (min-width: 1715px) { .lr-page .section-title { font-weight: 300; } }
.lr-page .section-title em { color: var(--maroon); font-style: italic; font-weight: inherit; }

/* The one coloured sheet of a page is full paper-2, as on the home (pages.css mixes it to 50 %). */
.lr-page .page-section--tint { background: var(--paper-2); }

/* --- 3. Sheet head (lr-head) and sheet foot (lr-foot) (all learning pages, 2026-10-24)
   The home's sheet skeleton: H2 on 10 of 12 columns, lead on 7; a foot row on a hairline with a sentence, an action
   and the source caption. The source line moves from the comments onto the page. */
.lr-head { display: grid; grid-template-columns: minmax(0, 1fr); row-gap: clamp(20px, 2.6vw, 36px); margin-bottom: clamp(32px, 4vw, 56px); }
.lr-head .lead { max-width: 54ch; }
.lr-head .section-title + * { margin-top: 0; }
@media (min-width: 1024px) {
  .lr-head { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); }
  .lr-head > .section-title { grid-column: 1 / span 10; }
  .lr-head > .lead, .lr-head > .lr-head__aside { grid-column: 1 / span 7; }
}
.lr-foot {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px var(--gutter);
  align-items: end;
  margin-top: clamp(32px, 4vw, 56px);
  padding-top: 22px;
  border-top: var(--hairline);
}
.lr-foot__text { font: 400 18px / 1.55 var(--font-serif); max-width: 62ch; }
.lr-foot__action { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; }
.lr-foot__source { max-width: 72ch; }
@media (min-width: 1024px) {
  .lr-foot { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .lr-foot__text { grid-column: 1 / span 8; }
  .lr-foot__action { grid-column: 10 / -1; justify-content: flex-end; justify-self: end; }
  .lr-foot__source { grid-column: 1 / -1; }
  .lr-foot__text:last-child, .lr-foot__source:only-child { grid-column: 1 / span 8; }
}

/* --- 4. Panel (lr-panel): the home's results-card recipe as a general box (2026-10-24)
   paper-3, a clay hairline, a 3 px coloured top rule (maroon; --gold and --ink variants). A row of them: lr-panels. */
.lr-panel {
  --lr-edge: var(--maroon);
  position: relative;
  padding: clamp(20px, 2.2vw, 30px) clamp(20px, 2.2vw, 30px) clamp(22px, 2.4vw, 32px);
  background: var(--paper-3);
  border: 1px solid var(--clay);
  border-top: 3px solid var(--lr-edge);
}
.lr-panel--gold { --lr-edge: var(--gold); }
.lr-panel--ink { --lr-edge: var(--ink); }
.lr-panel > * + * { margin-top: 12px; }
.lr-panel__title { font: 400 clamp(22px, 1.9vw, 30px) / 1.15 var(--font-serif); letter-spacing: -0.005em; }
.lr-panel__title + * { margin-top: 12px; }
.lr-panel p, .lr-panel li { font-size: 17px; line-height: 1.55; }
.lr-panel ul { list-style: none; }
.lr-panel ul li { position: relative; padding: 7px 0 7px 20px; border-bottom: var(--hairline); }
.lr-panel ul li:last-child { border-bottom: 0; }
.lr-panel ul li::before { content: ''; position: absolute; left: 0; top: 1.05em; width: 10px; height: 1px; background: var(--gold); }
.lr-panel .label + * { margin-top: 8px; }
.lr-panel__foot { margin-top: 16px; padding-top: 12px; border-top: var(--hairline); font: 400 15px / 1.5 var(--font-sans); color: var(--ink-2); }
.lr-panels { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); }
@media (min-width: 640px) { .lr-panels { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .lr-panels { grid-template-columns: repeat(3, minmax(0, 1fr)); } .lr-panels--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 640px) { .lr-panels--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 640px) and (max-width: 1023px) { .lr-panels > :last-child:nth-child(odd) { grid-column: 1 / -1; } .lr-panels--2 > :last-child:nth-child(odd) { grid-column: auto; } }
.lr-panels.lr-panels--stack { grid-template-columns: minmax(0, 1fr); }
.lr-panels.lr-panels--stack > :last-child:nth-child(odd) { grid-column: auto; }
/* a frame whose top edge must stay out of the crop (kept for any plate whose subject sits at the bottom edge) */
.lr-plate--bottom img { object-position: 50% 100%; }

/* --- 5. Contact panel (lr-call): the stage's phone line beside the people who look after it (stage pages, 2026-10-24)
   The one phone block of a stage page (one per page, plus the CTA band). The number is a full-width 44 px tap row. */
.lr-call { --lr-edge: var(--gold); }
.lr-call__rows { list-style: none; border-top: var(--hairline); }
.lr-panel .lr-call__rows li { padding-left: 0; }
.lr-panel .lr-call__rows li::before { content: none; }
.lr-call__row { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 16px; padding: 10px 0; border-bottom: var(--hairline); }
.lr-call__who { font: 400 15px / 1.4 var(--font-sans); color: var(--ink-2); }
.lr-call__num {
  display: inline-block;
  min-height: 44px;
  padding: 6px 0 4px;
  font: 300 clamp(26px, 2.2vw, 34px) / 1.1 var(--font-serif);
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
  background-image: linear-gradient(var(--gold), var(--gold));
  background-repeat: no-repeat;
  background-position: 0 calc(100% - 6px);
  background-size: 100% 1px;
}
.lr-call__num:hover, .lr-call__num:focus-visible { background-size: 100% 2px; }
.lr-call__hours { font: 400 15px / 1.5 var(--font-sans); color: var(--ink-2); }
.lr-call__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; margin-top: 18px; }
@media (max-width: 559px) { .lr-call__row { flex-direction: column; align-items: flex-start; } .lr-call__num { display: block; width: 100%; } }

/* The people sheet: the names in 8 columns, the contact panel in 4 (stage pages). */
.lr-people { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 4vw, 56px) var(--gutter); align-items: start; }
@media (min-width: 1024px) {
  .lr-people { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .lr-people__list { grid-column: 1 / span 8; }
  .lr-people__list--wide { grid-column: 1 / -1; }
  .lr-people__aside { grid-column: 10 / -1; }
  .lr-people__list--wide + .lr-people__aside { grid-column: 1 / span 5; }
}
.lr-people .people { margin-top: 0; }

/* --- 6. Steps: the home's "Visit, enquire, apply" grammar on inner pages (2026-10-24)
   main.css lays .steps five across; the stage pages have three and Examinations four. The ink line over each step is
   drawn on reveal (learning.js sets --drawn), as on the home. */
.steps.lr-steps { margin-top: clamp(28px, 3vw, 44px); }
@media (min-width: 1024px) {
  .steps.lr-steps--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .steps.lr-steps--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.lr-steps .step::before { transition: transform 700ms var(--ease-out); }
html.js-reveal .lr-steps .step:not(.is-in) { --drawn: 0; }
.lr-steps .step p a[href^="tel:"] { white-space: nowrap; }
.lr-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 28px; margin-top: clamp(24px, 3vw, 36px); }

/* --- 7. Numbers (feats) in two columns, and the counter (2026-10-24)
   .feats is the home's hairline list with the maroon numeral. On the hub six rows run in two columns from 1024 px.
   .lr-count is the counter learning.js animates; the final number is in the markup. */
.feats.lr-feats { margin-top: clamp(20px, 2.4vw, 32px); }
@media (min-width: 1024px) {
  .feats.lr-feats--2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(28px, 3vw, 56px); }
}
.lr-count { display: inline-block; min-width: 1.1ch; text-align: right; font-variant-numeric: tabular-nums lining-nums; }
.feat .feat__t a { color: inherit; text-decoration: none; background-image: linear-gradient(var(--gold), var(--gold)); background-repeat: no-repeat; background-position: 0 100%; background-size: 100% 1px; }
.feat .feat__t a:hover, .feat .feat__t a:focus-visible { background-size: 100% 2px; }

/* --- 8. Results panels on inner pages (results, senior, a-level, hub; 2026-10-24)
   The home's .result markup (ring, plain sentence, bars) reused as it is; this is only the layout around it.
   The rings and bars are drawn by learning.js when the panel comes into view; without JavaScript the final values are
   in the markup. */
.lr-results { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); margin-top: clamp(24px, 3vw, 40px); }
@media (min-width: 1024px) { .lr-results { grid-template-columns: repeat(3, minmax(0, 1fr)); } .lr-results--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 640px) and (max-width: 1023px) { .lr-results--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.lr-results .result { height: 100%; }
.lr-ring .donut__seg { transition: stroke-dasharray 900ms var(--ease-out); }
.lr-ring .grades__bar i { transition: transform 700ms var(--ease-out); }
.lr-ring.lr-ring--armed .donut__seg { stroke-dasharray: 0 100; }
.lr-ring.lr-ring--armed .grades__bar i { transform: scaleX(0); }
.lr-page .sub { margin-top: clamp(28px, 3vw, 44px); }
.lr-page .result__subj { display: flex; align-items: center; gap: 14px; margin-top: auto; padding-top: 16px; border-top: var(--hairline); color: inherit; text-decoration: none; font: 400 16px / 1.3 var(--font-sans); }
/* a 5 / 7 split: one ring left, the plain lines right (the hub's results sheet) */
.lr-split { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 4vw, 48px) var(--gutter); align-items: start; }
@media (min-width: 1024px) {
  .lr-split { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .lr-split__a { grid-column: 1 / span 5; }
  .lr-split__b { grid-column: 7 / -1; }
}

/* The home's results and subject markup carries three hook classes that main.css gives no rule (the home's script uses
   them); the checker wants every class in the HTML to have one, so here they are, harmless. */
.donut__segs { pointer-events: none; }
.grades__g { font-variant-numeric: lining-nums; }
.sub__intro { min-width: 0; }

/* --- 9. The venue panel on inner pages (2026-10-24)
   .venue is the home's paper-2 panel with the 3 px gold left rule; main.css gives it a grid-column that only matters
   inside the home's grid. Here it is a block. */
.lr-page .venue { max-width: 68ch; }
.lr-page .venue + .venue { margin-top: var(--gutter); }
.lr-page .venue__text a, .lr-page .venue p a { color: inherit; text-decoration: none; background-image: linear-gradient(var(--gold), var(--gold)); background-repeat: no-repeat; background-position: 0 calc(100% - 1px); background-size: 100% 1px; padding: 2px 0 3px; }
.lr-page .venue__text a:hover, .lr-page .venue p a:hover { background-size: 100% 2px; }
.lr-page .venue .dl { margin-top: 16px; }
.lr-page .venue .dl dd { font-size: 17px; }

/* --- 10. Photo cards (ev-grid) on the hub (2026-10-24)
   The home's events cards (whole card one link, mounted 16:9 picture, number, serif name, grey text, gold "more"
   line) for the four non-stage pages. main.css already snaps them sideways on phones. */
.lr-page .ev-grid { margin-top: clamp(24px, 3vw, 40px); }
.lr-page .ev__card:focus-visible { outline: 2px solid var(--maroon); outline-offset: 6px; }
.lr-page .ev__name { color: var(--ink); }

/* --- 11. Stage cards: a sideways snap row on phones (hub, 2026-10-24)
   Under 560 px the four 4:5 plates were four screens tall; as a snapping row they are one swipe, like the home's
   event cards. From 560 px pages.css lays them two and four across. */
@media (max-width: 559px) {
  .stage-cards.lr-snap {
    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;
  }
  .stage-cards.lr-snap > .stage { flex: 0 0 78%; scroll-snap-align: start; }
}
.lr-page .stage__name a:focus-visible::after { outline: 2px solid var(--maroon); outline-offset: 6px; }

/* --- 12. The class path (hub, Cambridge pathway, Middle; learning, 2026-10-11, revised 2026-10-24)
   The sixteen classes in a line, grouped under their four stages, like the rule on the home. A stage is a list item
   whose width in classes is --n (4, 3, 4, 5). It answers to the width of its own box: from 940 px the stages run in one
   line, from 560 px they pair up, below that they stack (one compact row per stage, 44 px cells). 2026-10-24: the stage
   names are links to the stage pages (with an invisible 44 px hit area), the Senior marker reads "O Level · AS · A Level"
   as on the home, and lr-path-quiet dims the stages that are not the page's own (the Middle page's bridge to Senior). */
.class-path { margin-top: clamp(28px, 3vw, 44px); container-type: inline-size; }
.class-path__stages {
  list-style: none;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 18px;
}
.class-path__stage { border-top: 1px solid var(--ink); padding-top: 12px; min-width: 0; }
.class-path__name {
  font: 500 11.5px / 1.2 var(--font-sans);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.class-path__name a {
  position: relative;
  display: inline-block;
  color: var(--ink);
  text-decoration: none;
  background-image: linear-gradient(var(--gold), var(--gold));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 1px;
  padding-bottom: 2px;
}
.class-path__name a::before { content: ''; position: absolute; inset: -16px -6px; }
.class-path__name a:hover, .class-path__name a:focus-visible { color: var(--maroon); background-size: 100% 2px; }
.class-path__classes {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(var(--n, 4), minmax(0, 1fr));
  margin-top: 10px;
  border-bottom: var(--hairline);
}
.class-path__classes li {
  padding: 11px 6px 13px;
  min-height: 44px;
  border-left: var(--hairline);
  font: 300 clamp(20px, 5.2vw, 28px) / 1 var(--font-serif);
  letter-spacing: -0.005em;
  font-variant-numeric: lining-nums;
  white-space: nowrap;
  min-width: 0;
}
.class-path__classes li:first-child { border-left: 0; padding-left: 0; }
.class-path__cambridge {
  margin-top: 12px;
  padding-left: 18px;
  position: relative;
  font: 500 11.5px / 1.45 var(--font-sans);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--maroon);
}
.class-path__cambridge::before { content: ''; position: absolute; left: 0; top: 0.78em; width: 10px; height: 1px; background: var(--maroon); }
.class-path__stage.lr-path-quiet { border-top-color: var(--clay); }
.class-path__stage.lr-path-quiet .class-path__classes li, .class-path__stage.lr-path-quiet .class-path__name { color: var(--ink-2); opacity: 0.72; }
.class-path__stage.lr-path-quiet .class-path__name a { color: var(--ink-2); opacity: 1; }
@container (min-width: 560px) {
  .class-path__stages { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gutter); row-gap: 26px; }
  .class-path__classes li { font-size: clamp(20px, 3.4cqw, 26px); padding: 14px 6px 16px; }
}
@container (min-width: 940px) {
  .class-path__stages { grid-template-columns: repeat(16, minmax(0, 1fr)); column-gap: 14px; row-gap: 0; }
  .class-path__stage { grid-column: span var(--n, 4); }
  .class-path__classes li { padding: 16px 6px 18px; font-size: clamp(18px, 2cqw, 28px); }
}

/* --- 13. The subject ledger (/learning/a-level/, learning, 2026-10-11; on paper since 2026-10-24)
   A numbered, single-column list of subjects in large serif type. The night variant stays for the record; the page
   now sets it on paper, because the footer is the site's only dark block. */
.subject-ledger { list-style: none; border-top: 1px solid var(--ink); }
.subject-ledger__item {
  display: grid;
  grid-template-columns: 52px minmax(0, 1fr);
  align-items: baseline;
  padding: 14px 0 16px;
  border-bottom: var(--hairline);
}
.subject-ledger__n {
  font: 500 11.5px / 1 var(--font-sans);
  letter-spacing: 0.14em;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}
.subject-ledger__name { font: 300 clamp(26px, 3vw, 44px) / 1.15 var(--font-serif); letter-spacing: -0.005em; }
.is-night .subject-ledger { border-top-color: var(--paper); }
.is-night .subject-ledger__item { border-bottom-color: var(--night-line); }
.is-night .subject-ledger__n { color: var(--gold-text); }

/* --- 14. Compact achievements timeline (/learning/results/, 2026-10-24)
   Eleven dated rows should not dominate the page: smaller dates, tighter rows, two columns from 1024 px. */
@media (min-width: 1024px) {
  .timeline.lr-timeline--compact { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(28px, 3vw, 56px); border-top: 0; }
  .timeline.lr-timeline--compact::before { display: none; }
  .timeline.lr-timeline--compact .timeline__item { grid-template-columns: minmax(150px, 2fr) 5fr; padding: 18px 0 20px 0; border-top: var(--hairline); border-bottom: 0; }
  .timeline.lr-timeline--compact .timeline__item::before { display: none; }
  .timeline.lr-timeline--compact .timeline__item:nth-child(-n+2) { border-top: 1px solid var(--ink); }
}
.timeline.lr-timeline--compact .timeline__date--sm { font-size: clamp(24px, 2vw, 32px); }
.timeline.lr-timeline--compact .timeline__title { font-size: clamp(19px, 1.5vw, 24px); }
.timeline.lr-timeline--compact .timeline__body p { font-size: 16px; }

/* --- 15. The mission quotation in the home's quotation style (/learning/cambridge-pathway/, 2026-10-24)
   .quote, .quote__mark, .quote__line and .quote__cite are the home's; this only spaces the block in a story column. */
.lr-page .quote { margin-top: clamp(36px, 5vw, 64px); }
.lr-page .quote__line { max-width: 26ch; }
.lr-page .quote__line--2 { max-width: 58ch; }
.lr-page .quote__cite { margin-top: clamp(20px, 2.6vw, 36px); padding-left: clamp(36px, 5vw, 80px); }

/* --- 16. Telephone numbers never break (all learning pages, 2026-10-11) */
.process__body a[href^="tel:"], .callout a[href^="tel:"], .accordion__body a[href^="tel:"], .prose a[href^="tel:"], .small-print a[href^="tel:"], .lr-panel a[href^="tel:"], .venue a[href^="tel:"] { white-space: nowrap; }

/* --- 17. Motion off (2026-10-24) */
@media (prefers-reduced-motion: reduce) {
  .lr-steps .step { --drawn: 1 !important; }
  .lr-steps .step::before, .lr-ring .donut__seg, .lr-ring .grades__bar i { transition: none !important; }
}

/* --- 18. Hero crop positions on phones (review fixes, 2026-10-24)
   Under 768 px the shell's hero is cut to 3:2 from a 21:9 or 16:9 file. Two frames need the cut moved: the Elementary
   colour wall's lettering sits in the lower part of the 21:9 frame (lr-hero-low), and the trophies on the Results page
   sit at the bottom edge of their 16:9 frame (lr-hero-bottom). The body_class of the page carries the switch. */
.lr-page.lr-hero-low .page-hero__plate img { object-position: 50% 72%; }
.lr-page.lr-hero-bottom .page-hero__plate img { object-position: 50% 100%; }
/* A 21:9 frame cut to 3:2 loses its sides, not its top, so object-position cannot save lettering that spans the width
   (the Elementary colour wall). lr-hero-swap hides the shell's plate under 768 px and shows the page's own 4:3 crop of the
   same frame (figure.lr-hero-phone, first in section 01) instead; from 768 px that figure is not rendered, so its lazy
   image is never requested. The shell's own hero is still fetched on phones (it is eager); the swap costs that one file. */
.lr-hero-phone { display: none; }
@media (max-width: 767px) {
  .lr-page.lr-hero-swap .page-hero__plate { display: none; }
  .lr-page.lr-hero-swap .lr-hero-phone { display: block; margin: 0 0 clamp(36px, 5vw, 56px); }
  .lr-page.lr-hero-swap .lr-hero-phone img { aspect-ratio: 4 / 3; object-fit: cover; width: 100%; transform: scale(1.15); transform-origin: 70% 100%; }
}

/* --- 19. Paper behind every photograph (review fixes, 2026-10-24)
   A plate that is still decoding showed as a white hole in the QA captures (the hub's Junior plate). The frame is now
   paper-2 until the picture arrives, and the four stage plates load eagerly in the markup. */
.lr-page .plate__frame { background: var(--paper-2); }

/* --- 20. Chapter navigation on phones (/learning/cambridge-pathway/, review fixes, 2026-10-24)
   pages.css lays the chapter links in one scrolling row with the scrollbar hidden, so on a 390 px screen the third link
   is cut and nothing says the row scrolls. Inside the learning group the row wraps under 600 px (two rows, 44 px links)
   and the chapters keep clear of the taller sticky index when a link jumps to them. */
@media (max-width: 599px) {
  .lr-page .chapter-nav ol { flex-wrap: wrap; gap: 0 20px; overflow-x: visible; padding: 4px 0; }
  .lr-page .chapter-nav a { padding: 12px 0 11px; min-height: 44px; }
  .lr-page .story-chapter { scroll-margin-top: calc(var(--nav-h) + 108px); }
}

/* --- 21. Disclosure (lr-disclose): a details element with the house summary row (review fixes, 2026-10-24)
   Results folds its subject grid behind one row at every width (closed in the markup; learning.js opens it when a link
   points inside it). Senior folds the same grid on phones only: lr-disclose--phone is written open, learning.js closes it
   under 600 px, and from 600 px the summary row is hidden so the grid always shows (without JavaScript it is simply open). */
.lr-disclose { margin-top: clamp(28px, 3vw, 44px); border-top: 1px solid var(--ink); }
.lr-disclose > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 60px;
  padding: 12px 0;
  font: 400 clamp(19px, 1.5vw, 24px) / 1.3 var(--font-serif);
  color: var(--ink);
}
.lr-disclose > summary::-webkit-details-marker { display: none; }
.lr-disclose > summary::after {
  content: '+';
  flex: none;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--clay);
  font: 300 28px / 1 var(--font-serif);
  color: var(--maroon);
}
.lr-disclose[open] > summary::after { content: '\2212'; }
.lr-disclose > summary:hover { color: var(--maroon); }
.lr-disclose > summary:focus-visible { outline: 2px solid var(--maroon); outline-offset: 4px; }
.lr-disclose > summary .lr-disclose__open { display: none; }
.lr-disclose[open] > summary .lr-disclose__open { display: inline; }
.lr-disclose[open] > summary .lr-disclose__closed { display: none; }
.lr-disclose .lr-disclose__body { padding-bottom: 8px; }
.lr-disclose .sub { margin-top: 12px; }
@media (min-width: 600px) {
  .lr-disclose--phone { border-top: 0; margin-top: 0; }
  .lr-disclose--phone > summary { display: none; }
}

/* --- 22. "More answers" row above the pager (stage pages, review fixes, 2026-10-24)
   The FAQ sheet's aside (a label and two links beside the accordion) left the stage pages to shorten them on phones; the
   two links sit on a hairline row above the pager instead, with 44 px hit areas. */
.lr-more { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 28px; margin-bottom: clamp(20px, 2.6vw, 36px); padding-bottom: 10px; border-bottom: var(--hairline); }
.lr-more .label { margin: 0; }
.lr-more a { display: inline-flex; align-items: center; min-height: 44px; }

/* --- 23. The split's figure fills its column (stage pages 03, review fixes, 2026-10-24)
   Beside a venue panel and a link list the 4:5 plate is the taller element; it stays at the top of the row. */
.lr-page .split .split__figure { margin-top: 0; }
.lr-page .split .link-list + .link-list, .lr-page .split .venue + .label, .lr-page .split .prose + .label { margin-top: clamp(24px, 3vw, 36px); }

/* --- 24. The further-queries row of the phone list (Examinations 05, Student support 05; review fixes r2, 2026-10-24)
   main.css stacks the two numbers of .phones__nums in a right-aligned column, so the second number sat orphaned under the row
   with no label. Inside the group the two numbers sit side by side with the footer's middle dot and, when the row is too
   narrow for label and numbers together, drop to their own line under the label, left-aligned. */
.lr-page .phones__row { flex-wrap: wrap; max-width: none; }
.lr-page .phones__nums { display: inline-flex; flex-direction: row; flex-wrap: wrap; align-items: baseline; justify-content: flex-end; gap: 4px 10px; margin-left: auto; }
.lr-page .phones__nums .foot__dot { display: inline; color: var(--ink-2); }
.lr-page .phones a { display: inline-flex; align-items: center; min-height: 44px; }
.lr-page .phones__nums a { white-space: nowrap; }
@media (max-width: 479px) {
  .lr-page .phones__nums { width: 100%; justify-content: flex-start; margin-left: 0; }
  .lr-page .phones__nums .foot__dot { display: none; }
  .lr-page .phones__nums a { flex: 1 1 100%; min-height: 40px; }
}

/* --- 25. The people sheet with one short row (Elementary 05, Junior 05; review fixes r2, 2026-10-24)
   Three names fill one row of the 8-column list while the contact panel ran four rows deep beside them. With
   lr-people--short the panel takes five columns from 1024 px and lays out in two: the line and the hours on the left, the
   button on the right, so names and panel end together. */
@media (min-width: 1024px) {
  .lr-people--short .lr-people__list { grid-column: 1 / span 7; }
  .lr-people--short .lr-people__aside { grid-column: 8 / -1; }
  .lr-people--short .lr-call { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 28px; align-items: end; }
  .lr-people--short .lr-call > .label { grid-column: 1 / -1; margin-top: 0; }
  .lr-people--short .lr-call__rows { grid-column: 1; grid-row: 2; margin-top: 12px; }
  .lr-people--short .lr-call__hours { grid-column: 1; grid-row: 3; margin-top: 10px; }
  .lr-people--short .lr-call__actions { grid-column: 2; grid-row: 2 / span 2; margin-top: 0; align-self: end; justify-self: end; padding-bottom: 2px; }
}

/* --- AI plates round (2026-10-25): /learning/senior/ sheet 03 has its figure again, the labelled AI plate
   img/learning-lab-still (4:5) beside the three panels stacked. On a phone the panels come first and the plate follows,
   at most 26rem wide; from 1024 px the plate takes 5 columns and the panels 6. */
.lr-split--fig .lr-fig { order: 2; margin: 0; max-width: 26rem; }
.lr-split--fig .lr-split__b { order: 1; }
@media (min-width: 1024px) {
  .lr-split--fig .lr-fig, .lr-split--fig .lr-split__b { order: 0; }
  .lr-split--fig .lr-fig { max-width: none; }
}

/* ---- additions/notices.css ---- */
/* notices: page-only layout for /notices/ (2026-10-22, spec redesign-2026-10-22-notices/spec.md §7).
   The notice cards themselves (nb-card, nb-status, nb-topic, nb-tile, nb-grid, nb-board, nb-empty, nb-ask, nb-count)
   are shared and live in site/css/main.css. This file only adds nbp- classes and never restyles an nb- class. */

/* 1 ---- the "Notices now" board: a warm paper-2 band, full bleed behind the band's own width (no layout change,
   no horizontal scroll: the shadow paints outside the box and clip-path keeps it to the band's height) */
.nbp-now {
  position: relative;
  padding-block: clamp(32px, 4vw, 56px);
  background: var(--paper-2);
  box-shadow: 0 0 0 100vmax var(--paper-2);
  clip-path: inset(0 -100vmax);
}

/* 2 ---- ended notices, folded in a native details (works without JS; Enter and Space open it).
   2026-10-24 (pages redesign): the label is one span and the round marker is pushed right with margin-left: auto, not
   justify-content: space-between, so "Ended notices (1)" reads as one phrase instead of a word at each end. */
.nbp-ended {
  margin-top: clamp(32px, 4vw, 48px);
  border-top: 1px solid var(--ink);
}
.nbp-ended__summary {
  position: relative;
  display: flex;
  align-items: center;
  gap: 16px;
  min-height: 56px;
  padding: 12px 0;
  font: 400 22px / 1.2 var(--font-serif);
  color: var(--ink);
  list-style: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.nbp-ended__label { flex: 1 1 auto; min-width: 0; }
.nbp-ended__summary::-webkit-details-marker { display: none; }
.nbp-ended__summary::marker { content: ''; }
.nbp-ended__summary::after {
  content: '+';
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: auto;
  width: 44px;
  height: 44px;
  border: 1px solid var(--ink-2);
  border-radius: 999px;
  font: 400 24px / 1 var(--font-sans);
  color: var(--ink);
}
.nbp-ended[open] > .nbp-ended__summary::after { content: '\2212'; }
.nbp-ended__summary:hover { color: var(--maroon); }
.nbp-ended__summary:hover::after { border-color: var(--maroon); color: var(--maroon); }
.nbp-ended__summary:focus-visible { outline: 2px solid var(--maroon); outline-offset: 2px; }
.nbp-ended[open] .nbp-ended__grid { margin-top: 16px; }

/* the phone action bar sits over the bottom of the screen: keep room under the last button */
@media (max-width: 719.98px) {
  .nbp-now { padding-bottom: 72px; }
}

@media (prefers-reduced-motion: reduce) {
  .nbp-ended__summary, .nbp-ended__summary::after { transition: none; }
}

@media (forced-colors: active) {
  .nbp-ended__summary::after { border-color: CanvasText; color: CanvasText; }
  .nbp-ended__summary:focus-visible { outline-color: Highlight; }
}

/* 3 ---- the honest empty slot on the board (review r2, 2026-10-24): the dashed box sat between the two cards and the
   ended-notices rule as a gap. On the page it takes the paper-3 panel of the cards beside it (the dashed line stays, as
   the inner edge), and it stretches to the row, so the board reads as one full row. Founder decision 6 (a reference
   card in this slot) replaces it. */
.nbp-slot {
  align-self: stretch;
  min-height: 100%;
  padding: clamp(20px, 2.2vw, 32px);
  background: var(--paper-3);
  border: 1px solid var(--clay);
  border-top: 4px solid var(--clay);
  box-shadow: inset 0 0 0 1px transparent;
}
.nbp-slot .label { color: var(--ink-2); }

/* final review 2026-10-25: the "No other notice" slot keeps its own height at the top of its cell instead of stretching to the
   height of the tallest notice beside it (a tall empty box with one line in the middle) */
.nbp-slot { align-self: start; }

/* ---- additions/portal.css ---- */
/* portal: the website portal (2026-10-23). The footer's visit-code line, the first-visit notice, the "Sent. Your code is"
   panel, the extra fields on Enquire and Book a visit, and the question helper (launcher + panel). Also linked alone by
   the home (site/css/portal.css), which loads no pages.css: every rule here stands on main.css's tokens only.
   Tokens only; 44 px targets; motion only through the site's own durations, none under reduced motion. */

[data-portal-only][hidden] { display: none !important; }
:root { --gold-light: rgb(241, 221, 109); /* the brand's light gold (F1DD6D): main.css has no token for it, so it is set here, where the crest, the robot's face and the focus ring use it */ --pp-actions-h: 0px; --pp-hero-offset: 0px; --pp-mono: ui-monospace, 'SFMono-Regular', 'Cascadia Mono', Consolas, 'Liberation Mono', monospace; --ppc-visor-y: 30%; /* the lit visor of assets/chat/assistant.png sits at 30 % of its height (rows 96-98 of 320) */ }

/* ---- the honeypot: never seen, never focused ---- */
.pp-hp { position: absolute !important; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; }

/* ---- footer: "Your visit code: V-7K3Q9M" ---- */
.foot__visit {
  flex-basis: 100%;
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 18px;
  margin-top: 4px; padding-top: 16px; border-top: 1px solid var(--night-line);
  font: 400 14px / 1.5 var(--font-sans); color: var(--bone-dim);
}
.foot__visit[hidden] { display: none; }
.foot__visit-code { font: 500 15px / 1 var(--pp-mono); letter-spacing: 0.06em; color: var(--paper); }
.foot__visit-btn {
  min-height: 44px; padding: 0; border: 0; background: none; cursor: pointer;
  font: 500 14px / 1.2 var(--font-sans); color: var(--gold-text);
  text-decoration: underline; text-underline-offset: 4px; text-decoration-thickness: 1px;
}
.foot__visit-btn:hover { color: var(--paper); }
.foot__visit-more { display: inline-flex; align-items: center; min-height: 44px; font-size: 14px; }
.foot__bottom .foot__visit-more { color: var(--bone-dim); }

/* ---- first-visit notice: small card, bottom left, never a wall ---- */
.pp-notice {
  position: fixed; z-index: 61;
  left: 16px; right: 88px; bottom: calc(16px + var(--pp-actions-h, 0px));
  max-width: 360px;
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px;
  padding: 14px 16px 10px;
  background: var(--paper-3); color: var(--ink);
  border: 1px solid var(--clay); border-radius: 6px;
  box-shadow: 0 18px 40px -24px rgba(28, 23, 21, 0.45);
  font: 400 14px / 1.5 var(--font-sans);
  transition: bottom var(--t-ui) var(--ease-out);
}
.pp-notice__text { flex: 1 1 220px; margin: 0; }
.pp-notice__more { color: var(--ink); }
.pp-notice__close {
  min-height: 44px; min-width: 44px; padding: 0 12px; margin-left: auto;
  border: 1px solid var(--ink); border-radius: 999px; background: transparent; color: var(--ink);
  font: 500 14px / 1 var(--font-sans); cursor: pointer;
}
.pp-notice__close:hover { color: var(--maroon); border-color: var(--maroon); }
@media (min-width: 600px) { .pp-notice { right: auto; } }

/* ---- "Sent. Your code is" ---- */
.pp-code {
  margin-top: 24px; padding: 22px 22px 18px;
  background: var(--paper-3); color: var(--ink);
  border: 1px solid var(--clay); border-left: 3px solid var(--gold); border-radius: 4px;
  max-width: 40rem;
}
.pp-code__h { margin: 0; font: 400 clamp(20px, 2vw, 24px) / 1.2 var(--font-serif); color: var(--ink); }
.pp-code__h:focus { outline: none; }
.pp-code__h:focus-visible { outline: 2px solid var(--maroon); outline-offset: 3px; }
.pp-code__code {
  margin: 10px 0 14px; font: 500 clamp(30px, 6vw, 44px) / 1.05 var(--pp-mono); letter-spacing: 0.08em; color: var(--ink);
  overflow-wrap: anywhere; user-select: all;
}
.pp-code__copy {
  display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 18px;
  border: 1px solid var(--ink); border-radius: 999px; background: transparent; color: var(--ink);
  font: 500 14px / 1 var(--font-sans); cursor: pointer;
}
.pp-code__copy:hover { color: var(--maroon); border-color: var(--maroon); }
.pp-code__keep { margin: 14px 0 0; font: 400 16px / 1.5 var(--font-serif); color: var(--ink); }
.pp-code__line { margin: 10px 0 0; font: 400 15px / 1.5 var(--font-sans); color: var(--ink-2); }
.pp-code__line .link, .pp-lines__tel { color: var(--ink); font-weight: 500; }
.pp-code__small { margin: 14px 0 0; padding-top: 10px; border-top: var(--hairline); font: 400 13px / 1.45 var(--font-sans); color: var(--ink-2); }

/* the three section lines (fallbacks and the code panel) */
.pp-lines { list-style: none; margin: 8px 0 0; padding: 0; }
.pp-lines__row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0 12px; min-height: 44px; border-bottom: var(--hairline); font: 400 14px / 1.3 var(--font-sans); }
.pp-lines__row:last-child { border-bottom: 0; }
.pp-lines__who { color: var(--ink-2); }
.pp-lines__tel { display: inline-flex; align-items: center; min-height: 44px; text-decoration: underline; text-underline-offset: 4px; }

/* ---- Enquire and Book a visit: the extra questions ---- */
.page-form__consent { margin: 4px 0 22px; padding: 0; border: 0; }
.page-form__consent legend { margin-bottom: 4px; }
.page-form__checks { display: flex; flex-wrap: wrap; gap: 0 28px; }
.page-form__when { margin: 4px 0 22px; padding: 0; border: 0; }
.page-form__when legend { margin-bottom: 10px; }
.page-form__when .form-row { margin-bottom: 0; }
.form-notice .pp-fail { margin-bottom: 8px; font-weight: 500; color: var(--maroon); }

/* ---- the question helper: the Admissions Desk launcher (2026-10-23 v3, figure edition, no face) ----
   A maroon pill with a gold-ringed crest, a title and a status line. The crest holds the assistant figure (a robot
   bust, /assets/chat/assistant.png) once the launcher has drawn it (.has-fig); until then it is the gold "P" monogram.
   On arrival it fades in once, a gold sheen crosses the crest once, the halo breathes once and the visor pulses once;
   after ~4.8 s nothing moves until the visitor acts (one window of motion under the 5 s line of WCAG 2.2.2). Under
   reduced motion it simply appears. The figure file is opaque (no alpha), so the halo is blended above it with screen:
   it brightens the dark ground around the bust and leaves the bust itself as it is. */
.ppc-launch {
  position: fixed; z-index: 62;
  right: 16px; bottom: calc(16px + var(--pp-actions-h, 0px) + var(--pp-hero-offset, 0px));
  display: inline-flex; align-items: center; gap: 10px;
  height: 56px; padding: 0 18px 0 4px; max-width: calc(100vw - 32px);
  border: 1px solid rgba(200, 155, 60, 0.55); border-radius: 28px;
  background: linear-gradient(180deg, var(--maroon) 0%, var(--maroon-deep) 100%);
  box-shadow: inset 0 0 0 1px rgba(217, 178, 92, 0.22), 0 8px 24px -8px rgba(20, 17, 16, 0.45);
  color: var(--paper); text-align: left; cursor: pointer;
  animation: ppc-enter 0.45s ease-out 0.15s backwards;
  transition: bottom var(--t-ui) var(--ease-out), border-color 0.16s ease, box-shadow 0.16s ease, transform 0.16s ease;
  -webkit-tap-highlight-color: transparent;
}
.ppc-launch:hover, .ppc-launch:focus-visible { transform: translateY(-2px); border-color: var(--gold); box-shadow: inset 0 0 0 1px rgba(217, 178, 92, 0.35), 0 12px 28px -8px rgba(20, 17, 16, 0.55); }
.ppc-launch:active { transform: scale(0.985); }
/* two-tone focus ring: night outside (15:1 on the paper pages) and gold-light inside (7:1 on the maroon pill) */
.ppc-launch:focus-visible { outline: 2px solid var(--night); outline-offset: 2px; box-shadow: 0 0 0 2px var(--gold-light), inset 0 0 0 1px rgba(217, 178, 92, 0.35), 0 12px 28px -8px rgba(20, 17, 16, 0.55); }
/* the crest: a fixed 48 px box whatever it holds, so the pill never shifts. Layers, bottom to top: figure or monogram (1),
   halo (2, screen-blended above the opaque figure), visor light (2, later in the DOM), ring (3), sheen (::after) and the
   thinking arc (::before). */
.ppc-crest { position: relative; flex: none; width: 48px; height: 48px; border-radius: 50%; display: block; overflow: hidden; background: radial-gradient(circle at 50% 35%, var(--maroon-deep) 0%, var(--night) 100%); }
.ppc-crest__ring { position: absolute; inset: 0; display: block; width: 100%; height: 100%; transform-origin: 50% 50%; z-index: 3; }
.ppc-crest__halo { position: absolute; inset: 6px; border-radius: 50%; display: block; background: var(--gold); filter: blur(7px); opacity: 0.2; z-index: 2; mix-blend-mode: screen; pointer-events: none; animation: ppc-halo 4.2s ease-in-out 0.6s 1; transition: opacity 0.3s ease; } /* ends at 4.8 s */
.ppc-crest__fig { position: absolute; inset: 0; width: 100%; height: 100%; display: block; opacity: 0; pointer-events: none; object-fit: cover; object-position: 50% 18%; z-index: 1; } /* kept in layout (not display:none) so a lazy image still loads */
.ppc-crest__mono { position: absolute; inset: 0; display: grid; place-items: center; font: 400 22px / 1 var(--font-serif); color: var(--gold-light); letter-spacing: 0.02em; z-index: 1; }
.ppc-crest__visor { position: absolute; left: 50%; top: var(--ppc-visor-y, 30%); width: 14px; height: 3px; margin-left: -7px; margin-top: -1px; border-radius: 2px; display: block; background: var(--gold-light); filter: blur(0.6px); mix-blend-mode: screen; opacity: 0; z-index: 2; pointer-events: none; }
.ppc-launch.has-fig .ppc-crest__fig { opacity: 1; }
.ppc-launch.has-fig .ppc-crest__mono { display: none; }
.ppc-launch.has-fig .ppc-crest__visor { opacity: 0.35; animation: ppc-visor 3.2s ease-in-out 0.8s 1; }
.ppc-launch:hover .ppc-crest__halo, .ppc-launch:focus-visible .ppc-crest__halo { opacity: 0.4; }
.ppc-launch.has-fig.is-thinking .ppc-crest__visor { animation: ppc-visor 1.4s ease-in-out infinite; } /* only while a request the visitor sent is in flight, max 8 s (fetch abort) */
.ppc-crest::after { /* one finite gold sheen on first appearance */
  content: ""; position: absolute; inset: 0; display: block; pointer-events: none; z-index: 4;
  background: linear-gradient(115deg, transparent 35%, rgba(241, 221, 109, 0.45) 50%, transparent 65%);
  transform: translateX(-100%); animation: ppc-sheen 1.4s ease-in-out 0.7s 1 forwards;
}
.ppc-crest__lamp { position: absolute; right: 3px; top: 3px; width: 7px; height: 7px; border-radius: 50%; display: block; z-index: 5; background: var(--gold-light); box-shadow: 0 0 0 1.5px var(--maroon-deep), 0 0 6px rgba(241, 221, 109, 0.8); }
.ppc-launch__text { display: flex; flex-direction: column; min-width: 0; line-height: 1.15; }
.ppc-launch__title { font: 600 14px / 1.15 var(--font-sans); color: var(--paper); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ppc-launch__title--short { display: none; }
.ppc-launch__status { margin-top: 2px; font: 500 11px / 1.2 var(--font-sans); letter-spacing: 0.03em; color: var(--gold-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ppc-launch.is-pulse .ppc-crest__ring { animation: ppc-ringpulse 1.2s ease-out 1; }
.ppc-launch.is-thinking .ppc-crest::before {
  content: ""; position: absolute; inset: 1px; border-radius: 50%; display: block; z-index: 4;
  border: 1.5px solid transparent; border-top-color: var(--gold-light);
  animation: ppc-arc 1.1s linear infinite; /* only while a request the visitor started is in flight; at most 8 s (fetch abort) */
}
@keyframes ppc-enter { from { opacity: 0; transform: translateY(8px); } }
@keyframes ppc-sheen { to { transform: translateX(100%); } }
@keyframes ppc-ringpulse { 0% { opacity: 1; transform: scale(1); } 50% { opacity: 0.55; transform: scale(1.06); } 100% { opacity: 1; transform: scale(1); } }
@keyframes ppc-arc { to { transform: rotate(360deg); } }
@keyframes ppc-halo { 0%, 100% { opacity: 0.2; } 50% { opacity: 0.34; } }
@keyframes ppc-visor { 0%, 100% { opacity: 0.35; } 50% { opacity: 0.75; } }
/* phones: a shorter pill with the short title only */
@media (max-width: 479px) {
  .ppc-launch { height: 48px; padding: 0 14px 0 4px; gap: 8px; border-radius: 24px; }
  .ppc-crest { width: 40px; height: 40px; }
  .ppc-crest__halo { inset: 5px; }
  .ppc-crest__mono { font-size: 18px; }
  .ppc-crest__visor { width: 12px; height: 2.5px; margin-left: -6px; }
  .ppc-crest__lamp { width: 6px; height: 6px; right: 2px; top: 2px; }
  .ppc-launch__title { display: none; }
  .ppc-launch__title--short { display: block; }
  .ppc-launch__status { display: none; }
}
/* while the first-visit notice shows on a narrow screen, the pill folds to its crest so the two never overlap */
@media (max-width: 679px) {
  html.pp-noticed .ppc-launch__text { display: none; }
  html.pp-noticed .ppc-launch { padding-right: 4px; gap: 0; }
  html.pp-noticed .ppc-launch:not(.has-robot) { padding-left: 4px; }
}

/* ---- the live robot (2026-10-23 v4, robot edition) ----
   The founder's robot stands in a 96 px slot at the pill's left end (72 px on phones); its head and a "?" bubble peek
   above the pill's top edge. The pill grows its left padding so the text starts after the slot; the v3 crest stays in
   the flow (faded out) so nothing reflows and it is the fallback when the robot file is missing. The face (eyes, smile,
   thinking dots) is an SVG laid over the blank glass; blink, float, bob and the curious nudge are CSS animations on
   transforms and opacity only; the pointer tilt comes from --rx/--ry set by the script. Everything is aria-hidden.
   Layout: slot 96 at left 2 / bottom 2 → head top ≈ 36 px above the pill, base inside the pill. */
.ppc-launch { overflow: visible; }
.ppc-launch.has-robot { padding-left: 42px; transition: bottom var(--t-ui) var(--ease-out), border-color 0.16s ease, box-shadow 0.16s ease, transform 0.16s ease, padding-left 0.24s ease; } /* 42 + crest 48 + gap 10 = text at 100 */
.ppc-launch.has-robot .ppc-crest { opacity: 0; transition: opacity 0.2s ease; } /* kept in the flow: no reflow, still the fallback */
.ppc-bot {
  position: absolute; left: 2px; bottom: 2px; width: 96px; height: 96px; display: block; z-index: 2;
  perspective: 320px; pointer-events: none; /* only the head's hit disc and the bubble take the pointer (below) */
  --rx: 0deg; --ry: 0deg; --rz: 0deg; --ex: 0; --ey: 0; --sx: 0px;
  animation: ppc-bot-in 0.52s cubic-bezier(0.34, 1.56, 0.64, 1) 0.2s backwards;
}
.ppc-bot__shadow {
  position: absolute; left: 20%; right: 20%; bottom: 1px; height: 8px; border-radius: 50%; display: block;
  background: radial-gradient(50% 50% at 50% 50%, rgba(20, 17, 16, 0.45), rgba(20, 17, 16, 0) 70%);
  animation: ppc-shadow 3.6s ease-in-out infinite;
}
.ppc-bot__float { position: absolute; inset: 0; display: block; animation: ppc-float 3.6s ease-in-out infinite; }
.ppc-bot__tilt {
  position: absolute; inset: 0; display: block; transform-style: preserve-3d; transform-origin: 50% 100%;
  transform: rotateX(var(--rx)) rotateY(var(--ry)); rotate: var(--rz);
  transition: transform 0.16s ease-out, rotate 0.32s cubic-bezier(0.34, 1.56, 0.64, 1), scale 0.24s ease;
}
.ppc-launch.has-robot .ppc-bot__tilt { animation: ppc-wobble 0.9s ease-in-out 0.7s 1; } /* one hello on arrival */
.ppc-bot__pic, .ppc-bot__img { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.ppc-bot__img { object-fit: contain; filter: drop-shadow(0 6px 6px rgba(20, 17, 16, 0.28)); }
/* the hit disc: a transparent circle over the head (the image's head spans x 6-93 %, y 4-72 %), so the empty corners
   of the slot and the air above the head take no click and no hover; the bust stands inside the pill, which is the
   button itself. Clicks and hover bubble up to the <button>. */
.ppc-bot__hit { position: absolute; left: 5%; top: 2%; width: 90%; height: 74%; border-radius: 50%; display: block; pointer-events: auto; }
.ppc-bot__bubble { pointer-events: auto; }
/* the face */
.ppc-bot__face {
  position: absolute; inset: 0; width: 100%; height: 100%; display: block; overflow: visible;
  filter: drop-shadow(0 0 1.5px rgba(241, 221, 109, 0.9)) drop-shadow(0 0 4px rgba(217, 178, 92, 0.55));
}
.ppc-bot__eyes { transform: translate(calc(var(--ex, 0) * 1px), calc(var(--ey, 0) * 1px)); transition: transform 0.16s ease-out; }
.ppc-bot__eye { transform-box: fill-box; transform-origin: 50% 50%; transition: transform 0.2s ease; }
.ppc-bot__eye-h, .ppc-bot__smile { fill: none; stroke: var(--gold-light); stroke-linecap: round; stroke-width: 2.4; }
.ppc-bot__face pattern circle { fill: var(--gold-light); } /* the LED dots */
.ppc-bot__eye-o:first-child { fill: var(--gold-text); } /* the soft underlay below the dots */
.ppc-bot__smile { stroke-width: 2.2; transform-box: fill-box; transform-origin: 50% 50%; transition: transform 0.2s ease, opacity 0.12s ease; }
.ppc-bot__eye-h { opacity: 0; transition: opacity 0.12s ease; }
.ppc-bot__eye-o { transition: opacity 0.12s ease; }
.ppc-bot__think { fill: var(--gold-light); opacity: 0; transition: opacity 0.12s ease; }
.ppc-bot__think circle { animation: ppc-scan 1.1s ease-in-out infinite; animation-play-state: paused; }
.ppc-bot__think circle:nth-child(2) { animation-delay: 0.18s; }
.ppc-bot__think circle:nth-child(3) { animation-delay: 0.36s; }
.is-blink .ppc-bot__eye { animation: ppc-blink 0.16s ease-in-out 1; }
/* hover and keyboard focus: ^ ^ and a wider smile. Hover only on a real hover device: on touch screens :hover sticks
   after a tap, so the face would stay squinting until the next tap elsewhere. */
.ppc-launch:focus-visible .ppc-bot__eye-o { opacity: 0; }
.ppc-launch:focus-visible .ppc-bot__eye-h { opacity: 1; }
.ppc-launch:focus-visible .ppc-bot__smile { transform: scaleX(1.12); }
@media (hover: hover) {
  .ppc-launch:hover .ppc-bot__eye-o { opacity: 0; }
  .ppc-launch:hover .ppc-bot__eye-h { opacity: 1; }
  .ppc-launch:hover .ppc-bot__smile { transform: scaleX(1.12); }
}
/* curious (every 12-15 s, 1.4 s): one eye bigger, a small head tilt, the bubble nudges */
.ppc-launch.is-curious .ppc-bot__eye--r { transform: scale(1.18); }
.ppc-launch.is-curious .ppc-bot__eye--l { transform: scale(0.92); }
.ppc-launch.is-curious .ppc-bot { --rz: -6deg; }
/* thinking: three scanning dots replace the face, only while a request the visitor sent is in flight (max 8 s) */
.ppc-launch.is-thinking .ppc-bot__eyes, .ppc-launch.is-thinking .ppc-bot__smile { opacity: 0; }
.ppc-launch.is-thinking .ppc-bot__think { opacity: 1; }
.ppc-launch.is-thinking .ppc-bot__think circle { animation-play-state: running; }
/* the glass sheen slides a little against the tilt */
.ppc-bot__sheen {
  position: absolute; left: 18.24%; top: 18.36%; width: 63.53%; height: 43.74%; display: block;
  border-radius: 30% / 40%; pointer-events: none; mix-blend-mode: screen;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.26) 0%, rgba(255, 255, 255, 0.06) 32%, transparent 48%);
  transform: translateX(var(--sx, 0px)); transition: transform 0.16s ease-out;
}
/* the "?" bubble on top of the head; "Ask me" on hover / focus (fine pointers only) */
.ppc-bot__bubble {
  position: absolute; left: 60%; top: -14px; height: 26px; width: 26px; min-width: 26px; padding: 0;
  border-radius: 13px; border: 1.5px solid var(--gold); background: var(--paper); color: var(--maroon);
  box-shadow: 0 4px 10px -4px rgba(20, 17, 16, 0.5); display: grid; place-items: center; white-space: nowrap;
  font: 400 17px / 1 var(--font-serif); transform-origin: 20% 100%;
  animation: ppc-pop 0.48s cubic-bezier(0.34, 1.56, 0.64, 1) 0.9s backwards, ppc-bob 2.8s ease-in-out 1.4s infinite;
  transition: width 0.2s ease, opacity 0.2s ease;
}
.ppc-bot__tail { position: absolute; left: 7px; bottom: -4.5px; width: 7px; height: 7px; display: block; background: var(--paper); border-right: 1.5px solid var(--gold); border-bottom: 1.5px solid var(--gold); transform: rotate(45deg); }
.ppc-bot__bubble-q { display: block; padding-bottom: 1px; }
.ppc-bot__bubble-a { display: none; font: 600 11px / 1 var(--font-sans); letter-spacing: 0.04em; color: var(--maroon); animation: ppc-fade 0.16s ease 0.1s backwards; }
.ppc-launch:focus-visible .ppc-bot__bubble { width: 62px; }
.ppc-launch:focus-visible .ppc-bot__bubble-q { display: none; }
.ppc-launch:focus-visible .ppc-bot__bubble-a { display: block; }
@media (hover: hover) {
  .ppc-launch:hover .ppc-bot__bubble { width: 62px; }
  .ppc-launch:hover .ppc-bot__bubble-q { display: none; }
  .ppc-launch:hover .ppc-bot__bubble-a { display: block; }
}
/* the nudge is appended to the list (pop and bob keep their places), so they carry on instead of replaying */
.ppc-launch.is-curious .ppc-bot__bubble { animation: ppc-pop 0.48s cubic-bezier(0.34, 1.56, 0.64, 1) 0.9s backwards, ppc-bob 2.8s ease-in-out 1.4s infinite, ppc-nudge 0.9s ease-in-out 1; }
/* while the panel is open the robot sits down into the pill (96 × .56 ≈ 54 px) and the bubble and shadow go */
html.ppc-open .ppc-bot__tilt { scale: 0.56; }
html.ppc-open .ppc-bot__bubble, html.ppc-open .ppc-bot__shadow { opacity: 0; transition: opacity 0.2s ease; }
/* .is-still: the script's "stopped" state (panel open, tab hidden, reduced motion). The pure loops (float, shadow) and
   the class-driven blink are cleared; the bubble and the head carry one-shots too (pop, wobble), so those two are PAUSED
   instead: a finished one-shot keeps its end state and never replays when the class comes off again (close, alt-tab,
   the motion switch), while the bob loop freezes and resumes. */
.ppc-launch.is-still .ppc-bot__float, .ppc-launch.is-still .ppc-bot__shadow, .ppc-launch.is-still .ppc-bot__eye { animation: none; }
.ppc-launch.is-still .ppc-bot__bubble, .ppc-launch.is-still .ppc-bot__tilt { animation-play-state: paused; }
@keyframes ppc-bot-in { from { opacity: 0; transform: translateY(14px) scale(0.8); } }
@keyframes ppc-wobble { 0%, 100% { rotate: 0deg; } 25% { rotate: -6deg; } 55% { rotate: 5deg; } 80% { rotate: -2deg; } }
@keyframes ppc-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-2.5px); } }
@keyframes ppc-shadow { 0%, 100% { transform: scaleX(1); opacity: 1; } 50% { transform: scaleX(0.9); opacity: 0.7; } }
@keyframes ppc-blink { 0%, 100% { transform: scaleY(1); } 45% { transform: scaleY(0.08); } }
@keyframes ppc-pop { from { transform: scale(0); opacity: 0; } }
@keyframes ppc-bob { 0%, 100% { translate: 0 0; } 50% { translate: 0 -3px; } }
@keyframes ppc-nudge { 0%, 100% { scale: 1; rotate: 0deg; } 30% { scale: 1.18; rotate: -8deg; } 60% { scale: 1.08; rotate: 6deg; } }
@keyframes ppc-scan { 0%, 100% { opacity: 0.25; } 50% { opacity: 1; } }
@keyframes ppc-fade { from { opacity: 0; } }
/* the medallions (teaser card, panel header) show the robot's head: the image box is nudged down so the head
   centre lands near the circle's centre; the face box matches it so the face map still lines up */
.ppc-tease__fig__img.is-robot, .ppc__fig__img.is-robot { object-fit: contain; width: 104%; height: 104%; left: -2%; top: 14%; }
.ppc-tease__fig__face, .ppc__fig__face { position: absolute; inset: auto; width: 104%; height: 104%; left: -2%; top: 14%; z-index: 1; filter: drop-shadow(0 0 1.5px rgba(241, 221, 109, 0.9)); }
/* phones: a 72 px slot in the 48 px pill */
@media (max-width: 479px) {
  .ppc-launch.has-robot { padding-left: 30px; } /* 30 + crest 40 + gap 8 = text at 78 */
  .ppc-bot { width: 72px; height: 72px; left: 2px; bottom: 1px; perspective: 260px; }
  .ppc-bot__bubble { height: 22px; width: 22px; min-width: 22px; top: -10px; font-size: 14px; border-radius: 11px; }
  .ppc-bot__tail { left: 5px; width: 6px; height: 6px; bottom: -4px; }
  html.ppc-open .ppc-bot__tilt { scale: 0.62; }
}
/* the folded pill (first-visit notice on a narrow screen) keeps the slot: 42 + 48 + 14 = 104 wide, phones 30 + 40 + 8 = 78.
   The robot pill is ~285 px wide (the slot ate the air the crest pill had), so it folds 40 px earlier than the crest pill
   (719 instead of 679) to keep clear of the 360 px notice on the left. */
@media (max-width: 719px) {
  html.pp-noticed .ppc-launch.has-robot .ppc-launch__text { display: none; }
  html.pp-noticed .ppc-launch.has-robot { padding-right: 14px; gap: 0; }
}
@media (max-width: 479px) {
  html.pp-noticed .ppc-launch.has-robot { padding-right: 8px; }
}
@media (max-width: 599px) {
  html.ppc-robot.pp-noticed .pp-notice { right: 0; }
}
/* final review 2026-10-25: on phones the first-visit notice is a slim full-width bar docked at the bottom (above the sticky
   actions), not a card over the hero, and the launcher rises above it while it shows (--pp-notice-h is measured by
   portal.js), so the two never touch and the first screen keeps its photograph */
@media (max-width: 599px) {
  .pp-notice {
    left: 0; right: 0; bottom: var(--pp-actions-h, 0px); max-width: none;
    flex-wrap: nowrap; gap: 12px; padding: 8px 12px 8px 16px;
    border-width: 1px 0 0; border-radius: 0;
    box-shadow: 0 -10px 24px -18px rgba(28, 23, 21, 0.45);
    font-size: 13px; line-height: 1.4;
  }
  .pp-notice__text { flex: 1 1 auto; }
  .pp-notice__close { flex: none; }
  html.pp-noticed .ppc-launch { bottom: calc(12px + var(--pp-actions-h, 0px) + var(--pp-notice-h, 0px)); }
}

/* ---- the teaser: three real questions for this page, above the launcher ----
   The medallion (figure or monogram) rises 26 px above the card's top edge; the text sits to its right and the chips use
   the full width below. It is position:absolute inside the card, so the stacking against the launcher is unchanged. */
.ppc-tease {
  position: fixed; z-index: 63;
  right: 16px; bottom: calc(16px + 56px + 12px + var(--pp-actions-h, 0px) + var(--pp-hero-offset, 0px));
  width: min(340px, calc(100vw - 32px));
  padding: 22px 48px 12px 16px;
  background: var(--paper); color: var(--night);
  border: 1px solid var(--gold); border-left: 3px solid var(--maroon); border-radius: 12px;
  box-shadow: 0 18px 40px -20px rgba(20, 17, 16, 0.5);
  font-family: var(--font-sans);
  overflow: visible;
  opacity: 0; transform: translateY(10px);
  transition: opacity 0.24s ease, transform 0.24s ease, bottom var(--t-ui) var(--ease-out);
}
.ppc-tease.is-in { opacity: 1; transform: none; }
html.ppc-robot .ppc-tease { bottom: calc(16px + 56px + 12px + 68px + var(--pp-actions-h, 0px) + var(--pp-hero-offset, 0px)); } /* clear of the robot's head and bubble (slot top 40 px above the pill, bubble 14 + 3 bob above that, 8 px air) */
.ppc-tease__fig {
  position: absolute; left: 14px; top: -26px; width: 72px; height: 72px; border-radius: 50%; overflow: hidden; display: block;
  background: radial-gradient(circle at 50% 35%, var(--maroon-deep), var(--night));
  box-shadow: 0 0 0 2px var(--gold), 0 8px 18px -8px rgba(20, 17, 16, 0.6);
}
.ppc-tease__fig__halo { position: absolute; inset: 8px; border-radius: 50%; display: block; background: var(--gold); filter: blur(9px); opacity: 0.22; z-index: 1; mix-blend-mode: screen; pointer-events: none; } /* above the opaque figure */
.ppc-tease__fig__img { position: absolute; inset: 0; width: 100%; height: 100%; display: block; object-fit: cover; object-position: 50% 16%; z-index: 0; }
.ppc-tease__fig__mono { position: absolute; inset: 0; display: none; place-items: center; font: 400 30px / 1 var(--font-serif); color: var(--gold-light); }
.ppc-tease__fig.is-mono .ppc-tease__fig__mono { display: grid; }
.ppc-tease__fig.is-mono .ppc-tease__fig__img { opacity: 0; }
.ppc-tease__body { padding-left: 84px; min-height: 56px; }
.ppc-tease__eyebrow { margin: 0 0 4px; font: 600 11px / 1.2 var(--font-sans); letter-spacing: 0.08em; text-transform: uppercase; color: var(--maroon); }
.ppc-tease__q { margin: 0; font: 400 17px / 1.3 var(--font-serif); color: var(--night); }
.ppc-tease__trust { margin: 6px 0 10px; font: 400 12px / 1.4 var(--font-sans); color: var(--ink-2); }
.ppc-tease__chips { display: flex; flex-wrap: wrap; gap: 6px; padding-top: 4px; }
.ppc-tease__chip { border-style: solid; border-color: var(--gold); background: var(--paper); color: var(--night); }
.ppc-tease__chip:hover { background: var(--paper-2); }
.ppc-tease__foot { display: flex; justify-content: flex-end; margin-top: 4px; }
.ppc-tease__later { min-height: 44px; padding: 0 6px; border: 0; background: none; color: var(--ink-2); font: 500 13px / 1 var(--font-sans); text-decoration: underline; text-underline-offset: 4px; cursor: pointer; }
.ppc-tease__later:hover, .ppc-tease__later:focus-visible { color: var(--maroon); }
.ppc-tease__close { position: absolute; right: 2px; top: 2px; width: 44px; height: 44px; padding: 0; border: 0; border-radius: 50%; background: transparent; color: var(--ink-2); display: grid; place-items: center; cursor: pointer; }
.ppc-tease__close:hover { color: var(--maroon); background: var(--paper-2); }
.ppc-tease__chip:focus-visible, .ppc-tease__later:focus-visible, .ppc-tease__close:focus-visible { outline: 2px solid var(--maroon); outline-offset: 2px; }
@media (max-width: 479px) {
  .ppc-tease { bottom: calc(16px + 48px + 10px + var(--pp-actions-h, 0px) + var(--pp-hero-offset, 0px)); padding-top: 16px; }
  html.ppc-robot .ppc-tease { bottom: calc(16px + 48px + 10px + 46px + var(--pp-actions-h, 0px) + var(--pp-hero-offset, 0px)); }
  .ppc-tease__fig { width: 56px; height: 56px; top: -18px; left: 12px; }
  .ppc-tease__fig__halo { inset: 6px; }
  .ppc-tease__fig__mono { font-size: 24px; }
  .ppc-tease__body { padding-left: 70px; min-height: 44px; }
  html.ppc-open .ppc-tease { display: none; }
}
/* short viewports (phones in landscape): the card would leave the screen above the robot, so it stays away
   (the script also waits while the viewport is this short, and retries after a rotation) */
@media (max-height: 519px) { .ppc-tease { display: none; } }

/* ---- the panel ---- */
.ppc {
  position: fixed; z-index: 64;
  right: 16px; bottom: calc(84px + var(--pp-actions-h, 0px));
  width: min(380px, calc(100vw - 32px));
  height: min(560px, calc(100vh - 120px));
  height: min(560px, calc(100dvh - 120px));
  display: flex; flex-direction: column;
  background: var(--paper-3); color: var(--ink);
  border: 1px solid var(--clay); border-radius: 8px;
  box-shadow: 0 30px 60px -30px rgba(28, 23, 21, 0.55);
  overflow: hidden;
  font-family: var(--font-sans);
}
.ppc[hidden] { display: none; }
.ppc__head {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 10px 12px 16px;
  background: var(--night); color: var(--paper);
}
/* the small medallion in the header: decoration only, the h2 labels the dialog */
.ppc__fig {
  position: relative; flex: none; width: 36px; height: 36px; border-radius: 50%; overflow: hidden; display: block;
  background: radial-gradient(circle at 50% 35%, var(--maroon-deep), var(--night)); box-shadow: 0 0 0 1.5px var(--gold);
}
.ppc__fig__halo { position: absolute; inset: 4px; border-radius: 50%; display: block; background: var(--gold); filter: blur(5px); opacity: 0.22; z-index: 1; mix-blend-mode: screen; pointer-events: none; } /* above the opaque figure */
.ppc__fig__img { position: absolute; inset: 0; width: 100%; height: 100%; display: block; object-fit: cover; object-position: 50% 18%; z-index: 0; }
.ppc__fig__mono { position: absolute; inset: 0; display: none; place-items: center; font: 400 17px / 1 var(--font-serif); color: var(--gold-light); }
.ppc__fig.is-mono .ppc__fig__mono { display: grid; }
.ppc__fig.is-mono .ppc__fig__img { opacity: 0; }
.ppc__htext { flex: 1 1 auto; min-width: 0; }
.ppc__title { margin: 0; font: 400 20px / 1.2 var(--font-serif); color: var(--paper); }
.ppc__title:focus { outline: none; }
.ppc__title:focus-visible { outline: 2px solid var(--amber); outline-offset: 2px; }
.ppc__sub { margin: 4px 0 0; font: 400 12.5px / 1.45 var(--font-sans); color: var(--bone-dim); }
.ppc__close {
  flex: none; display: inline-grid; place-items: center; width: 44px; height: 44px; padding: 0;
  border: 0; border-radius: 50%; background: transparent; color: var(--paper); cursor: pointer;
}
.ppc__close:hover { background: var(--night-2); }
.ppc__close:focus-visible { outline: 2px solid var(--amber); outline-offset: 0; }

.ppc__log {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  list-style: none; margin: 0; padding: 16px 14px 8px;
  display: flex; flex-direction: column; gap: 12px;
}
.ppc__log:focus-visible { outline: 2px solid var(--maroon); outline-offset: -2px; }
.ppc__msg { max-width: 88%; }
.ppc__msg--bot { align-self: flex-start; }
.ppc__msg--me { align-self: flex-end; }
.ppc__msg--code, .ppc__msg--form { max-width: 100%; align-self: stretch; }
.ppc__text {
  margin: 0; padding: 10px 14px; border-radius: 14px 14px 14px 4px;
  background: var(--paper-2); color: var(--ink);
  font: 400 15px / 1.5 var(--font-sans); white-space: pre-line; overflow-wrap: anywhere;
}
.ppc__msg--me .ppc__text { border-radius: 14px 14px 4px 14px; background: var(--ink); color: var(--paper); }
.ppc__acts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.ppc__act {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 14px;
  border: 1px solid var(--ink); border-radius: 999px; background: transparent; color: var(--ink);
  font: 500 14px / 1.2 var(--font-sans); text-decoration: none; cursor: pointer;
}
.ppc__act:hover { color: var(--maroon); border-color: var(--maroon); }
.ppc__act--form { border-color: var(--gold); }
.ppc__src { margin: 6px 0 0 2px; font: 400 13px / 1.4 var(--font-sans); color: var(--ink-2); }
.ppc__src .link { color: var(--ink-2); display: inline-flex; align-items: center; min-height: 32px; }
.ppc__chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.ppc__chip {
  min-height: 44px; padding: 6px 14px; text-align: left;
  border: 1px dashed var(--gold); border-radius: 999px; background: var(--paper-3); color: var(--ink);
  font: 400 14px / 1.3 var(--font-sans); cursor: pointer;
}
.ppc__chip:hover { border-style: solid; background: var(--paper); }
.ppc__lines { margin-top: 6px; padding: 0 4px; }
/* suggested questions under the question box (2026-10-26): never inside or over the conversation */
.ppc__suggest { margin-top: 8px; }
.ppc__suggest[hidden] { display: none; }
.ppc__suggest .ppc__chips { margin-top: 0; }
.ppc__suggest .ppc__chips {
  flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity;
  padding-bottom: 4px; scrollbar-width: thin;
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
}
.ppc__suggest .ppc__chip { flex: none; white-space: nowrap; scroll-snap-align: start; }
.ppc__suggest .ppc__chip:last-child { margin-right: 24px; }
/* footer links and the "How this chat works" note (2026-10-26) */
.ppc__links { flex: none; display: inline-flex; gap: 2px 14px; flex-wrap: wrap; }
.ppc__about { margin: 8px 0 0; padding: 10px 12px; border-left: 3px solid var(--gold); background: var(--paper); font: 400 13px / 1.45 var(--font-sans); color: var(--ink); }
.ppc__about[hidden] { display: none; }
/* a short screen (a phone with its keyboard open): while typing, the suggestions step aside so the answer keeps the room */
@media (max-height: 560px) { .ppc__form:focus-within .ppc__suggest { display: none; } }

.ppc__typing { align-self: flex-start; display: inline-flex; gap: 5px; align-items: center; padding: 14px 16px; border-radius: 14px; background: var(--paper-2); }
.ppc__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-2); opacity: 0.35; animation: ppc-dot 1.1s var(--ease-soft) infinite; }
.ppc__dot:nth-child(2) { animation-delay: 0.15s; }
.ppc__dot:nth-child(3) { animation-delay: 0.3s; }
.ppc__typing-text { font: 400 13px / 1 var(--font-sans); color: var(--ink-2); }
@keyframes ppc-dot { 0%, 80%, 100% { opacity: 0.35; transform: none; } 40% { opacity: 1; transform: translateY(-3px); } }

.ppc__form { flex: none; padding: 10px 14px 12px; border-top: var(--hairline); background: var(--paper-3); }
.ppc__label { display: block; margin-bottom: 4px; font: 500 13px / 1.2 var(--font-sans); color: var(--ink-2); }
.ppc__row { display: flex; gap: 8px; align-items: stretch; }
.ppc__input {
  flex: 1 1 auto; min-width: 0; min-height: 44px; padding: 8px 12px;
  border: 1px solid var(--ink-2); border-radius: 999px; background: var(--paper); color: var(--ink);
  font: 400 16px / 1.3 var(--font-sans);
}
.ppc__input:focus-visible { outline: 2px solid var(--maroon); outline-offset: 2px; }
.ppc__send {
  flex: none; min-height: 44px; min-width: 64px; padding: 0 18px;
  border: 0; border-radius: 999px; background: var(--maroon); color: var(--paper);
  font: 500 15px / 1 var(--font-sans); cursor: pointer;
}
.ppc__send:hover { background: var(--maroon-deep); }
.ppc__send:disabled { opacity: 0.55; cursor: progress; }
.ppc__foot { display: flex; align-items: center; justify-content: space-between; gap: 4px 10px; margin-top: 6px; flex-wrap: wrap; }
.ppc__hint { flex: 1 1 180px; margin: 0; font: 400 12px / 1.4 var(--font-sans); color: var(--ink-2); }
.ppc__person, .ppc__how {
  flex: none; min-height: 44px; padding: 0 4px; border: 0; background: none; color: var(--ink); cursor: pointer;
  font: 500 13px / 1.2 var(--font-sans); text-decoration: underline; text-underline-offset: 4px;
}
.ppc__person:hover, .ppc__how:hover { color: var(--maroon); }

/* the short enquiry form inside the helper */
.ppc__hand { padding: 14px 14px 6px; border: 1px solid var(--clay); border-left: 3px solid var(--gold); border-radius: 4px; background: var(--paper); }
.ppc__hand-title { margin: 0; font: 400 18px / 1.25 var(--font-serif); }
.ppc__hand-title:focus { outline: none; }
.ppc__hand-title:focus-visible { outline: 2px solid var(--maroon); outline-offset: 3px; }
.ppc__hand-note { margin: 4px 0 12px; font: 400 13px / 1.45 var(--font-sans); color: var(--ink-2); }
.ppc__field { margin-bottom: 12px; }
.ppc__field input, .ppc__field select, .ppc__field textarea { min-height: 44px; font-size: 16px; }
.ppc__fhint { margin: 0; font: 400 12.5px / 1.4 var(--font-sans); color: var(--ink-2); }
.ppc__consent { margin: 0 0 10px; padding: 0; border: 0; }
.ppc__consent legend { padding: 0; margin-bottom: 2px; font: 500 13px / 1.2 var(--font-sans); color: var(--ink-2); }
.ppc__check { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; margin-right: 16px; font: 400 15px / 1.2 var(--font-sans); cursor: pointer; }
.ppc__check input { width: 20px; height: 20px; margin: 0; accent-color: var(--maroon); }
.ppc__hand-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-top: 4px; }
.ppc__hand-send { white-space: normal; text-align: center; }
.ppc__hand-cancel { min-height: 44px; padding: 0 4px; border: 0; background: none; color: var(--ink); cursor: pointer; font: 500 14px / 1 var(--font-sans); text-decoration: underline; text-underline-offset: 4px; }
.ppc__hand-status { margin-top: 6px; }
.ppc__hand-fail { margin: 0; font: 500 14px / 1.45 var(--font-sans); color: var(--maroon); }
.ppc .pp-code { margin-top: 0; padding: 16px 16px 12px; }
.ppc .pp-code__code { font-size: 30px; }
.ppc .pp-code__h { font-size: 19px; }

/* phones: the panel becomes a full-width sheet above the sticky actions */
@media (max-width: 479px) {
  .ppc {
    left: 0; right: 0; bottom: var(--pp-actions-h, 0px);
    width: 100%;
    height: min(560px, calc(100vh - 72px - var(--pp-actions-h, 0px)));
    height: min(620px, calc(100dvh - 56px - var(--pp-actions-h, 0px)));
    border-radius: 12px 12px 0 0; border-left: 0; border-right: 0; border-bottom: 0;
  }
  html.ppc-open .ppc-launch { visibility: hidden; }
  html.ppc-open .pp-notice { display: none; }
}

/* reduced motion: the site's own switch and the system setting */
@media (prefers-reduced-motion: reduce) {
  .ppc-launch, .pp-notice { transition: none; }
  .ppc__dot { animation: none; opacity: 0.7; }
  .ppc-launch, .ppc-crest::after, .ppc-crest::before, .ppc-crest__ring, .ppc-crest__halo, .ppc-crest__visor, .ppc-tease, .ppc-tease__fig { animation: none !important; transition: none !important; }
  .ppc-launch, .ppc-launch:hover, .ppc-launch:focus-visible { opacity: 1; transform: none; }
  .ppc-crest::after { display: none; }
  .ppc-crest__halo, .ppc-launch:hover .ppc-crest__halo, .ppc-launch:focus-visible .ppc-crest__halo { opacity: 0.2; }
  .ppc-launch.has-fig .ppc-crest__visor { opacity: 0.35; }
  .ppc-launch.is-thinking .ppc-crest::before { display: none; }
  .ppc-tease { opacity: 1; transform: none; }
  /* the robot stands still, eyes open, the "?" bubble shown; hover ^ ^ and "Ask me" are state changes and stay */
  .ppc-bot, .ppc-bot__float, .ppc-bot__shadow, .ppc-bot__tilt, .ppc-bot__bubble, .ppc-bot__bubble-a, .ppc-bot__eye, .ppc-bot__think circle { animation: none !important; transition: none !important; }
  .ppc-bot__tilt { transform: none !important; rotate: 0deg !important; }
  .ppc-bot__eyes, .ppc-bot__sheen { transform: none !important; transition: none !important; }
  .ppc-bot__smile, .ppc-bot__eye-o, .ppc-bot__eye-h { transition: none !important; } /* the hover ^ ^ and wider smile switch at once, nothing glides */
  .ppc-launch.is-curious .ppc-bot__eye--r, .ppc-launch.is-curious .ppc-bot__eye--l { transform: none; }
  .ppc-launch.has-robot { transition: none; }
  .ppc-bot__bubble { opacity: 1; transform: none; }
  html.ppc-open .ppc-bot__bubble, html.ppc-open .ppc-bot__shadow { opacity: 0; }
  .ppc-launch.is-thinking .ppc-bot__think circle { animation: none !important; opacity: 0.7; }
}
html[data-motion="reduced"] .ppc-launch, html[data-motion="reduced"] .pp-notice { transition: none; }
html[data-motion="reduced"] .ppc__dot { animation: none; opacity: 0.7; }
html[data-motion="reduced"] .ppc-launch, html[data-motion="reduced"] .ppc-crest::after, html[data-motion="reduced"] .ppc-crest::before,
html[data-motion="reduced"] .ppc-crest__ring, html[data-motion="reduced"] .ppc-crest__halo, html[data-motion="reduced"] .ppc-crest__visor,
html[data-motion="reduced"] .ppc-tease, html[data-motion="reduced"] .ppc-tease__fig { animation: none !important; transition: none !important; }
html[data-motion="reduced"] .ppc-launch, html[data-motion="reduced"] .ppc-launch:hover, html[data-motion="reduced"] .ppc-launch:focus-visible { opacity: 1; transform: none; }
html[data-motion="reduced"] .ppc-crest::after { display: none; }
html[data-motion="reduced"] .ppc-crest__halo, html[data-motion="reduced"] .ppc-launch:hover .ppc-crest__halo, html[data-motion="reduced"] .ppc-launch:focus-visible .ppc-crest__halo { opacity: 0.2; }
html[data-motion="reduced"] .ppc-launch.has-fig .ppc-crest__visor { opacity: 0.35; }
html[data-motion="reduced"] .ppc-launch.is-thinking .ppc-crest::before { display: none; }
html[data-motion="reduced"] .ppc-tease { opacity: 1; transform: none; }
/* the robot under the site's own switches: the footer switch (data-motion) and the home's gate (data-tier="still") */
:is(html[data-motion="reduced"], html[data-tier="still"]) :is(.ppc-bot, .ppc-bot__float, .ppc-bot__shadow, .ppc-bot__tilt, .ppc-bot__bubble, .ppc-bot__bubble-a, .ppc-bot__eye, .ppc-bot__think circle) { animation: none !important; transition: none !important; }
:is(html[data-motion="reduced"], html[data-tier="still"]) .ppc-bot__tilt { transform: none !important; rotate: 0deg !important; }
:is(html[data-motion="reduced"], html[data-tier="still"]) :is(.ppc-bot__eyes, .ppc-bot__sheen) { transform: none !important; transition: none !important; }
:is(html[data-motion="reduced"], html[data-tier="still"]) :is(.ppc-bot__smile, .ppc-bot__eye-o, .ppc-bot__eye-h) { transition: none !important; }
:is(html[data-motion="reduced"], html[data-tier="still"]) .ppc-launch.is-curious :is(.ppc-bot__eye--r, .ppc-bot__eye--l) { transform: none; }
:is(html[data-motion="reduced"], html[data-tier="still"]) .ppc-launch.has-robot { transition: none; }
:is(html[data-motion="reduced"], html[data-tier="still"]) .ppc-bot__bubble { opacity: 1; transform: none; }
:is(html[data-motion="reduced"], html[data-tier="still"]).ppc-open :is(.ppc-bot__bubble, .ppc-bot__shadow) { opacity: 0; }
:is(html[data-motion="reduced"], html[data-tier="still"]) .ppc-launch.is-thinking .ppc-bot__think circle { animation: none !important; opacity: 0.7; }

/* menus, the lightbox and print come first */
html.menu-open .ppc-launch, html.menu-open .ppc-tease, html.menu-open .pp-notice,
html.lightbox-open .ppc-launch, html.lightbox-open .ppc-tease, html.lightbox-open .pp-notice { visibility: hidden; }
@media print {
  .ppc-launch, .ppc-tease, .ppc, .pp-notice, .foot__visit { display: none !important; }
}
html.af-printing .ppc-launch, html.af-printing .ppc-tease, html.af-printing .ppc, html.af-printing .pp-notice { display: none !important; }

/* Review 2026-10-23: the parent-or-guardian tick, the join tick and the privacy line on Enquire and Book a visit; the
   "Send another" button after a send; the admission form's note on what stays on paper. */
.page-form__guardian, .page-form__join { margin: 0 0 10px; }
.page-form__privacy { margin: 0 0 22px; }
.page-form__privacy .link { color: var(--ink); }
.pp-code__again { margin-top: 14px; padding: 0; min-height: 44px; border: 0; background: none; font: 500 15px / 1.4 var(--font-sans); color: var(--ink); text-decoration: underline; text-underline-offset: 4px; cursor: pointer; }
.pp-code__again:hover { color: var(--maroon); }
.af__keep, .af__as-note { margin: 0 0 12px; max-width: 46rem; font: 400 14px / 1.5 var(--font-sans); color: var(--ink-2); }
.af__as-note { color: var(--ink); font-weight: 500; }
.ppc__form[hidden] { display: none; }
.af__join { margin-top: 6px; }
.af__join[hidden] { display: none; }

/* ---- figure only (founder 2026-10-23): when the robot is drawn, the launcher is just the robot and its "?" bubble.
   No pill, no visible text, no "Ask me" swap. The title and status stay in the button for screen readers, so the
   button is still named "Ask the Admissions Desk, AI assistant". If the robot file fails, the pill comes back. ---- */
.ppc-launch.has-robot {
  width: 104px; height: 104px; padding: 0; gap: 0;
  border: 0; border-radius: 50%; background: transparent; box-shadow: none;
}
.ppc-launch.has-robot:hover, .ppc-launch.has-robot:focus-visible { box-shadow: none; transform: translateY(-2px); }
.ppc-launch.has-robot:focus-visible { outline: 2px solid var(--night); outline-offset: 2px; box-shadow: 0 0 0 4px var(--gold-light); }
.ppc-launch.has-robot .ppc-crest { display: none; }
.ppc-launch.has-robot .ppc-launch__text {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.ppc-launch.has-robot .ppc-bot { left: 4px; bottom: 0; }
.ppc-launch .ppc-bot__bubble-a { display: none !important; }
.ppc-launch .ppc-bot__bubble-q { display: block !important; }
.ppc-launch:hover .ppc-bot__bubble, .ppc-launch:focus-visible .ppc-bot__bubble { width: 26px; }
@media (max-width: 479px) {
  .ppc-launch.has-robot { width: 80px; height: 80px; padding: 0; }
  .ppc-launch.has-robot .ppc-bot { left: 4px; bottom: 0; }
  .ppc-launch:hover .ppc-bot__bubble, .ppc-launch:focus-visible .ppc-bot__bubble { width: 22px; }
}
@media (max-width: 719px) {
  html.pp-noticed .ppc-launch.has-robot { padding: 0; }
}

/* ---- additions/schoollife.css ---- */
/* School life group (schoollife), 2026-10-11; redesigned 2026-10-24.
   Prefix: .sl-. Tokens only, mobile first, 44 px targets, every motion stopped by the page's reduced-motion rules
   (the group adds no motion of its own: data-reveal and the plate curtain come from inner.js and pages.css).
   The group reuses the home's own classes from main.css where they are not tied to a home layout: .display-l, .lead,
   .caption, .label, .feat / .feat__n / .feat__t, .ev-grid / .ev / .ev__card / .ev__media / .ev__name / .ev__text / .ev__more,
   .venue / .venue__text, .steps / .step / .step__n, .frame / .frame__mat. The sl- rules below only place them. */

/* Page marker: the first section of every School life page carries .sl-page, so the shell's hero plate can be
   mounted for this group alone (all six pages, 2026-10-24). The bleed plate (no side mount, full width to 1600 px)
   becomes a .plate inside the band: 12 px paper-3 mount, 1 px clay line, like every photograph on the home. */
.sl-page { --sl-group: school-life; }
.page-hero:has(+ .sl-page) .page-hero__plate {
  width: min(100% - 2 * var(--margin), var(--band-max));
  margin-inline: auto;
  padding: 12px;
  border: 1px solid var(--clay);
}

/* Head: the home's sheet head grid (H2 on 10 of 12 columns, the lead on 7), all six pages, 2026-10-24 */
.sl-head { display: grid; grid-template-columns: minmax(0, 1fr); row-gap: clamp(20px, 2.6vw, 36px); margin-bottom: clamp(36px, 4.4vw, 64px); }
.sl-head > h2 { max-width: 18ch; text-wrap: balance; }
.sl-head > .lead { max-width: 54ch; }
.sl-head > .lead a { color: inherit; }
.sl-head--tight { margin-bottom: clamp(24px, 3vw, 40px); }
@media (min-width: 1024px) {
  .sl-head { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); }
  .sl-head > h2 { grid-column: 1 / span 10; }
  .sl-head > .lead { grid-column: 1 / span 7; }
}

/* Foot: the home's sheet foot (hairline, one sentence, one action, a source caption), all six pages, 2026-10-24 */
.sl-foot { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px var(--gutter); align-items: end; margin-top: clamp(36px, 4.4vw, 64px); padding-top: 24px; border-top: var(--hairline); }
.sl-foot__text { font-size: 18px; line-height: 1.55; max-width: 62ch; }
.sl-foot__text a { color: inherit; }
.sl-foot__action { display: flex; flex-wrap: wrap; gap: 12px 28px; align-items: center; font: 400 16px / 1.4 var(--font-sans); }
.sl-foot__action a { position: relative; }
.sl-foot__action a:not(.btn)::before { content: ''; position: absolute; inset: -10px -4px; }
.sl-foot__source { grid-column: 1 / -1; }
@media (min-width: 1024px) {
  .sl-foot { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .sl-foot__text { grid-column: 1 / span 8; }
  .sl-foot__action { grid-column: 10 / -1; justify-self: end; justify-content: flex-end; text-align: right; }
}
.is-night .sl-foot { border-top-color: var(--night-line); }
.is-night .sl-foot__source { color: var(--bone-dim); }

/* Panel: the home's results-card recipe as a general panel (paper-3, 1 px clay, a 3 px coloured top rule);
   --sl-edge sets the rule: maroon by default, gold with .sl-panel--gold, ink with .sl-panel--ink. All six pages, 2026-10-24 */
.sl-panel { --sl-edge: var(--maroon); position: relative; padding: clamp(20px, 2.2vw, 30px) clamp(20px, 2vw, 28px) clamp(22px, 2.4vw, 32px); background: var(--paper-3); border: 1px solid var(--clay); border-top: 3px solid var(--sl-edge); }
.sl-panel--gold { --sl-edge: var(--gold); }
.sl-panel--ink { --sl-edge: var(--ink); }
.sl-panel > * + * { margin-top: 12px; }
.sl-panel__label { display: block; }
.sl-panel__n { display: block; font: 300 clamp(28px, 2.4vw, 40px) / 1 var(--font-serif); color: var(--gold); font-variant-numeric: tabular-nums lining-nums; }
.sl-panel__value { font: 400 clamp(22px, 1.9vw, 30px) / 1.15 var(--font-serif); letter-spacing: -0.005em; max-width: 18ch; }
.sl-panel__value a { color: inherit; }
.sl-panel__text { font-size: 17px; line-height: 1.5; color: var(--ink-2); max-width: 46ch; }
.sl-panel__text a, .sl-panel p a { color: inherit; }
.sl-panel__text + .sl-panel__text { margin-top: 8px; }
.sl-panel__meta { display: block; margin-top: 14px; padding-top: 10px; border-top: var(--hairline); }
.sl-panel__links { list-style: none; display: flex; flex-direction: column; gap: 20px; margin-top: 16px; font: 400 16px / 1.4 var(--font-sans); }
.sl-panel__links a { position: relative; }
.sl-panel__links a::before { content: ''; position: absolute; inset: -8px -4px; }
.page-section--tint .sl-panel { background: var(--paper-3); }
.is-night .sl-panel { --sl-edge: var(--gold-text); background: var(--night-2); border-color: var(--night-line); border-top-color: var(--sl-edge); color: var(--paper); }
.is-night .sl-panel__n { color: var(--gold-text); }
.is-night .sl-panel__text { color: var(--bone-dim); }
.is-night .sl-panel__meta { border-top-color: var(--night-line); }

/* Panel grid: two to five panels in a row from 640 / 1024 px, one column on a phone. All six pages, 2026-10-24 */
.sl-grid { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); }
.sl-grid > li { display: flex; flex-direction: column; }
.sl-grid > li > .sl-panel { flex: 1; }
@media (min-width: 640px) {
  .sl-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .sl-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .sl-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .sl-grid--5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}
@media (min-width: 1440px) {
  .sl-grid--3w { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Feats: the home's hairline rows of a big maroon numeral and its phrase (.feat from main.css), set in columns:
   2 x 2 on a phone, 3 or 4 across from 1024 px. Hub, Sports, Clubs, 2026-10-24 */
.sl-feats { list-style: none; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--gutter); border-top: var(--hairline); }
.sl-feats .feat { grid-template-columns: minmax(0, auto) minmax(0, 1fr); align-items: baseline; padding: 18px 0; }
.sl-feats .feat__n { font-size: clamp(36px, 3.4vw, 56px); }
.sl-feats .feat__t { max-width: 22ch; }
@media (max-width: 639px) {
  .sl-feats .feat { grid-template-columns: minmax(0, 1fr); gap: 8px; }
}
@media (min-width: 1024px) {
  .sl-feats--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .sl-feats--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* Two-column block (a .venue or prose beside a panel), 7 / 5 from 1024 px. Hub, Clubs, Culture, 2026-10-24 */
.sl-two { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 4vw, 56px) var(--gutter); align-items: start; }
.sl-two > .venue { grid-column: auto; }
@media (min-width: 1024px) {
  .sl-two { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .sl-two > :first-child { grid-column: 1 / span 7; }
  .sl-two > :last-child { grid-column: 9 / -1; }
  .sl-two--even > :first-child { grid-column: 1 / span 6; }
  .sl-two--even > :last-child { grid-column: 8 / -1; }
}
/* the home's .venue is 7 of 12 columns inside its own grid; here it fills its column */
.sl-venue { grid-column: auto; max-width: none; }
.sl-venue .venue__text a { color: inherit; }
.sl-venue .label + .venue__text { margin-top: 10px; }

/* Ask the school: the one place on a page that lists what the school has not yet published, with the lines to call.
   A gold-edged panel; the open items as a plain list; the numbers as 44 px rows. All six pages, 2026-10-24.
   (Candidate for the shared kit: one phone panel for the whole site, see docs/additions/schoollife.md.) */
.sl-ask { --sl-edge: var(--gold); }
.sl-ask__grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(24px, 3vw, 40px) clamp(32px, 4vw, 64px); }
.sl-ask__grid > div > * + * { margin-top: 12px; }
.sl-ask__title { font: 400 clamp(22px, 1.9vw, 30px) / 1.15 var(--font-serif); max-width: 24ch; }
.sl-ask__title + .sl-ask__intro { margin-top: 16px; }
.sl-ask__intro { font-size: 17px; line-height: 1.55; color: var(--ink-2); max-width: 54ch; }
.sl-ask__list { list-style: none; margin-top: 14px; border-top: var(--hairline); max-width: 54ch; }
.sl-ask__list li { padding: 10px 0 10px 22px; border-bottom: var(--hairline); font-size: 17px; line-height: 1.5; position: relative; }
.sl-ask__list li::before { content: ''; position: absolute; left: 0; top: 0.95em; width: 10px; height: 1px; background: var(--gold); }
.sl-ask__lines { list-style: none; border-top: 1px solid var(--ink); }
.sl-ask__line { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 4px 20px; min-height: 44px; padding: 11px 0; border-bottom: var(--hairline); }
.sl-ask__who { font: 400 16px / 1.4 var(--font-sans); color: var(--ink-2); }
.sl-ask__line .link, .sl-ask__line a { font: 400 clamp(19px, 1.5vw, 22px) / 1.3 var(--font-serif); font-variant-numeric: tabular-nums lining-nums; white-space: nowrap; position: relative; }
.sl-ask__line a::before { content: ''; position: absolute; inset: -10px -4px; }
.sl-ask__hours { margin-top: 14px; }
.sl-ask__more { list-style: none; display: flex; flex-wrap: wrap; gap: 14px 28px; margin-top: 18px; font: 400 16px / 1.4 var(--font-sans); }
.sl-ask__more a { position: relative; }
.sl-ask__more a::before { content: ''; position: absolute; inset: -10px -4px; }
.sl-ask__review { margin-top: 20px; }
@media (min-width: 900px) {
  .sl-ask__grid { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
}

/* Hub photo cards: the home's events grid (.ev-grid from main.css) used for the five School life pages. The first two
   cards are wide. --sl-pos moves the crop's focal point per card (set with style="--sl-pos: 50% 60%", the only inline
   style the build allows). On a phone the grid is the home's snap row. /school-life/, 2026-10-24 */
.sl-cards .ev__media img { object-position: var(--sl-pos, 50% 45%); }
.sl-cards .ev__n { display: block; }
.sl-cards .ev__text { color: var(--ink-2); }
.sl-cards + .sl-foot { margin-top: clamp(40px, 5vw, 72px); }
@media (max-width: 639px) {
  .sl-cards .ev__text { max-width: none; }
}

/* The day: the home's steps (ink top line, gold numeral, an action as the title) in a 3 x 2 grid from 1024 px,
   two across from 640 px, one column on a phone; a step may carry a small mounted photograph. /school-life/school-day/, 2026-10-24 */
.sl-day .steps { grid-template-columns: minmax(0, 1fr); gap: clamp(32px, 4vw, 48px) var(--gutter); margin-top: 0; }
.sl-day .step p { max-width: 40ch; }
.sl-day .step p a { color: inherit; }
.sl-day__plate { margin-top: 18px; }
.sl-day__plate img { aspect-ratio: 3 / 2; object-fit: cover; }
@media (min-width: 640px) {
  .sl-day .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .sl-day .steps { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .sl-day .step p { max-width: 34ch; }
}

/* Bus steps: three of the home's steps in a row from 1024 px. /school-life/transport-and-safety/, 2026-10-24 */
.sl-steps .steps { margin-top: 0; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 3vw, 40px) var(--gutter); }
.sl-steps .step p { max-width: 40ch; }
.sl-steps .step p a { color: inherit; }
@media (min-width: 640px) {
  .sl-steps .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .sl-steps--3 .steps { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Safety ledger: the five safeguards as numbered panels on the night ground. /school-life/transport-and-safety/, 2026-10-24 */
.sl-safe .sl-panel { min-height: 100%; }
.sl-safe .sl-panel__value { color: var(--paper); }

/* The seven games, grouped by where they are played: three groups, each a label and a row of text tiles
   (gold numeral, the game in serif, the place as a label). /school-life/sports/, 2026-10-24 */
.sl-games { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 3vw, 40px) var(--gutter); }
.sl-games__group > .label { display: block; padding-bottom: 12px; border-bottom: 1px solid var(--ink); }
.sl-games__tiles { list-style: none; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 9.5rem), 1fr)); gap: 0 var(--gutter); }
.sl-games__tile { padding: 18px 0 20px; border-bottom: var(--hairline); }
.sl-games__n { display: block; font: 300 clamp(22px, 1.8vw, 28px) / 1 var(--font-serif); color: var(--gold); font-variant-numeric: tabular-nums lining-nums; }
.sl-games__name { display: block; margin-top: 12px; font: 400 clamp(22px, 1.8vw, 28px) / 1.1 var(--font-serif); }
.sl-games__place { display: block; margin-top: 8px; font: 400 15px / 1.45 var(--font-sans); color: var(--ink-2); }
@media (min-width: 1024px) {
  .sl-games { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .sl-games__group--3 { grid-column: span 5; }
  .sl-games__group--1 { grid-column: span 2; }
  .sl-games__group--3b { grid-column: span 5; }
}
@media (min-width: 1200px) {
  .sl-games__group--3 .sl-games__tiles, .sl-games__group--3b .sl-games__tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Activity tiles: panels inside a filter scope ([data-tags]); the script sets hidden, this hides them. A tile that
   carries a dated result has a maroon edge, the rest gold. /school-life/clubs-and-activities/, 2026-10-24 */
.sl-tiles { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); margin-top: 8px; }
.sl-tiles > li[hidden] { display: none; }
.sl-tile { --sl-edge: var(--gold); height: 100%; }
.sl-tile--proof { --sl-edge: var(--maroon); }
.sl-tile .sl-panel__value { font-size: clamp(22px, 1.8vw, 28px); }
.sl-tile__proof { font: 400 15px / 1.45 var(--font-sans); color: var(--ink); }
.sl-tile__proof time { font-variant-numeric: tabular-nums lining-nums; }
@media (min-width: 640px) {
  .sl-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .sl-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width: 1440px) {
  .sl-tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
/* chips on a phone: one row that scrolls, with a fade at the right edge as the cue */
@media (max-width: 639px) {
  .sl-chips { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; margin-inline: calc(-1 * var(--margin)); padding: 2px var(--margin) 6px; padding-right: calc(var(--margin) + 40px); -webkit-mask-image: linear-gradient(to right, var(--ink) calc(100% - 40px), transparent); mask-image: linear-gradient(to right, var(--ink) calc(100% - 40px), transparent); }
  .sl-chips::-webkit-scrollbar { display: none; }
  .sl-chips > li { flex: none; }
  .sl-chips .chip { white-space: nowrap; }
}
/* phones: a little less padding in a panel, so a stack of them stays short */
@media (max-width: 639px) {
  .sl-panel { padding: 18px 18px 20px; }
}

/* Pair: two mounted plates stacked in a split's figure column. /school-life/clubs-and-activities/, 2026-10-24 */
.sl-pair { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); }
@media (min-width: 560px) and (max-width: 899px) {
  .sl-pair { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Plate trio: one tall plate beside two landscape plates stacked, one column on a phone. /school-life/culture-and-service/, Pohela Boishakh chapter (2026-10-11, schoollife) */
.sl-trio { list-style: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); }
@media (min-width: 640px) {
  .sl-trio { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sl-trio > li:first-child { grid-row: 1 / span 2; }
  /* final review 2026-10-25: a trio of two (Culture, after the pots plate left) is a plain pair, top-aligned */
  .sl-trio:not(:has(> li:nth-child(3))) { align-items: start; }
  .sl-trio:not(:has(> li:nth-child(3))) > li:first-child { grid-row: auto; }
}

/* Ceremonial frame column: the home's maroon .frame (main.css sets it 7 of 12 columns inside its own grid) placed in a
   layout aside, with an optional small plate under it. /school-life/culture-and-service/, 2026-10-24 */
.sl-frame-col .frame { grid-column: auto; }
.sl-frame-col .frame img { aspect-ratio: 3 / 2; object-fit: cover; }
.sl-frame-col > * + * { margin-top: clamp(24px, 3vw, 40px); }

/* Timeline beside the frame: the dated rail takes 7 columns, the frame 5, from 1024 px. /school-life/culture-and-service/, 2026-10-24 */
.sl-days { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 4vw, 56px) var(--gutter); align-items: start; }
@media (min-width: 1024px) {
  .sl-days { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .sl-days > :first-child { grid-column: 1 / span 7; }
  .sl-days > :last-child { grid-column: 8 / -1; }
}

/* Chapter index on a phone: the scrolling row gets a fade at its right edge and room after the last link, so the
   last chapter no longer looks cut. Scoped to this group; the shared component is unchanged. /school-life/culture-and-service/, 2026-10-24 */
@media (max-width: 1023px) {
  .sl-chapnav ol { padding-right: 56px; -webkit-mask-image: linear-gradient(to right, var(--ink) calc(100% - 44px), transparent); mask-image: linear-gradient(to right, var(--ink) calc(100% - 44px), transparent); }
}

/* Visit prompt in the body: one sentence and one secondary button, on a hairline. Hub, Sports, 2026-10-24 */
.sl-visit { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px 28px; margin-top: clamp(32px, 4vw, 56px); padding-top: 22px; border-top: var(--hairline); }
.sl-visit__text { font-size: 17px; line-height: 1.5; color: var(--ink-2); max-width: 56ch; }

/* Story chapter heads inside the Culture story keep the display size but a shorter measure */
.story-chapter .sl-head { margin-bottom: clamp(28px, 3.4vw, 48px); }

/* Prose and lists inside a panel grid cell keep the house link style */
.sl-panel .checklist li { font-size: 16.5px; }
.sl-panel .checklist li:first-child { border-top: 0; }
.sl-panel .checklist li:last-child { border-bottom: 0; }

/* Night ground: the home's gold underline on links inside the group's components */
.is-night .sl-panel a:not(.btn), .is-night .sl-foot a:not(.btn) { color: var(--paper); background-image: linear-gradient(var(--gold-text), var(--gold-text)); }

/* ---- Review round, 2026-10-24 (schoollife) ---------------------------------------------------------------- */

/* Focal point for any plate: style="--sl-pos: 50% 25%" on figure.plate.sl-pos moves the crop (custom properties are the
   one inline style the build allows). Sports band (50% 15%: the spectators at the foot leave), Sports games plate
   (50% 85%: the match, not the top storeys), Clubs paper craft (50% 25%: the half-cut label at the foot leaves). */
.sl-pos img { object-position: var(--sl-pos, 50% 50%); }

/* Full-band plate capped at 1200 px: img/sl-march-band (the march past, 3:1, cut from the media/life-7 source) is
   catalogued "distance" and its 100 % check covered the 1200 file; wider, the front rank would be shown larger than
   that check. Inside the band, centred; no effect below 1200 + margins. /school-life/sports/ (1440 until review round 3) */
.sl-band { max-width: 1200px; margin-inline: auto; }
/* final review 2026-10-25: from 1024 px the band is shown at the content column's width (860 px), so the 1200 px video frame
   is not stretched to 1161 px and its softness reads less; the consent cap is unchanged */
@media (min-width: 1024px) { .sl-band { max-width: 860px; } }

/* A portrait plate at the frame's own ratio (the 2024 welcome board, 3:4): nothing is cut top or bottom. /school-life/culture-and-service/ */
.sl-plate--3x4 img { aspect-ratio: 3 / 4; object-fit: cover; }

/* Pair in a row: two plates side by side from 640 px (the stacked .sl-pair stays for a split's figure column). /school-life/clubs-and-activities/ */
@media (min-width: 640px) {
  .sl-pair--row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* A column of two blocks inside .sl-two (the hub's Houses venue over its visit prompt; the Sports plate over its Kit note) */
.sl-two__col > * + * { margin-top: clamp(24px, 3vw, 40px); }
.sl-two__col > .sl-visit { margin-top: clamp(24px, 3vw, 40px); }
.sl-venue .link-list { margin-top: 16px; }

/* Caption under the maroon frame: the home's .frame has none; here the plate caption sits on the maroon, in paper and gold.
   /school-life/culture-and-service/, Days the school marks */
.sl-frame-col .frame .plate__cap { position: relative; z-index: 1; margin: 12px 4px 2px; color: var(--paper); }
.sl-frame-col .frame .plate__n { color: var(--gold-text); }

/* Card counter under the hub's snap row: the home's "01 / 05" (counter__cur / counter__num from main.css), shown only on
   a phone where the row scrolls; schoollife.js moves the number with the scroll. /school-life/ */
.sl-counter { display: none; margin-top: 4px; font: 400 14px / 1 var(--font-sans); color: var(--ink-2); font-variant-numeric: tabular-nums lining-nums; white-space: nowrap; }
.sl-counter .counter__sep, .sl-counter .counter__total { color: var(--ink-2); }
@media (max-width: 639px) {
  .sl-counter { display: block; }
}

/* Activity tiles on a phone: two across with compact type, so eleven tiles take six rows instead of eleven screens.
   Under 360 px they fall back to one column. /school-life/clubs-and-activities/ */
@media (min-width: 360px) and (max-width: 639px) {
  .sl-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  .sl-tiles .sl-tile { padding: 14px 14px 16px; }
  .sl-tiles .sl-tile .sl-panel__value { font-size: 19px; max-width: none; }
  .sl-tiles .sl-tile .sl-panel__text { font-size: 15px; }
  .sl-tiles .sl-tile .sl-panel__meta { margin-top: 10px; padding-top: 8px; font-size: 13.5px; }
  .sl-tiles .sl-tile > * + * { margin-top: 8px; }
}

/* ---- Review round 3, 2026-10-24 (schoollife) --------------------------------------------------------------- */

/* Three feats on a phone: the third spans both columns of the 2 x 2 grid, so no numeral sits beside an empty cell
   under a hairline that runs across the void. Hub 01, Sports 01, Clubs 06 */
@media (max-width: 639px) {
  .sl-feats--3 .feat:last-child { grid-column: 1 / -1; }
}

/* The day's two plates sit at the foot of their step (flex column, the plate pushed down), and are 16:9 from 1024 px:
   the hairline tops of a row stay level, the plates close the row's bottom edge, and the paper under the text-only
   steps is a line or two, not a plate's height. /school-life/school-day/ */
.sl-day .step { display: flex; flex-direction: column; }
.sl-day__plate { margin-top: auto; padding-top: 18px; }
@media (min-width: 1024px) {
  .sl-day__plate img { aspect-ratio: 16 / 9; }
}

/* March past band at 3:1 (img/sl-march-band): the crop is cut from the frame, not by the plate, so it needs no focal
   point; on a phone the band is 16:9 (the middle of the frame; the marchers are shown smaller than the 100 % check's
   size, because the 1200 file is scaled down to fit). /school-life/sports/ */
.sl-band--3x1 img { aspect-ratio: 3 / 1; object-fit: cover; }
@media (max-width: 639px) {
  .sl-band--3x1 img { aspect-ratio: 16 / 9; }
}

/* Night panels on Transport 01: three of the five state one fact and carry no text line, so the row no longer
   stretches them to the tallest; each panel is as tall as what it says. /school-life/transport-and-safety/ */
/* final review 2026-10-25: the ragged heights read as uneven on the dark band; the five panels stretch to one height again */
.sl-safe { align-items: stretch; }
.sl-safe .sl-panel { min-height: 0; }
/* final review 2026-10-25: the ask box runs full width (its illustration left), so every line of "The school's lines" keeps
   the label left and the number right on one row; under 480 px every row stacks the same way */
.sl-ask-wrap > .sl-ask { grid-column: 1 / -1; }
.sl-ask__line { flex-wrap: nowrap; }
@media (max-width: 479px) { .sl-ask__line { flex-direction: column; align-items: flex-start; gap: 2px; } }

/* Days rail on Culture: the date column is wide enough for "16 December" on one line at every width from 768 px, and
   the rail's tick stays clear of the words ("Each year"). /school-life/culture-and-service/ */
@media (min-width: 768px) {
  .sl-days .timeline__item { grid-template-columns: minmax(13rem, 3fr) 6fr; padding-left: 36px; }
  .sl-days .timeline__date { white-space: nowrap; }
}

/* ---- AI plates round (2026-10-25): /school-life/transport-and-safety/ "Ask the office" carries the plan's stop-gap plate,
   the labelled AI plate img/sl-safety-still (4:5), beside the panel: under it on a phone (at most 24rem wide), 8 / 4 from
   1024 px, the plate aligned to the panel's top ---- */
.sl-ask-wrap { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(24px, 3vw, 40px) var(--gutter); align-items: start; }
.sl-ask-wrap__fig { margin: 0; max-width: 24rem; }
@media (min-width: 1024px) {
  .sl-ask-wrap { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .sl-ask-wrap > .sl-ask { grid-column: 1 / span 8; }
  .sl-ask-wrap__fig { grid-column: 9 / -1; max-width: none; }
}

/* final review 2026-10-25: School day's two plates as one pair under the six steps (/school-life/school-day/) */
.sl-day__pair { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); margin-top: clamp(32px, 4vw, 56px); }
.sl-day__pair .sl-day__plate { margin-top: 0; }
@media (min-width: 640px) { .sl-day__pair { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* final review 2026-10-25: Clubs and activities, the 13th card alone on the last row of three spans the row (/school-life/clubs-and-activities/) */
/* (with no filter on, nothing hidden) the 13th activity card spans the last row instead of standing alone beside two empty cells */
@media (min-width: 640px) { .sl-tiles:not(:has(> li[hidden])) > li:last-child:nth-child(odd) { grid-column: 1 / -1; } }
@media (min-width: 1024px) { .sl-tiles:not(:has(> li[hidden])) > li:last-child:nth-child(odd) { grid-column: auto; } .sl-tiles:not(:has(> li[hidden])) > li:last-child:nth-child(3n + 1) { grid-column: 1 / -1; } }

/* ---- additions/sitemap.css ---- */
/* ==========================================================================
   Sitemap and the Community hub (integrator, 2026-10-25; plan: redesign-2026-10-24-pages/plans/sitemap-ia.md).
   Prefix sm-. Tokens only, mobile first, 44 px targets, a reduced-motion block at the end.
   Pages: /sitemap/ (body.sm-page) and /community/ (body.sm-hub). Documented in docs/additions/sitemap.md.
   ========================================================================== */

/* ---- page markers: "Sheet 01 of 05" never breaks inside its rule */
.sm-page .sheet-rule__n, .sm-hub .sheet-rule__n { white-space: nowrap; }

/* ---- hero: the shell's page-hero, written in the body so the search form can sit in the band */
.sm-hero .page-hero__lead { max-width: 40ch; }
.sm-search { margin-top: clamp(28px, 3.4vw, 44px); max-width: 36rem; }
.sm-search .field input { min-height: 48px; }
.sm-search .btn { min-height: 48px; }
@media (min-width: 1280px) { .sm-search { grid-column: 1 / span 7; width: 100%; } }
@media (max-width: 559px) {
  .sm-search { flex-direction: column; align-items: stretch; }
  .sm-search .field { flex: none; }
  .sm-search .btn { justify-content: center; }
}

/* ---- sheet head and foot (the kit's pk-head / pk-foot recipe, under this prefix until 0-kit ships) */
.sm-sheet { scroll-margin-top: calc(var(--nav-h, 72px) + 12px); }
.sm-head { display: grid; grid-template-columns: minmax(0, 1fr); row-gap: clamp(18px, 2.4vw, 32px); margin-bottom: clamp(32px, 4.2vw, 60px); }
.sm-head > h2 { max-width: 18ch; text-wrap: balance; }
.sm-head > .lead { max-width: 54ch; }
.sm-head--tight { margin-bottom: clamp(24px, 3vw, 40px); }
@media (min-width: 900px) {
  .sm-head { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); }
  .sm-head > h2 { grid-column: 1 / span 9; }
  .sm-head > .lead { grid-column: 1 / span 7; }
}
.sm-foot { display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px var(--gutter); align-items: end; margin-top: clamp(32px, 4vw, 56px); padding-top: 24px; border-top: var(--hairline); }
.sm-foot__text { font-size: 18px; line-height: 1.55; max-width: 62ch; }
.sm-foot__note { max-width: 46ch; }
.sm-foot__note a, .sm-panel__note a { color: inherit; }
.sm-foot--end { margin-top: clamp(40px, 5vw, 64px); }
@media (min-width: 900px) {
  .sm-foot { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .sm-foot__text { grid-column: 1 / span 8; }
  .sm-foot__note { grid-column: 9 / -1; justify-self: end; text-align: right; }
}

/* ---- sheet 01: the four steps (the home's .steps, four across) and the two side panels */
.sm-steps { margin-top: 0; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.sm-steps .step p { max-width: 26ch; }
.sm-step__links { margin-top: 18px; gap: 4px; }
.sm-step__links a, .sm-list__link, .sm-chips a, .sm-help .link-list a { display: inline-flex; align-items: center; min-height: 44px; }
@media (max-width: 1023px) { .sm-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 44px var(--gutter); } }
@media (max-width: 639px) {
  .sm-steps { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  /* phones: a step's links wrap as a row, so four steps fit in about two screens */
  .sm-step__links { flex-direction: row; flex-wrap: wrap; gap: 0 22px; margin-top: 10px; }
}
.sm-panels { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); margin-top: clamp(40px, 5vw, 72px); }
@media (min-width: 720px) { .sm-panels { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.sm-panel { --sm-edge: var(--maroon); padding: clamp(20px, 2.2vw, 30px) clamp(20px, 2vw, 28px); background: var(--paper-3); border: 1px solid var(--clay); border-top: 3px solid var(--sm-edge); }
.sm-panel--gold { --sm-edge: var(--gold); }
.sm-panel__title { margin-bottom: 14px; }
.sm-panel .link-list { gap: 2px; }
.sm-panel .link-list a { display: inline-flex; align-items: center; min-height: 44px; }
.sm-panel .phones { margin-top: 4px; }
.sm-panel__note { margin-top: 14px; }

/* ---- sheet 02: the class ladder (horizontal from 900 px, vertical under it) */
.sm-ladder { list-style: none; position: relative; display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; padding-left: 28px; counter-reset: none; }
.sm-ladder::before { content: ''; position: absolute; left: 7px; top: 8px; bottom: 8px; width: 2px; background: var(--gold); }
.sm-ladder__step { position: relative; }
.sm-ladder__step::before { content: ''; position: absolute; left: -26px; top: 50%; width: 12px; height: 12px; margin-top: -6px; border-radius: 50%; background: var(--paper); border: 2px solid var(--gold); }
.sm-ladder__link { display: grid; grid-template-columns: auto minmax(0, 1fr); grid-template-areas: 'n name' 'n range'; column-gap: 16px; align-items: baseline; min-height: 72px; padding: 14px 18px; background: var(--paper); border: 1px solid var(--clay); color: inherit; text-decoration: none; transition: border-color var(--t-ui) var(--ease-soft); }
.sm-ladder__n { grid-area: n; align-self: center; color: var(--maroon); font-weight: 300; font-variant-numeric: tabular-nums lining-nums; }
.sm-ladder__name { grid-area: name; font: 400 clamp(22px, 2vw, 32px) / 1.1 var(--font-serif); }
.sm-ladder__range { grid-area: range; margin-top: 4px; font: 400 15px / 1.35 var(--font-sans); color: var(--ink-2); }
.sm-ladder__link:hover, .sm-ladder__link:focus-visible { border-color: var(--ink-2); }
.sm-ladder__link:hover .sm-ladder__name, .sm-ladder__link:focus-visible .sm-ladder__name { color: var(--maroon); }
.sm-ladder__link:focus-visible { outline-offset: 4px; }
@media (min-width: 900px) {
  .sm-ladder { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--gutter); padding: 28px 0 0; }
  .sm-ladder::before { left: 0; right: 0; top: 7px; bottom: auto; width: auto; height: 2px; }
  .sm-ladder__step::before { left: 18px; top: -27px; margin-top: 0; }
  .sm-ladder__link { height: 100%; grid-template-columns: minmax(0, 1fr); grid-template-areas: 'n' 'name' 'range'; row-gap: 6px; padding: 20px 20px 22px; align-content: start; }
  .sm-ladder__n { align-self: start; margin-bottom: 8px; }
}
.sm-chips { list-style: none; display: flex; flex-wrap: wrap; gap: 0 28px; margin-top: 8px; font: 400 16px / 1.3 var(--font-sans); }

/* ---- sheet 03: the six doors */
.sm-doors { display: grid; grid-template-columns: minmax(0, 1fr); gap: clamp(28px, 3.4vw, 48px) var(--gutter); }
@media (min-width: 900px) { .sm-doors { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.sm-door { display: flex; flex-direction: column; background: var(--paper-3); border: 1px solid var(--clay); border-top: 3px solid var(--maroon); }
.sm-door__media { padding: 10px 10px 0; }
.sm-door__media img { display: block; width: 100%; height: auto; aspect-ratio: 21 / 9; object-fit: cover; object-position: 50% 45%; }
@media (min-width: 900px) { .sm-door__media img { aspect-ratio: 16 / 10; } }
.sm-door__body { display: flex; flex-direction: column; gap: 10px; padding: clamp(18px, 2vw, 26px) clamp(18px, 2vw, 28px) clamp(20px, 2.2vw, 30px); }
.sm-door__n { color: var(--maroon); }
.sm-door__name { font: 400 clamp(28px, 2.6vw, 40px) / 1.05 var(--font-serif); }
.sm-door__link { color: inherit; text-decoration: none; background-image: linear-gradient(var(--gold), var(--gold)); background-repeat: no-repeat; background-position: 0 100%; background-size: 0 1px; transition: background-size var(--t-ui) var(--ease-out), color var(--t-ui) var(--ease-soft); }
.sm-door__link::after { content: ''; display: inline-block; width: 0.32em; height: 0.32em; margin-left: 0.32em; border-top: 1.5px solid currentColor; border-right: 1.5px solid currentColor; transform: translateY(-0.16em) rotate(45deg); }
.sm-door__link:hover, .sm-door__link:focus-visible { color: var(--maroon); background-size: 100% 1px; }
.sm-door__text { font-size: 17px; line-height: 1.5; color: var(--ink-2); max-width: 46ch; }
.sm-door__fold { margin-top: 8px; border-top: 1px solid var(--ink); }
.sm-door__sum { display: flex; align-items: center; justify-content: space-between; gap: 12px; min-height: 48px; cursor: pointer; list-style: none; font: 500 15px / 1.3 var(--font-sans); }
.sm-door__sum::-webkit-details-marker { display: none; }
.sm-door__sum::after { content: ''; flex: none; width: 9px; height: 9px; margin-right: 4px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-3px) rotate(45deg); transition: transform var(--t-ui) var(--ease-out); }
.sm-door__fold[open] > .sm-door__sum::after { transform: translateY(2px) rotate(-135deg); }
.sm-door__sum:focus-visible { outline-offset: 2px; }
.sm-door__more { margin-top: 6px; font: 400 16px / 1.4 var(--font-sans); }
.sm-door__more a { display: inline-flex; align-items: center; min-height: 44px; }
/* from 900 px the door lists are always open: the summary is only the phone's fold */
@media (min-width: 900px) {
  .sm-door__sum { pointer-events: none; min-height: 0; padding: 12px 0 2px; color: var(--ink-2); font-weight: 400; font-size: 13px; letter-spacing: 0.12em; text-transform: uppercase; }
  .sm-door__sum::after { display: none; }
}

/* ---- the hairline list of pages: label, then the one-line summary ({{children:... as="list"}}) */
.sm-list { list-style: none; padding: 0; margin: 0; counter-reset: sm-n; }
.sm-list__row { display: flex; flex-direction: column; gap: 0; padding: 6px 0 10px; border-bottom: var(--hairline); }
.sm-list__row:last-child { border-bottom: 0; }
.sm-list__link { position: relative; font: 400 clamp(18px, 1.4vw, 21px) / 1.25 var(--font-serif); align-self: flex-start; }
.sm-list__note { font: 400 14px / 1.45 var(--font-sans); color: var(--ink-2); max-width: 60ch; }
ol.sm-list > .sm-list__row { counter-increment: sm-n; padding-left: 38px; position: relative; }
ol.sm-list > .sm-list__row::before { content: counter(sm-n, decimal-leading-zero); position: absolute; left: 0; top: 18px; font: 500 12px / 1 var(--font-sans); letter-spacing: 0.1em; color: var(--maroon); font-variant-numeric: tabular-nums; }

/* ---- sheet 04: the two long folds */
.sm-folds { display: grid; grid-template-columns: minmax(0, 1fr); border-top: 1px solid var(--ink); }
.sm-fold { border-bottom: var(--hairline); scroll-margin-top: calc(var(--nav-h, 72px) + 12px); }
.sm-fold__sum { display: flex; align-items: center; justify-content: space-between; gap: 16px; min-height: 64px; padding: 10px 0; cursor: pointer; list-style: none; }
.sm-fold__sum::-webkit-details-marker { display: none; }
.sm-fold__title { font: 400 clamp(22px, 2vw, 30px) / 1.15 var(--font-serif); }
.sm-fold__icon { position: relative; flex: none; width: 44px; height: 44px; border: 1px solid var(--clay); border-radius: 50%; }
.sm-fold__icon::before, .sm-fold__icon::after { content: ''; position: absolute; left: 50%; top: 50%; width: 14px; height: 1.5px; margin: -0.75px 0 0 -7px; background: var(--ink); transition: transform var(--t-ui) var(--ease-out); }
.sm-fold__icon::after { transform: rotate(90deg); }
.sm-fold[open] .sm-fold__icon::after { transform: rotate(0deg); }
.sm-fold__sum:hover .sm-fold__title, .sm-fold__sum:focus-visible .sm-fold__title { color: var(--maroon); }
.sm-fold__sum:focus-visible { outline-offset: 2px; }
.sm-fold__body { padding: 4px 0 28px; }
.sm-fold__lead { margin-bottom: 12px; font: 400 16px / 1.4 var(--font-sans); }
.sm-fold__lead a { display: inline-flex; align-items: center; min-height: 44px; }
.sm-fold__note { margin-top: 18px; max-width: 62ch; }
@media (min-width: 900px) {
  .sm-fold__body .sm-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gutter); }
  .sm-fold__body .sm-list__row:last-child { border-bottom: var(--hairline); }
}

/* ---- sheet 05: help and site information */
.sm-help { display: grid; grid-template-columns: minmax(0, 1fr); gap: 32px var(--gutter); }
@media (min-width: 720px) { .sm-help { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.sm-help .link-list { gap: 2px; }
.sm-help__col > .label { margin-bottom: 10px; }

/* ---- the Community hub (body.sm-hub): the mounted hero plate (as the School life, Learning and Events hubs), cards
   and the current-parents panel */
.sm-hub .page-hero__plate {
  width: min(100% - 2 * var(--margin), var(--band-max));
  margin-inline: auto;
  padding: 12px;
  border: 1px solid var(--clay);
  background: var(--paper-3);
}
.sm-hub-two .lead { margin-top: clamp(18px, 2.2vw, 28px); }
.sm-hub-cards .ev__text { color: var(--ink-2); }
.sm-hub-cards .ev__n { display: block; }
.sm-hub-cards .ev__media img { object-position: var(--sm-pos, 50% 45%); }
.sm-hub-two { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gutter); }
@media (min-width: 900px) { .sm-hub-two { grid-template-columns: repeat(12, minmax(0, 1fr)); } .sm-hub-two > :first-child { grid-column: 1 / span 6; } .sm-hub-two > :last-child { grid-column: 8 / -1; } }
.sm-hub-two .lead { max-width: 40ch; }

/* ---- print: the folds print open, the search form does not print */
@media print {
  .sm-search { display: none; }
  .sm-fold__icon, .sm-door__sum::after { display: none; }
}

/* ---- reduced motion: no transitions on the ladder, the doors or the folds */
@media (prefers-reduced-motion: reduce) {
  .sm-ladder__link, .sm-door__link, .sm-door__sum::after, .sm-fold__icon::before, .sm-fold__icon::after { transition: none; }
}
html[data-motion="reduced"] .sm-ladder__link, html[data-motion="reduced"] .sm-door__link,
html[data-motion="reduced"] .sm-door__sum::after, html[data-motion="reduced"] .sm-fold__icon::after { transition: none; }
