/* Oswald, self-hosted. 12KB a weight, and it renders on a slow Dschang
   connection without a round trip to Google. */
@font-face{font-family:'Oswald';font-style:normal;font-weight:400;font-display:swap;src:url('../vendor/fonts/oswald-400.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Oswald';font-style:normal;font-weight:400;font-display:swap;src:url('../vendor/fonts/oswald-ext-400.woff2') format('woff2');unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Oswald';font-style:normal;font-weight:500;font-display:swap;src:url('../vendor/fonts/oswald-500.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Oswald';font-style:normal;font-weight:500;font-display:swap;src:url('../vendor/fonts/oswald-ext-500.woff2') format('woff2');unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Oswald';font-style:normal;font-weight:600;font-display:swap;src:url('../vendor/fonts/oswald-600.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Oswald';font-style:normal;font-weight:600;font-display:swap;src:url('../vendor/fonts/oswald-ext-600.woff2') format('woff2');unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}
@font-face{font-family:'Oswald';font-style:normal;font-weight:700;font-display:swap;src:url('../vendor/fonts/oswald-700.woff2') format('woff2');unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;}
@font-face{font-family:'Oswald';font-style:normal;font-weight:700;font-display:swap;src:url('../vendor/fonts/oswald-ext-700.woff2') format('woff2');unicode-range:U+0100-02AF,U+0304,U+0308,U+0329,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;}

/* =====================================================================
   RSC.CSS — Rainbow School Complex, authoritative design layer (2026)
   ---------------------------------------------------------------------
   This file is loaded LAST on every page and is the single source of
   truth for the redesigned components.

   WHY THIS FILE EXISTS
   The site had grown two competing token sets (tokens.css and
   theme-2026.css) plus two override layers (compat.css, nav-hotfix.css)
   carrying ~1,150 !important rules between them. Any change made in
   theme-2026.css was silently overridden before it reached the screen.
   Components are migrated into this file one at a time; the rules they
   replace are deleted from compat.css / nav-hotfix.css in the same pass,
   so the !important count goes down, never up.

   RULES FOR EDITING
   - Three colours only: brand blue, gold accent, ink. Neutrals are free.
   - Gold is for ONE primary action per section. Never for decoration.
   - One radius scale (below). One shadow scale. No new ones.
   - No !important unless deleting an old override is not yet possible.
   ===================================================================== */

:root {
  /* Type */
  --font-display: 'Source Serif 4', Georgia, 'Times New Roman', serif;
  --font-body: 'Poppins', system-ui, -apple-system, Arial, sans-serif;

  /* Shape — ONE scale, locked */
  --r-card: 14px;
  --r-media: 10px;
  --r-pill: 999px;

  /* Depth — tinted to the page, never pure black */
  --e1: 0 1px 2px rgba(12, 40, 64, .06);
  --e2: 0 6px 20px rgba(12, 40, 64, .08);
  --e3: 0 18px 44px rgba(12, 40, 64, .12);

  /* Rhythm */
  --sp-section: clamp(56px, 7vw, 104px);
  --measure: 62ch;
}

/* ---------------------------------------------------------------------
   1. TYPOGRAPHY — hierarchy by weight and colour, not raw scale
   ------------------------------------------------------------------- */
body { font-family: var(--font-body); }

h1, h2, h3, h4,
.section-title,
.hero-content h1, .hero-content .hero-h {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

.hero-content h1, .hero-content .hero-h {
  font-size: clamp(34px, 4.4vw, 60px);
  line-height: 1.06;
  font-weight: 600;
  max-width: 17ch;
  margin: 0 0 18px;
}

.section-title {
  font-size: clamp(28px, 3.1vw, 42px);
  line-height: 1.14;
  margin: 0 0 14px;
  max-width: 20ch;
}

.section-copy,
.section-lead {
  font-size: 17px;
  line-height: 1.65;
  color: var(--ink-soft, #5b6b78);
  max-width: var(--measure);
  margin: 0 0 8px;
}

.section { padding: var(--sp-section) 0; }

/* The pulsing dot above every heading is gone. So is the label itself. */
.eyebrow { display: none; }

/* ---------------------------------------------------------------------
   2. BUTTONS — gold means "the one thing to do here"
   ------------------------------------------------------------------- */
.btn-pill,
.btn-hero,
.btn-secondary-hero,
.nav-cta {
  border-radius: var(--r-pill);
  font-family: var(--font-body);
  font-weight: 600;
  letter-spacing: 0;
  transition: transform .18s ease, background-color .18s ease, box-shadow .18s ease;
  white-space: nowrap;
}

.btn-pill:active,
.btn-hero:active,
.nav-cta:active { transform: translateY(1px); }

/* Primary: gold. One per section. */
.btn-gold,
.btn-primary-action {
  background: var(--accent, #14577f);
  color: #fff;
  border: 1px solid transparent;
  box-shadow: var(--e1);
}
.btn-gold:hover,
.btn-primary-action:hover {
  background: var(--accent-dark, #0d3c5a);
  color: #fff;
}

/* Secondary: outlined brand. Everything that was gold-by-default. */
.btn-quiet {
  background: transparent;
  color: var(--brand, #14577f);
  border: 1px solid var(--line, #dcd8d0);
}
.btn-quiet:hover {
  background: var(--brand-soft, #e7ecef);
  color: var(--brand-dark, #0d3c5a);
}

/* Visible keyboard focus everywhere. Non-negotiable. */
a:focus-visible,
button:focus-visible,
.campus-card:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--accent, #14577f);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ---------------------------------------------------------------------
   3. SCHOOLS GRID — photo on top, readable body below.
   Replaces the dark scrim that was doing the minimum to make text legible.
   ------------------------------------------------------------------- */
.cards-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
}

.campus-card {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--surface, #fff);
  border: 1px solid var(--line, #dcd8d0);
  border-radius: var(--r-card);
  overflow: hidden;
  box-shadow: var(--e1);
  color: var(--ink, #0d2233);
  cursor: pointer;
  transition: box-shadow .22s ease, transform .22s ease, border-color .22s ease;
}

.campus-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--e3);
  border-color: rgba(15, 90, 137, .3);
}

/* Photo sits at full brightness. It is the school, not a texture. */
.campus-track {
  position: relative;
  inset: auto;
  height: 0;
  padding-bottom: 62%;
  overflow: hidden;
  background: var(--brand-soft, #e7ecef);
}

.campus-track .frame {
  position: absolute;
  inset: 0;
  top: 0;
  height: 100%;
  background-size: cover;
  background-position: center;
  filter: none;
  animation: none;
  transition: transform 1.2s cubic-bezier(.16, 1, .3, 1);
}
.campus-track .frame.two { opacity: 0; }
.campus-card:hover .frame.one { transform: scale(1.04); }

/* No scrim. The photo is not carrying text any more. */
.campus-card::before,
.campus-card::after { content: none; }

.campus-copy {
  position: static;
  inset: auto;
  padding: 20px 22px 22px;
  background: none;
  text-shadow: none;
  display: flex;
  flex-direction: column;
  flex: 1;
}

.campus-copy .campus-tag,
.campus-tag {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: none;
  padding: 0;
  margin: 0 0 8px;
  color: var(--brand, #14577f);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: none;
  opacity: 1;
}

.campus-copy h3 {
  font-family: var(--font-display);
  font-size: 21px;
  line-height: 1.22;
  font-weight: 600;
  margin: 0 0 6px;
  color: var(--ink, #0d2233);
}

.campus-copy p {
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink-soft, #5b6b78);
  margin: 0 0 16px;
  max-width: none;
  opacity: 1;
  text-shadow: none;
}

.campus-links {
  margin-top: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-top: 14px;
  border-top: 1px solid var(--line, #dcd8d0);
}

.campus-copy .link-arrow,
.campus-links .link-arrow {
  color: var(--brand, #14577f);
  font-weight: 600;
  font-size: 15px;
  text-shadow: none;
}
.campus-links .campus-prospectus {
  color: var(--ink-soft, #5b6b78);
  font-size: 13.5px;
  font-weight: 500;
}
.campus-links .campus-prospectus:hover { color: var(--brand, #14577f); }

/* The arrow glyph after every single link is an AI tell. Keep one, drop the rest. */
.campus-links .link-arrow .fa-long-arrow-right { display: none; }

/* ---------------------------------------------------------------------
   4. RECOGNISED BY — a quiet credibility line, not a card row
   ------------------------------------------------------------------- */
.rsc-trusted {
  padding: 26px 0;
  background: var(--surface, #fff);
  border-top: 1px solid var(--line, #dcd8d0);
  border-bottom: 1px solid var(--line, #dcd8d0);
}
.rsc-trusted .container {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px 28px;
}
.rsc-trusted-label {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-soft, #5b6b78);
}
.rsc-trusted-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
}
.rsc-trusted-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 15px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line, #dcd8d0);
  background: var(--paper, #fbfaf7);
  color: var(--ink, #0d2233);
  font-size: 13.5px;
  font-weight: 500;
}
.rsc-trusted-pill .fa { color: var(--brand, #14577f); font-size: 12px; }

/* ---------------------------------------------------------------------
   5. RESULTS — numbers breathe. No card boxes around a statistic.
   ------------------------------------------------------------------- */
.stats-three,
.stat-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
  border-top: 1px solid var(--line, #dcd8d0);
}
.stat-card {
  background: none;
  box-shadow: none;
  border: 0;
  border-right: 1px solid var(--line, #dcd8d0);
  border-radius: 0;
  padding: 30px 26px 30px 0;
  height: auto;
}
.stat-card:last-child { border-right: 0; }
.stat-card h3 {
  font-family: var(--font-display);
  font-size: clamp(38px, 4.6vw, 56px);
  font-weight: 600;
  line-height: 1;
  color: var(--brand, #14577f);
  margin: 0 0 10px;
  font-variant-numeric: lining-nums tabular-nums;
}
.stat-card p {
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--ink-soft, #5b6b78);
  margin: 0;
  max-width: 26ch;
}

/* ---------------------------------------------------------------------
   6. MOTION — sparing, and always optional
   ------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Hero background video was playing too fast. Slowed in JS; this is the
   CSS half, keeping the first frame calm while it loads. */
.hero-video,
video.hero-bg { will-change: auto; }

/* ---------------------------------------------------------------------
   7. RESPONSIVE — single column early, generous tap targets
   ------------------------------------------------------------------- */
@media (max-width: 1199px) {
  .cards-grid { grid-template-columns: repeat(2, 1fr); }
  .stats-three, .stat-grid { grid-template-columns: repeat(2, 1fr); }
  .stat-card:nth-child(2) { border-right: 0; }
}

@media (max-width: 767px) {
  .cards-grid { grid-template-columns: 1fr; gap: 18px; }
  .campus-card { min-height: 0; }
  .campus-track { padding-bottom: 56%; }

  .stats-three, .stat-grid { grid-template-columns: 1fr; }
  .stat-card {
    border-right: 0;
    border-bottom: 1px solid var(--line, #dcd8d0);
    padding: 22px 0;
  }
  .stat-card:last-child { border-bottom: 0; }

  .rsc-trusted .container { justify-content: flex-start; }
  .section-title { max-width: none; }
}

/* ---------------------------------------------------------------------
   8. FIXES FOUND IN RENDER REVIEW
   ------------------------------------------------------------------- */

/* The school-card tag was inheriting a drop shadow and stretching to the
   full card width, drawing a ghost bar between the photo and the title. */
.campus-copy .campus-tag,
.campus-tag {
  display: inline-flex;
  width: fit-content;
  max-width: 100%;
  box-shadow: none;
  border: 0;
  text-shadow: none;
}

/* Nav CTA failed contrast: ink text (#0d2233) on brand blue (#14577f) is
   about 1.9:1, well under the 4.5:1 minimum. It is also the site's single
   primary action, so it takes the gold. */
.nav-cta,
.nav-cta:link,
.nav-cta:visited {
  background: var(--accent, #14577f);
  color: #fff;
  box-shadow: var(--e1);
}
.nav-cta:hover,
.nav-cta:focus {
  background: var(--accent-dark, #0d3c5a);
  color: #fff;
}

/* Hero headline: 2 lines at desktop, not 3. */
.hero-content h1, .hero-content .hero-h { max-width: 24ch; }
.hero-content p { max-width: 54ch; font-size: 17px; }

/* The hero's darkening is owned by section 72 and is EVEN. This rule is
   the fifth stylesheet to declare .hero-slide::before and the one that
   wins, so it is the one that has to stop leaning a dark sheet across the
   left of the picture. */
.hero-slide:before {
  background: none !important;
}

/* Results ticker: the coloured dot before every item is decoration, not
   state. The text is the content. */
.marquee-bar .dot { display: none; }
.marquee-item { gap: 0; }
.marquee-item + .marquee-item::before {
  content: "";
  display: inline-block;
  width: 4px; height: 4px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .34);
  margin: 0 26px 0 0;
  vertical-align: middle;
}

/* Testimonials: quote cards and video cards were different heights and
   weights. One grid, one card treatment. */
.testimonial-card {
  display: flex;
  flex-direction: column;
  background: var(--surface, #fff);
  border: 1px solid var(--line, #dcd8d0);
  border-radius: var(--r-card);
  box-shadow: var(--e1);
  padding: 24px;
  height: 100%;
}
.testimonial-card .quote {
  font-family: var(--font-display);
  font-size: 19px;
  line-height: 1.45;
  font-weight: 400;
  color: var(--ink, #0d2233);
  margin: 0 0 16px;
}
.testimonial-card .meta {
  margin-top: auto;
  font-size: 13.5px;
  color: var(--ink-soft, #5b6b78);
}
.testimonial-card-video { padding: 0; overflow: hidden; }
.testimonial-card-video .testimonial-video-thumb {
  position: relative;
  height: 0;
  padding-bottom: 68%;
  background-size: cover;
  background-position: center;
}
.testimonial-card-video .gallery-open-link {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 20px;
  background: rgba(4, 20, 35, .28);
  transition: background .2s ease;
}
.testimonial-card-video .gallery-open-link:hover { background: rgba(4, 20, 35, .12); }
.testimonial-card-video .gallery-open-link .fa {
  width: 54px; height: 54px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, .92);
  color: var(--brand, #14577f);
  box-shadow: var(--e2);
}
.testimonial-card-video .meta { padding: 16px 20px 18px; margin-top: 0; }

/* WhatsApp float.
   The three-colour rule says this green does not belong. Keeping it anyway:
   in Cameroon WhatsApp is how parents actually make contact, and the green
   bubble is a recognised affordance, not decoration. A blue circle would be
   a cleaner palette and a worse contact button.
   What does go: the infinite pulsing ring and the heavy green glow. */
.wa-float {
  box-shadow: 0 8px 22px rgba(12, 40, 64, .22);
  animation: none;
}
.wa-float:hover {
  transform: scale(1.05);
  box-shadow: 0 12px 28px rgba(12, 40, 64, .28);
}
.wa-float::after { content: none; }

/* ---------------------------------------------------------------------
   9. NAV CTA — specificity fix
   An older rule (body.has-hero-page .site-nav:not(.nav-scrolled) .nav-cta)
   was repainting the button brand-blue while another set the label to ink,
   giving roughly 1.9:1 contrast. Matching the specificity rather than
   piling on !important.
   ------------------------------------------------------------------- */
body .site-nav .navbar-nav > li > a.nav-cta,
body.has-hero-page .site-nav:not(.nav-scrolled) .nav-cta,
body.has-hero-page .site-nav:not(.nav-scrolled) .navbar-nav > li > a.nav-cta {
  background: var(--accent, #14577f);
  color: #fff;
  border: 0;
  box-shadow: 0 2px 10px rgba(12, 40, 64, .16);
}
body .site-nav .navbar-nav > li > a.nav-cta:hover,
body.has-hero-page .site-nav:not(.nav-scrolled) .nav-cta:hover {
  background: var(--accent-dark, #0d3c5a);
  color: #fff;
}

/* ---------------------------------------------------------------------
   10. HERO PROPORTIONS
   882px of photograph with the message in the top third reads as a stock
   banner. Tightening it puts the headline and both CTAs in view on a phone
   without scrolling.
   ------------------------------------------------------------------- */
.hero .carousel,
.hero .carousel-inner,
.hero .item,
.hero-slide { min-height: clamp(460px, 68vh, 660px); }

@media (max-width: 767px) {
  .hero .carousel,
  .hero .carousel-inner,
  .hero .item,
  .hero-slide { min-height: clamp(420px, 76vh, 560px); }
  .hero-content h1, .hero-content .hero-h { font-size: clamp(28px, 8vw, 36px); max-width: none; }
  .hero-content p { font-size: 15.5px; }
}

/* ---------------------------------------------------------------------
   11. CTA HIERARCHY
   Gold was on every section button, so nothing read as the main action.
   Gold now means: the nav CTA, the hero primary, and the closing
   admission band. Everything else is a quiet outlined button.
   ------------------------------------------------------------------- */
.btn-pill.btn-quiet,
.section .btn-pill:not(.btn-gold):not(.btn-hero):not(.btn-filled) {
  background: transparent;
  color: var(--brand, #14577f);
  border: 1px solid var(--line, #dcd8d0);
  box-shadow: none;
  min-width: 0;
  padding: 13px 22px;
}
.btn-pill.btn-quiet:hover,
.section .btn-pill:not(.btn-gold):not(.btn-hero):hover {
  background: var(--brand-soft, #e7ecef);
  color: var(--brand-dark, #0d3c5a);
  border-color: rgba(15, 90, 137, .3);
}
/* the closing admission band keeps the gold */
.cta-panel .btn-pill {
  background: var(--accent, #14577f);
  color: #fff;
  border: 0;
}
.cta-panel .btn-pill:hover { background: var(--accent-dark, #0d3c5a); color: #fff; }

/* Two stats, not three. They get more room each. The rule is about STAT
   cards; a row of three picture panels in the same container is three. */
.stats-three { grid-template-columns: repeat(2, 1fr); }
.stats-three .stat-card:nth-child(2) { border-right: 0; }
.stats-three:has(.picture-panel) {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
  border-top: 0;
}
@media (max-width: 991px) {
  .stats-three:has(.picture-panel) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 575px) {
  .stats-three:has(.picture-panel) { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------
   12. BREAKING THE THREE-CARD RHYTHM
   Schools, testimonials, gallery and FAQs were all the same three-column
   card grid, one after another. A list of questions is a list, not a card
   grid, so the FAQ section becomes one and the page stops repeating itself.
   ------------------------------------------------------------------- */
.home-faq-grid {
  display: block;
  max-width: 820px;
  border-top: 1px solid var(--line, #dcd8d0);
}
.home-faq-grid .faq-item {
  background: none;
  border: 0;
  border-bottom: 1px solid var(--line, #dcd8d0);
  border-radius: 0;
  box-shadow: none;
  padding: 0;
  margin: 0;
}
.home-faq-grid .faq-question {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  background: none;
  border: 0;
  padding: 20px 2px;
  text-align: left;
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 500;
  line-height: 1.35;
  color: var(--ink, #0d2233);
  cursor: pointer;
}
.home-faq-grid .faq-question::after {
  content: "+";
  flex: none;
  font-family: var(--font-body);
  font-size: 20px;
  font-weight: 400;
  color: var(--brand, #14577f);
  transition: transform .2s ease;
}
.home-faq-grid .faq-item.is-open .faq-question::after { transform: rotate(45deg); }
.home-faq-grid .faq-question:hover { color: var(--brand, #14577f); }
.home-faq-grid .faq-answer p {
  margin: 0;
  padding: 0 2px 20px;
  color: var(--ink-soft, #5b6b78);
  font-size: 15.5px;
  line-height: 1.6;
  max-width: 68ch;
}

/* Testimonial cards: equal height, one rhythm. */
.section .cards-grid > .testimonial-card { align-self: stretch; }

/* ---------------------------------------------------------------------
   13. MOBILE
   Most parents reach this site on a phone. The hero was ~880px of
   photograph with the message in the top third, so the first screen said
   almost nothing. Older rules set 72vh from three different files, so
   these are scoped tightly enough to win without !important.
   ------------------------------------------------------------------- */
@media (max-width: 991px) {
  .hero .carousel,
  .hero .carousel-inner,
  .hero .item,
  .hero .hero-slide,
  body .hero-slide { min-height: 0; }

  .hero .hero-slide {
    padding-top: 34px;
    padding-bottom: 40px;
    min-height: min(78vh, 600px);
  }
}

@media (max-width: 767px) {
  .hero .hero-slide {
    padding-top: 28px;
    padding-bottom: 34px;
    min-height: min(74vh, 520px);
  }
  .hero-content h1, .hero-content .hero-h { font-size: clamp(27px, 7.6vw, 34px); line-height: 1.1; }
  .hero-content p { font-size: 15px; line-height: 1.55; }

  /* Full-width stacked CTAs are kept: on a phone they are the easier tap
     target, and both actions stay visible without scrolling. */
  .hero-content .btn-hero,
  .hero-content .btn-secondary-hero {
    padding: 13px 20px;
    margin: 10px 0 0;
    font-size: 15px;
  }

  /* The hero still ran to roughly 85% of the screen because its content
     box, not its min-height, was setting the size. */
  .hero .hero-slide { max-height: 68vh; }
  .hero .hero-slide .container { padding-top: 0; padding-bottom: 0; }

  /* "Rainbow School Ds..." truncated mid-word in the header. */
  .brand .brand-text,
  .brand span { display: none; }
  .brand img { height: 42px; }

  .section-title { font-size: clamp(25px, 6.6vw, 31px); }
  .rsc-trusted .container { gap: 10px; }
  .rsc-trusted-pill { font-size: 12.5px; padding: 7px 13px; }
}

/* =====================================================================
   14. PARENTS PORTAL
   ===================================================================== */
.portal-wrap { max-width: 760px; margin: 0 auto; }

.portal-card {
  background: var(--surface, #fff);
  border: 1px solid var(--line, #dcd8d0);
  border-radius: var(--r-card);
  box-shadow: var(--e2);
  padding: 28px;
}

.portal-steps { display: flex; gap: 8px; margin-bottom: 22px; }
.portal-step {
  flex: 1; text-align: center; padding: 9px 10px;
  border-radius: var(--r-pill); font-size: 13px; font-weight: 500;
  background: var(--paper, #fbfaf7); color: var(--ink-soft, #5b6b78);
  border: 1px solid var(--line, #dcd8d0);
}
.portal-step.active { background: var(--brand, #14577f); color: #fff; border-color: var(--brand, #14577f); }

/* Form. Labels above inputs, never placeholder-as-label. */
.portal-form label {
  display: block; font-size: 14px; font-weight: 600;
  color: var(--ink, #0d2233); margin-bottom: 7px;
}
.portal-form input {
  width: 100%; height: 52px;
  padding: 0 15px;
  font-size: 16px;                 /* 16px stops iOS zooming on focus */
  font-family: var(--font-body);
  color: var(--ink, #0d2233);
  background: var(--surface, #fff);
  border: 1px solid #b9cddd;
  border-radius: var(--r-media);
}
.portal-form input::placeholder { color: #7b8b99; }
.portal-form input:focus {
  outline: 3px solid var(--accent, #14577f);
  outline-offset: 2px;
  border-color: var(--brand, #14577f);
}
#portalCode { text-transform: uppercase; letter-spacing: .18em; font-weight: 600; }
.portal-form button[type="submit"] {
  width: 100%; height: 52px; margin-top: 20px;
  border: 0; border-radius: var(--r-pill);
  background: var(--accent, #14577f); color: #fff;
  font-family: var(--font-body); font-size: 16px; font-weight: 600;
  cursor: pointer;
}
.portal-form button[type="submit"]:hover { background: var(--accent-dark, #0d3c5a); }
.portal-form button[type="submit"]:disabled { opacity: .65; cursor: progress; }
.portal-hint { margin: 14px 0 0; font-size: 13.5px; line-height: 1.55; color: var(--ink-soft, #5b6b78); }

/* Error. Says what to do, not just that something failed. */
.portal-error { display: none; }
.portal-error.is-visible {
  display: block;
  margin-bottom: 20px; padding: 16px 18px;
  background: #fdf4e3;
  border: 1px solid #e8c37a;
  border-left: 3px solid var(--accent-dark, #0d3c5a);
  border-radius: var(--r-media);
  font-size: 14.5px; line-height: 1.55; color: #4a3410;
}
.portal-error strong { display: block; margin-bottom: 8px; color: #3a2806; }
.portal-error ul { margin: 0; padding-left: 18px; }
.portal-error li { margin-bottom: 5px; }
.portal-error .portal-help { display: inline-block; margin-top: 10px; font-weight: 600; color: var(--brand-dark, #0d3c5a); }

/* Child picker */
.portal-children { display: grid; gap: 10px; margin-top: 6px; }
.portal-child {
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  width: 100%; padding: 16px 18px; text-align: left;
  background: var(--surface, #fff);
  border: 1px solid var(--line, #dcd8d0);
  border-radius: var(--r-media);
  cursor: pointer;
  transition: border-color .18s ease, background .18s ease;
}
.portal-child:hover { border-color: var(--brand, #14577f); background: var(--brand-soft, #e7ecef); }
.portal-child-name { font-family: var(--font-display); font-size: 18px; font-weight: 600; color: var(--ink, #0d2233); }
.portal-child-meta { font-size: 13.5px; color: var(--ink-soft, #5b6b78); }

/* Result sheet */
.portal-result { margin-top: 20px; }
.portal-back {
  background: none; border: 0; padding: 0 0 14px;
  color: var(--brand, #14577f); font-size: 14px; font-weight: 600; cursor: pointer;
}
.portal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.portal-head h2 { font-family: var(--font-display); font-size: 26px; font-weight: 600; margin: 0 0 4px; }
.portal-sub { margin: 0; font-size: 14px; color: var(--ink-soft, #5b6b78); }
.portal-verdict {
  flex: none; padding: 7px 15px; border-radius: var(--r-pill);
  font-size: 13px; font-weight: 700; letter-spacing: .04em;
}
.portal-verdict.is-pass { background: #e6f2e9; color: #1d5b30; }
.portal-verdict.is-fail { background: #fdf0ec; color: #8a3419; }

.portal-tabs { display: flex; gap: 6px; margin: 22px 0 4px; border-bottom: 1px solid var(--line, #dcd8d0); }
.portal-tab {
  background: none; border: 0; border-bottom: 2px solid transparent;
  padding: 11px 4px; margin-right: 18px;
  font-family: var(--font-body); font-size: 14.5px; font-weight: 500;
  color: var(--ink-soft, #5b6b78); cursor: pointer;
}
.portal-tab.is-active { color: var(--brand, #14577f); border-bottom-color: var(--brand, #14577f); font-weight: 600; }

.portal-stats {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 0; margin: 22px 0 6px;
  border-top: 1px solid var(--line, #dcd8d0);
}
.portal-stats > div { padding: 16px 14px 16px 0; border-right: 1px solid var(--line, #dcd8d0); }
.portal-stats > div:last-child { border-right: 0; }
.portal-stats span { display: block; font-size: 12.5px; color: var(--ink-soft, #5b6b78); margin-bottom: 5px; }
.portal-stats strong {
  font-family: var(--font-display); font-size: 21px; font-weight: 600;
  color: var(--brand, #14577f); font-variant-numeric: lining-nums tabular-nums;
}

.portal-table-wrap { overflow-x: auto; margin-top: 10px; }
.portal-table { width: 100%; border-collapse: collapse; font-size: 14.5px; }
.portal-table th {
  text-align: left; padding: 11px 12px 11px 0;
  font-family: var(--font-body); font-size: 12.5px; font-weight: 600;
  color: var(--ink-soft, #5b6b78);
  border-bottom: 1px solid var(--line, #dcd8d0);
  white-space: nowrap;
}
.portal-table td {
  padding: 11px 12px 11px 0;
  border-bottom: 1px solid #eef4f9;
  color: var(--ink, #0d2233);
}
.portal-table .num { text-align: right; padding-right: 20px; font-variant-numeric: lining-nums tabular-nums; }
.portal-table tbody tr:last-child td { border-bottom: 0; }

.portal-note { margin: 16px 0 0; font-size: 14px; color: var(--ink-soft, #5b6b78); line-height: 1.55; }
.portal-actions {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  margin-top: 22px; padding-top: 20px; border-top: 1px solid var(--line, #dcd8d0);
}
.portal-download {
  border: 0; border-radius: var(--r-pill);
  padding: 13px 24px;
  background: var(--brand, #14577f); color: #fff;
  font-family: var(--font-body); font-size: 15px; font-weight: 600; cursor: pointer;
}
.portal-download:hover { background: var(--brand-dark, #0d3c5a); }
.portal-help { font-size: 14px; font-weight: 500; color: var(--brand, #14577f); }

@media (max-width: 640px) {
  .portal-card { padding: 20px 18px; }
  .portal-stats { grid-template-columns: repeat(2, 1fr); }
  .portal-stats > div:nth-child(2) { border-right: 0; }
  .portal-stats > div:nth-child(1),
  .portal-stats > div:nth-child(2) { border-bottom: 1px solid var(--line, #dcd8d0); }
  .portal-head h2 { font-size: 22px; }
  .portal-table .hide-sm, .portal-table th.hide-sm { display: none; }
  .portal-actions { flex-direction: column; align-items: stretch; }
  .portal-download { width: 100%; }
  .portal-help { text-align: center; }
}

/* ---------------------------------------------------------------------
   PRINT: "Download as PDF" uses the browser's own print-to-PDF, so there
   is no library to download on a phone. Everything except the report
   sheet is hidden and the sheet is laid out for A4.
   ------------------------------------------------------------------- */
@media print {
  /* Print the report sheet and nothing else.

     Two earlier attempts went wrong here, so the approach is spelled out:
       - Hiding every direct child of <body> that was not a .section also hid
         <main>, and the report lives inside <main>. The PDF came out blank.
       - Hiding everything with visibility:hidden showed the report but left
         the whole page in the layout, so the card was followed by two blank
         pages.
     What works is naming the chrome to remove, and leaving the report's own
     ancestors alone. */
  body.printing-report .utility-bar,
  body.printing-report .site-nav,
  body.printing-report .site-footer,
  body.printing-report .wa-float,
  body.printing-report .hero,
  body.printing-report .internal-links-strip,
  body.printing-report .marquee-bar,
  body.printing-report .portal-steps,
  body.printing-report .portal-error,
  body.printing-report .portal-card:not(.portal-result),
  body.printing-report .portal-children,
  body.printing-report .portal-tabs,
  body.printing-report .portal-actions,
  body.printing-report .portal-back,
  body.printing-report .cards-grid,
  body.printing-report .button-row,
  body.printing-report .section > .container > div[style*="text-align:center"] {
    display: none !important;
  }

  /* The section wrapping the portal keeps its box but loses the page padding
     that would otherwise push the card onto a second sheet. */
  body.printing-report .section {
    padding: 0 !important;
  }
  body.printing-report .portal-wrap {
    max-width: none;
    margin: 0;
  }
  body.printing-report #portalSheet {
    margin: 0;
    padding: 0;
    border: 0;
    box-shadow: none;
    background: #fff;
    break-inside: auto;
  }

  /* The teacher column is dropped on small screens; a printed card keeps it. */
  body.printing-report .portal-table .hide-sm,
  body.printing-report .portal-table th.hide-sm {
    display: table-cell !important;
  }

  body.printing-report .portal-table { font-size: 10pt; }
  body.printing-report .portal-table-wrap { overflow: visible; }
  body.printing-report .portal-head,
  body.printing-report .portal-stats { break-inside: avoid; }
  body.printing-report .portal-table tr { break-inside: avoid; }

  body.printing-report #portalSheet::after {
    content: "Rainbow School Complex, Dschang. Issued from the Parents Portal.";
    display: block;
    margin-top: 18px;
    padding-top: 10px;
    border-top: 1px solid #ccc;
    font-size: 9pt;
    color: #555;
  }

  @page { margin: 14mm; }
}

/* =====================================================================
   15. TESTIMONIALS
   Built to the reference: a coloured eyebrow, a large condensed display
   headline, one testimonial at a time with a big quote glyph, and a
   vertical dot rail on the right. One voice at full size reads as
   confidence; six small cards read as a directory.
   ===================================================================== */
.tm-section {
  background: var(--paper, #fbfaf7);
  overflow: hidden;
}

.tm-eyebrow {
  display: block;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--accent-dark, #0d3c5a);
  margin-bottom: 14px;
}

.tm-title {
  font-family: var(--font-display);
  font-size: clamp(34px, 5.4vw, 68px);
  line-height: .98;
  font-weight: 600;
  letter-spacing: -0.02em;
  margin: 0 0 44px;
  color: var(--ink, #0d2233);
}

.tm-stage {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 54px;
  gap: 28px;
  align-items: start;
}

.tm-slides { position: relative; min-height: 330px; }

.tm-slide {
  position: absolute;
  inset: 0;
  max-width: 760px;
  opacity: 0;
  visibility: hidden;
  transform: translateY(14px);
  transition: opacity .5s ease, transform .5s cubic-bezier(.16, 1, .3, 1);
}
.tm-slide.is-active {
  position: relative;
  opacity: 1;
  visibility: visible;
  transform: none;
}

.tm-mark {
  display: block;
  font-family: var(--font-display);
  font-size: 68px;
  line-height: .6;
  color: var(--accent, #14577f);
  margin-bottom: 10px;
}

.tm-quote {
  font-family: var(--font-body);
  font-size: clamp(15px, 1.5vw, 17px);
  line-height: 1.75;
  letter-spacing: .01em;
  color: var(--ink, #0d2233);
  margin: 0 0 26px;
  max-width: 64ch;
}
.tm-quote-empty { color: var(--ink-soft, #5b6b78); font-style: italic; }

/* Video testimonial: a wide, calm player bar rather than a card. */
.tm-video {
  position: relative;
  width: 100%;
  max-width: 520px;
  height: 0;
  padding-bottom: 26%;
  min-height: 116px;
  border-radius: var(--r-pill);
  background-size: cover;
  background-position: center;
  margin: 0 0 26px;
  overflow: hidden;
  box-shadow: var(--e2);
}
.tm-video::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(4, 20, 35, .62), rgba(4, 20, 35, .28));
}
.tm-play {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 100%;
  border: 0;
  background: none;
  cursor: pointer;
}
.tm-play svg {
  width: 54px; height: 54px;
  padding: 15px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .94);
  fill: var(--brand, #14577f);
  transition: transform .2s ease, background .2s ease;
}
.tm-play:hover svg { transform: scale(1.07); background: #fff; }

.tm-person { display: flex; align-items: center; gap: 13px; }
.tm-avatar {
  flex: none;
  width: 46px; height: 46px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--brand-soft, #e7ecef);
  color: var(--brand, #14577f);
  font-family: var(--font-body);
  font-size: 14px; font-weight: 600;
}
.tm-avatar-video { background: var(--accent, #14577f); }
.tm-who { display: flex; flex-direction: column; line-height: 1.35; }
.tm-who strong {
  font-family: var(--font-body);
  font-size: 14px; font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink, #0d2233);
}
.tm-who em {
  font-style: normal;
  font-size: 13px;
  color: var(--accent-dark, #0d3c5a);
}

/* Vertical rail, as in the reference. */
.tm-nav {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 11px;
  padding-top: 10px;
}
.tm-dot {
  width: 8px; height: 8px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: #cfd8e0;
  cursor: pointer;
  transition: background .2s ease, transform .2s ease;
}
.tm-dot:hover { background: #9fb3c4; }
.tm-dot.is-active { background: var(--accent, #14577f); transform: scale(1.45); }
.tm-arrow {
  width: 26px; height: 26px;
  display: grid; place-items: center;
  padding: 0; border: 0; background: none; cursor: pointer;
}
.tm-arrow svg {
  width: 17px; height: 17px;
  fill: none; stroke: var(--ink-soft, #5b6b78);
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}
.tm-arrow:hover svg { stroke: var(--brand, #14577f); }

@media (max-width: 767px) {
  .tm-stage { grid-template-columns: 1fr; gap: 18px; }
  .tm-slides { min-height: 370px; }
  .tm-nav { flex-direction: row; justify-content: center; padding-top: 0; }
  .tm-video { padding-bottom: 42%; max-width: none; }
  .tm-title { margin-bottom: 30px; }
}

/* =====================================================================
   16. VERIFIED TICK for "Recognised by"
   A plain check said nothing. The badge shape is the one people already
   read as "verified" on WhatsApp and X.
   ===================================================================== */
.verified-tick { width: 17px; height: 17px; flex: none; }
.verified-tick .tick-badge { fill: var(--brand, #14577f); }
.verified-tick .tick-mark {
  fill: none; stroke: #fff; stroke-width: 2.1;
  stroke-linecap: round; stroke-linejoin: round;
}
.rsc-trusted-pill { gap: 9px; }

/* =====================================================================
   17. HERO ALIGNMENT + LANGUAGE SWITCHER
   The hero text sat hard against the top-left. It now sits on the lower
   third, left of centre, which is where the eye lands and which leaves
   the photograph room to breathe.
   ===================================================================== */
.hero .hero-slide { align-items: flex-end; }
.hero .hero-slide .container { width: 100%; }
.hero-content {
  max-width: 760px;
  margin-left: clamp(0px, 4vw, 90px);
  padding-bottom: clamp(48px, 9vh, 104px);
}

@media (max-width: 767px) {
  .hero-content { margin-left: 0; padding-bottom: 34px; }
}

/* The EN / FR switcher read as black-and-white system chrome. */
.lang-switcher {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border-radius: var(--r-pill);
  background: var(--brand-soft, #e7ecef);
  border: 1px solid var(--line, #dcd8d0);
}
.lang-switcher a {
  display: inline-grid;
  place-items: center;
  min-width: 34px;
  height: 27px;
  padding: 0 9px;
  border-radius: var(--r-pill);
  font-family: var(--font-body);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .03em;
  color: var(--brand, #14577f);
  background: none;
  transition: background .18s ease, color .18s ease;
}
.lang-switcher a:hover { background: rgba(15, 90, 137, .1); color: var(--brand-dark, #0d3c5a); }
.lang-switcher a.lang-active {
  background: var(--brand, #14577f);
  color: #fff;
  box-shadow: 0 1px 3px rgba(12, 40, 64, .18);
}
.lang-switcher .lang-div { display: none; }

/* =====================================================================
   18. "READY TO ENROL" BAND
   The buttons carried dark text on a dark navy panel.
   ===================================================================== */
.cta-panel .btn-pill,
.cta-panel .btn-pill.btn-quiet,
.cta-panel .section .btn-pill:not(.btn-gold):not(.btn-hero):not(.btn-filled) {
  background: var(--accent, #14577f);
  color: #fff;
  border: 0;
}
.cta-panel .btn-pill:hover { background: var(--accent-dark, #0d3c5a); color: #fff; }
.cta-panel .btn-pill + .btn-pill,
.cta-panel .btn-secondary {
  background: transparent;
  color: #fff;
  border: 1px solid rgba(255, 255, 255, .42);
}
.cta-panel .btn-pill + .btn-pill:hover { background: rgba(255, 255, 255, .12); color: #fff; }

/* Two columns: the headline holds the left, the voice takes the right.
   One column left two thirds of the width empty. */
.tm-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1fr);
  gap: clamp(32px, 6vw, 88px);
  align-items: start;
}
.tm-head { position: sticky; top: 120px; }
.tm-head .tm-title { margin-bottom: 0; }
.tm-grid .tm-stage { padding-top: 6px; }
.tm-grid .tm-slide { max-width: none; }
.tm-grid .tm-video { max-width: none; padding-bottom: 34%; }

@media (max-width: 991px) {
  .tm-grid { grid-template-columns: 1fr; gap: 28px; }
  .tm-head { position: static; }
  .tm-head .tm-title { margin-bottom: 4px; }
}

/* Explicit placement. Auto-placement was putting the headline in column 2
   despite correct DOM order, so the columns are named rather than inferred. */
.tm-grid > .tm-head  { grid-column: 1; grid-row: 1; }
.tm-grid > .tm-stage { grid-column: 2; grid-row: 1; }
@media (max-width: 991px) {
  .tm-grid > .tm-head  { grid-column: 1; grid-row: 1; }
  .tm-grid > .tm-stage { grid-column: 1; grid-row: 2; }
}

/* =====================================================================
   15. REPORT CARD
   Laid out to match the card the school prints, so a parent can hold the
   two side by side. Same header block, same column order, same footer,
   same subject list including the blank rows for subjects the class does
   not take. Colours follow the school's own sheet rather than the site
   palette, because this is a document, not a web section.
   ===================================================================== */
.report-card {
  background: #fff;
  border: 1px solid #9fb8c9;
  border-radius: 6px;
  padding: 16px 18px 12px;
  margin-top: 18px;
  font-family: var(--font-body);
  font-size: 13px;
  color: #10202c;
  max-width: 820px;
  box-shadow: var(--e1);
}

.rc-head {
  display: flex; align-items: center; gap: 14px;
  padding-bottom: 10px; border-bottom: 2px solid #14577f;
}
.rc-logo { width: 54px; height: 54px; object-fit: contain; flex: none; }
.rc-titles { flex: 1; text-align: center; }
.rc-titles h1 {
  font-family: var(--font-display);
  font-size: 17px; font-weight: 700; margin: 0 0 2px; color: #14577f;
  letter-spacing: .01em;
}
.rc-titles p { margin: 0; font-size: 11px; line-height: 1.45; color: #33505f; }
.rc-site { color: #14577f; text-decoration: underline; }

.report-card table { width: 100%; border-collapse: collapse; }
.report-card th, .report-card td {
  border: 1px solid #9fb8c9; padding: 3px 7px; text-align: left; vertical-align: middle;
}
.report-card th { background: #dbe9f2; font-weight: 600; font-size: 11.5px; white-space: nowrap; }
.rc-n { text-align: right; font-variant-numeric: lining-nums tabular-nums; }

.rc-meta { margin-top: 10px; }
/* The pupil's name is the one thing on the card a parent looks for first.
   Red read as a warning; bold ink reads as a name. */
.rc-meta .rc-name { color: var(--ink, #0d2233); font-weight: 700; font-size: 13.5px; }
.rc-meta .rc-strong { font-weight: 700; text-align: center; }

.rc-subjects { margin-top: 8px; }
.rc-subjects thead th { background: #14577f; color: #fff; font-size: 11px; letter-spacing: .02em; }
.rc-subjects td { font-size: 12.5px; height: 20px; }
.rc-subjects tbody tr:nth-child(even) td { background: #f6fafd; }
.rc-blank td { color: #9fb0bc; }

/* A failed subject is marked red, as it would be ringed on paper. The GRADE
   column still spells out POOR / V.POOR, so colour is never the only signal. */
.rc-fail td { color: #b3261e; font-weight: 600; background: #fdf1ef !important; }

.rc-terms { margin-top: 8px; }
.rc-terms td { text-align: center; font-weight: 600; }

.rc-summary { display: flex; gap: 8px; margin-top: 8px; align-items: flex-start; }
.rc-avg { flex: 2; }
.rc-subcount { flex: 1; }
.rc-avg td { font-weight: 600; }
.rc-hl { background: #c9ecf7; font-weight: 700; }

.rc-foot { display: flex; gap: 8px; margin-top: 8px; align-items: stretch; }
.rc-conduct { flex: 1.4; }
.rc-legend, .rc-verdict-box {
  flex: 1; border: 1px solid #9fb8c9; padding: 5px 8px; font-size: 11px; line-height: 1.5;
}
.rc-legend p, .rc-verdict-box p { margin: 0; }
.rc-legend-title { font-weight: 700; background: #dbe9f2; margin: -5px -8px 5px !important; padding: 3px 8px; }
.rc-verdict-box { display: flex; flex-direction: column; }
.rc-verdict {
  flex: 1; display: grid; place-items: center;
  font-family: var(--font-display); font-size: 21px; font-weight: 700; letter-spacing: .04em;
}
.rc-verdict.is-pass { color: #1d5b30; }
.rc-verdict.is-fail { color: #b3261e; }

.rc-sign {
  margin: 10px 0 0; padding-top: 18px;
  border-top: 1px solid #9fb8c9; text-align: center;
  font-size: 11px; font-weight: 600; color: #33505f;
}
.rc-copyright { margin: 4px 0 0; font-size: 10px; color: #7e93a2; }

@media (max-width: 720px) {
  /* The card keeps its shape rather than reflowing, because a report card
     that has been rearranged is no longer the same document. It scrolls
     sideways instead. */
  .portal-wrap .report-card { font-size: 12px; padding: 12px; }
  .rc-summary, .rc-foot { flex-direction: column; }
  .rc-titles h1 { font-size: 14px; }
  .rc-head { gap: 10px; }
  .rc-logo { width: 42px; height: 42px; }
}

@media print {
  /* Sized to land on ONE A4 sheet even for the longest card (15 subjects
     plus blank rows). An overflowing card prints a second, empty page. */
  body.printing-report .report-card {
    border: 1px solid #9fb8c9; box-shadow: none; margin: 0; padding: 8px 10px;
    max-width: none; font-size: 8.6pt; break-inside: avoid;
  }
  body.printing-report .report-card th,
  body.printing-report .report-card td { padding: 1.5px 5px; }
  body.printing-report .rc-subjects td { height: auto; font-size: 8.4pt; }
  body.printing-report .rc-titles h1 { font-size: 12pt; }
  body.printing-report .rc-titles p { font-size: 7.4pt; }
  body.printing-report .rc-logo { width: 38px; height: 38px; }
  body.printing-report .rc-verdict { font-size: 14pt; }
  body.printing-report .rc-legend,
  body.printing-report .rc-verdict-box { font-size: 7.6pt; padding: 3px 6px; }
  body.printing-report .rc-sign { padding-top: 12px; margin-top: 6px; font-size: 7.6pt; }
  body.printing-report .rc-head { padding-bottom: 6px; }
  body.printing-report .rc-meta,
  body.printing-report .rc-subjects,
  body.printing-report .rc-terms,
  body.printing-report .rc-summary,
  body.printing-report .rc-foot { margin-top: 5px; }
  body.printing-report .rc-fail td { background: #fdf1ef !important; color: #b3261e !important; }
  body.printing-report .rc-subjects thead th { background: #14577f !important; color: #fff !important; }
  body.printing-report .report-card th { background: #dbe9f2 !important; }
  body.printing-report .rc-hl { background: #c9ecf7 !important; }
}

/* =====================================================================
   19. CAMPUS CAROUSEL
   A single photograph could not show what a campus is. Five can. The
   frame keeps the same 62% height the static photo had, so the three
   cards still line up, and the controls only appear on the card the
   visitor is actually looking at.
   ===================================================================== */
.campus-carousel {
  position: relative;
  height: 0;
  padding-bottom: 62%;
  overflow: hidden;
  background: var(--brand-soft, #e7ecef);
  border-bottom: 1px solid var(--line, #dcd8d0);
}

.cc-slide {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  opacity: 0;
  transform: scale(1.03);
  transition: opacity .85s ease, transform 6s linear;
  will-change: opacity;
}
.cc-slide.is-on { opacity: 1; transform: scale(1); }

/* Controls: quiet until wanted, and always reachable by keyboard. */
.cc-nav {
  position: absolute;
  top: 50%;
  z-index: 3;
  width: 34px; height: 34px;
  margin-top: -17px;
  display: grid; place-items: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .9);
  color: var(--ink, #0d2233);
  font-size: 17px;
  cursor: pointer;
  opacity: 0;
  transition: opacity .2s ease, background .2s ease, transform .2s ease;
  box-shadow: 0 2px 8px rgba(10, 30, 50, .22);
}
.cc-prev { left: 10px; }
.cc-next { right: 10px; }
.campus-card:hover .cc-nav,
.campus-carousel:focus-within .cc-nav { opacity: 1; }
.cc-nav:hover { background: #fff; transform: scale(1.08); }
.cc-nav:focus-visible { opacity: 1; outline: 2px solid var(--accent, #14577f); outline-offset: 2px; }

.cc-dots {
  position: absolute;
  z-index: 3;
  left: 0; right: 0; bottom: 11px;
  display: flex;
  justify-content: center;
  gap: 6px;
}
.cc-dot {
  width: 6px; height: 6px;
  padding: 0; border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .55);
  box-shadow: 0 1px 2px rgba(10, 30, 50, .35);
  cursor: pointer;
  transition: background .2s ease, width .2s ease, border-radius .2s ease;
}
.cc-dot.is-on { background: #fff; width: 17px; border-radius: 3px; }
.cc-dot:focus-visible { outline: 2px solid var(--accent, #14577f); outline-offset: 2px; }

@media (hover: none) {
  /* On a phone there is no hover to reveal them, so they stay visible. */
  .cc-nav { opacity: 1; background: rgba(255, 255, 255, .84); }
}
@media (prefers-reduced-motion: reduce) {
  .cc-slide { transition: opacity .3s ease; transform: none; }
  .cc-slide.is-on { transform: none; }
}

/* =====================================================================
   20. THE 2027/2028 ANNOUNCEMENT
   Real, confirmed news deserves to be seen without hijacking the page.
   It slides in from the corner, is dismissable, and never covers the
   WhatsApp button or the primary call to action.
   ===================================================================== */
.rsc-news {
  position: fixed;
  right: 22px;
  bottom: 96px;
  z-index: 1040;
  width: min(330px, calc(100vw - 44px));
  padding: 17px 19px 19px;
  border-radius: var(--r-card, 14px);
  background: var(--surface, #fff);
  border: 1px solid var(--line, #dcd8d0);
  border-left: 3px solid var(--accent, #14577f);
  box-shadow: 0 14px 40px rgba(10, 30, 50, .18);
  opacity: 0;
  transform: translateY(14px) scale(.98);
  pointer-events: none;
  transition: opacity .45s ease, transform .45s cubic-bezier(.16, 1, .3, 1);
}
.rsc-news.is-in { opacity: 1; transform: none; pointer-events: auto; }

.rsc-news-x {
  position: absolute;
  top: 7px; right: 8px;
  width: 26px; height: 26px;
  display: grid; place-items: center;
  padding: 0; border: 0;
  border-radius: 50%;
  background: none;
  color: var(--ink-soft, #5b6b78);
  font-size: 19px;
  line-height: 1;
  cursor: pointer;
}
.rsc-news-x:hover { background: var(--brand-soft, #e7ecef); color: var(--ink, #0d2233); }

.rsc-news-tag {
  margin: 0 0 6px;
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--accent-dark, #0d3c5a);
}
.rsc-news-title {
  margin: 0 0 6px;
  font-family: var(--font-display);
  font-size: 18px;
  line-height: 1.24;
  font-weight: 600;
  color: var(--ink, #0d2233);
  padding-right: 18px;
}
.rsc-news-body {
  margin: 0 0 12px;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ink-soft, #5b6b78);
}
.rsc-news-cta {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--brand, #14577f);
}
.rsc-news-cta::after { content: " \2192"; margin-left: 5px; }
.rsc-news-cta:hover { color: var(--brand-dark, #0d3c5a); }

@media (max-width: 767px) {
  .rsc-news { right: 12px; left: 12px; bottom: 84px; width: auto; }
}

/* =====================================================================
   21. SCROLL RAIL AND BACK TO TOP
   The rail shows how much of a long page is left. It is visible while
   the page is moving and fades when it stops. Back-to-top sits bottom
   LEFT so it never fights the WhatsApp button on the right.
   ===================================================================== */
.rsc-rail {
  position: fixed;
  right: 9px;
  top: 22vh;
  bottom: 22vh;
  z-index: 1030;
  width: 3px;
  opacity: 0;
  transition: opacity .35s ease;
  pointer-events: none;
}
.rsc-rail.is-live { opacity: 1; }
.rsc-rail-track {
  position: absolute;
  inset: 0;
  border-radius: 3px;
  background: rgba(15, 90, 137, .13);
  overflow: hidden;
}
.rsc-rail-fill {
  position: absolute;
  inset: 0;
  border-radius: 3px;
  background: linear-gradient(180deg, var(--brand, #14577f), var(--accent, #14577f));
  transform-origin: top center;
  transform: scaleY(0);
}

.rsc-top {
  position: fixed;
  left: 20px;
  bottom: 24px;
  z-index: 1035;
  width: 42px; height: 42px;
  display: grid; place-items: center;
  padding: 0;
  border: 1px solid var(--line, #dcd8d0);
  border-radius: 50%;
  background: var(--surface, #fff);
  color: var(--brand, #14577f);
  font-size: 19px;
  cursor: pointer;
  opacity: 0;
  transform: translateY(10px);
  pointer-events: none;
  box-shadow: 0 6px 18px rgba(10, 30, 50, .16);
  transition: opacity .3s ease, transform .3s ease, background .2s ease;
}
.rsc-top.is-in { opacity: 1; transform: none; pointer-events: auto; }
.rsc-top:hover { background: var(--brand, #14577f); color: #fff; border-color: var(--brand, #14577f); }

@media (max-width: 767px) {
  .rsc-rail { display: none; }
  .rsc-top { left: 14px; bottom: 18px; width: 38px; height: 38px; }
}

/* =====================================================================
   22. GERMAN PARTNERSHIP
   Two institutions side by side must read as equals. The German school
   gets its own identity block rather than sitting under Rainbow's logo
   as though it were a sub-brand.
   ===================================================================== */
.rsc-partnership-logo-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  min-width: 190px;
  padding: 16px 20px;
  border-radius: var(--r-card, 14px);
  background: var(--surface, #fff);
  border: 1px solid var(--line, #dcd8d0);
}
.rsc-partnership-logo-box img { max-height: 46px; width: auto; }
.rsc-partnership-logo-name {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.25;
  text-align: center;
  color: var(--ink, #0d2233);
}
.rsc-partnership-logo-loc {
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ink-soft, #5b6b78);
}
.rsc-partnership-logo-box.is-partner {
  background: linear-gradient(180deg, #fff, #f6f9fc);
  border-color: rgba(15, 90, 137, .26);
}
.rsc-partnership-flag { font-size: 30px; line-height: 1; }

.rsc-partnership-divider-badge {
  align-self: center;
  padding: 5px 13px;
  border-radius: var(--r-pill);
  background: var(--accent, #14577f);
  color: #fff;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  white-space: nowrap;
}
.rsc-partnership-logos {
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
}

@media (max-width: 575px) {
  .rsc-partnership-logo-box { min-width: 0; flex: 1 1 100%; }
}

/* =====================================================================
   23. 2026 RESULTS — two facts, two columns
   A three-column rule with two facts in it left a third of the row
   empty and made the section look unfinished.
   ===================================================================== */
.stat-grid-2 { grid-template-columns: repeat(2, 1fr); }
.stat-grid-2 .stat-card { padding-right: 34px; }
.stat-grid-2 .stat-card:nth-child(2) { border-right: 0; }
.stat-grid-2 .stat-card h3 { font-size: clamp(34px, 4.2vw, 50px); }
.stat-grid-2 .stat-card p { max-width: 30ch; font-size: 15px; }
@media (max-width: 767px) {
  .stat-grid-2 { grid-template-columns: 1fr; }
  .stat-grid-2 .stat-card { border-right: 0; border-bottom: 1px solid var(--line, #dcd8d0); padding-right: 0; }
  .stat-grid-2 .stat-card:last-child { border-bottom: 0; }
}

/* =====================================================================
   24. INSIDE OUR CAMPUSES
   The three cards were different heights with the photo cropped at a
   different ratio in each. One ratio, one card shape, one rhythm.
   ===================================================================== */
.masonry {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22px;
  column-count: auto;
}
.masonry .gallery-card {
  display: flex;
  flex-direction: column;
  margin: 0;
  overflow: hidden;
  background: var(--surface, #fff);
  border: 1px solid var(--line, #dcd8d0);
  border-radius: var(--r-card, 14px);
  box-shadow: var(--e1);
  transition: box-shadow .22s ease, transform .22s ease, border-color .22s ease;
}
.masonry .gallery-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--e3);
  border-color: rgba(15, 90, 137, .3);
}
.masonry .gallery-card img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 0;
  margin: 0;
}
.masonry .gallery-card h3 {
  font-family: var(--font-display);
  font-size: 19px;
  line-height: 1.24;
  font-weight: 600;
  color: var(--ink, #0d2233);
  margin: 18px 20px 6px;
}
.masonry .gallery-card p {
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--ink-soft, #5b6b78);
  margin: 0 20px 16px;
  flex: 1;
}
.masonry .gallery-card .btn-link-inline {
  margin: 0 20px 20px;
  font-family: var(--font-body);
  font-size: 14.5px;
  font-weight: 600;
  color: var(--brand, #14577f);
}
@media (max-width: 991px) { .masonry { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px)  { .masonry { grid-template-columns: 1fr; } }

/* =====================================================================
   25. A WORD FROM OUR FOUNDERS
   Portraits at 4:3 rather than a tall crop, so both faces sit at the
   same height and the two messages start on the same line.
   ===================================================================== */
.leadership-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 26px;
  align-items: stretch;
}
.leadership-grid .leader-card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--surface, #fff);
  border: 1px solid var(--line, #dcd8d0);
  border-radius: var(--r-card, 14px);
  box-shadow: var(--e1);
}
.leadership-grid .leader-photo {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: center 22%;
  border-radius: 0;
  margin: 0;
  display: block;
}
.leadership-grid .leader-body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 22px 24px 24px;
}
.leadership-grid .leader-role {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--accent-dark, #0d3c5a);
  margin-bottom: 8px;
}
.leadership-grid .leader-name {
  font-family: var(--font-display);
  font-size: 22px;
  line-height: 1.2;
  font-weight: 600;
  color: var(--ink, #0d2233);
  margin: 0 0 3px;
}
.leadership-grid .leader-title {
  font-size: 13.5px;
  color: var(--ink-soft, #5b6b78);
  margin: 0 0 14px;
}
.leadership-grid .leader-quote {
  flex: 1;
  padding-left: 16px;
  border-left: 2px solid var(--accent, #14577f);
}
.leadership-grid .leader-quote p {
  font-size: 15px;
  line-height: 1.7;
  color: var(--ink, #0d2233);
  margin: 0 0 12px;
}
.leadership-grid .leader-sign {
  font-family: var(--font-display);
  font-size: 16px;
  font-style: italic;
  color: var(--brand, #14577f);
}
@media (max-width: 767px) { .leadership-grid { grid-template-columns: 1fr; } }

/* =====================================================================
   26. FOOTER SOCIAL ICONS
   Font Awesome 4 brand glyphs next to two inline SVGs looked like two
   different sets, because they were. One set, one size, one shape.
   ===================================================================== */
.site-footer .social-icons {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 4px;
}
.site-footer .social-icons a {
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .18);
  color: rgba(255, 255, 255, .9);
  transition: background .2s ease, border-color .2s ease, transform .2s ease;
}
.site-footer .social-icons a:hover {
  background: var(--accent, #14577f);
  border-color: var(--accent, #14577f);
  color: #fff;
  transform: translateY(-2px);
}
.site-footer .social-icons svg {
  width: 17px; height: 17px;
  fill: currentColor;
  display: block;
}
.site-footer .social-icons i { font-size: 16px; line-height: 1; }
.site-footer .social-icon-svg { display: grid; place-items: center; }

/* =====================================================================
   27. FIXES FOUND IN THE SECOND RENDER REVIEW
   Three of these are the legacy layers winning on !important, which is
   why the earlier passes appeared to change nothing.
   ===================================================================== */

/* The card tag was set to white for a photo it no longer sits on, with
   colour: #fff !important. On a white card it was invisible. */
.campus-copy .campus-tag,
.cards-grid .campus-tag {
  color: var(--brand, #14577f) !important;
  background: none !important;
  padding: 0 !important;
  border-radius: 0 !important;
  letter-spacing: .04em !important;
  text-transform: none !important;
  font-weight: 600 !important;
  opacity: 1 !important;
}

/* "Ready to enrol": black text on a navy panel, which is what Dexter
   saw. The first action takes the gold; the rest are outlined in white.
   !important because the legacy layer sets these with it. */
.cta-panel .btn-pill,
.cta-panel a.btn-pill,
.cta-panel .button-row .btn-pill {
  background: transparent !important;
  color: #fff !important;
  border: 1px solid rgba(255, 255, 255, .5) !important;
  box-shadow: none !important;
}
.cta-panel .btn-pill:hover,
.cta-panel a.btn-pill:hover {
  background: rgba(255, 255, 255, .13) !important;
  border-color: rgba(255, 255, 255, .8) !important;
  color: #fff !important;
}
.cta-panel .button-row .btn-pill:first-child,
.cta-panel a.btn-pill:first-child {
  background: var(--accent, #14577f) !important;
  color: #fff !important;
  border-color: var(--accent, #14577f) !important;
  font-weight: 600 !important;
}
.cta-panel .button-row .btn-pill:first-child:hover,
.cta-panel a.btn-pill:first-child:hover {
  background: var(--accent-dark, #0d3c5a) !important;
  border-color: var(--accent-dark, #0d3c5a) !important;
  color: #fff !important;
}

/* The founder's role was rendering as a full-width grey bar because an
   older rule gave it a pill background it no longer needs. */
.leadership-grid .leader-role {
  display: inline-block !important;
  width: auto !important;
  background: none !important;
  padding: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
}
/* One quote mark, not two: the gold rule already says "this is a quote". */
.leadership-grid .leader-quote::before,
.leadership-grid .leader-quote::after { content: none !important; }

/* The testimonial headline broke to three lines in its column. */
.tm-title { font-size: clamp(32px, 3.9vw, 52px); }
/* This ratio is a DESKTOP correction and must stay behind a min-width.
   Written unscoped it sat after the 991px rule that collapses the section
   to one column, so on a phone the quote was squeezed into a 159px-wide
   half-column and every line broke after three words. */
@media (min-width: 992px) {
  .tm-grid { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1fr); }
}

/* Card footers were wrapping in two of the three cards and not the
   third, so the three cards ended at different heights. Stack always. */
.campus-links {
  flex-direction: column;
  align-items: flex-start;
  gap: 9px;
}

/* The testimonial headline was sticky in a section barely taller than
   itself, so it drifted down the column while scrolling past. */
.tm-head { position: static; }
.tm-slides { min-height: 300px; }

/* The photo was floating inside a white frame because the card kept the
   padding from the old masonry tile. The photo is the card's top edge. */
.masonry .gallery-card { padding: 0 !important; }
.masonry .gallery-card img { padding: 0 !important; border: 0 !important; }

/* =====================================================================
   28. FRENCH NAVIGATION
   French labels run roughly a third longer than the English ones, which
   pushed the bar past the viewport. The bar tightens rather than the
   words being cut down to something that no longer says anything.
   ===================================================================== */
@media (min-width: 992px) {
  html[lang="fr"] .site-nav .navbar-nav > li > a {
    padding-left: 11px;
    padding-right: 11px;
    font-size: 14.5px;
  }
  html[lang="fr"] .site-nav .navbar-nav > li > a.nav-cta {
    padding-left: 17px;
    padding-right: 17px;
  }
  html[lang="fr"] .site-nav .language-switcher { margin-left: 6px; }
}

/* The switcher sat on a second rounded panel of its own, so it read as a
   blob beside the navigation rather than a control. */
.site-nav .language-switcher,
.site-nav li.language-switcher > a {
  background: none !important;
  border: 0 !important;
  box-shadow: none !important;
  padding: 0 !important;
}
.site-nav .language-switcher { display: flex; align-items: center; margin-left: 10px; }

/* =====================================================================
   29. HERO VERTICAL PLACEMENT, AND THE SWITCHER'S HEIGHT
   ===================================================================== */

/* Section 17 set align-items on the slide, but a Bootstrap carousel item
   is display:block, so it did nothing and the headline stayed pinned to
   the top. The active and transitioning items become flex containers;
   the rest keep Bootstrap's display:none. */
.hero .carousel-inner > .item.active,
.hero .carousel-inner > .item.next,
.hero .carousel-inner > .item.prev {
  display: flex !important;
  align-items: center;
}
.hero .carousel-inner > .item > .container,
.hero .hero-slide > .container { width: 100%; }
/* Just below centre, left of centre: where the eye lands. */
.hero-content { padding-top: clamp(24px, 6vh, 74px); padding-bottom: clamp(56px, 12vh, 140px); }

/* The switcher was stretching to the navbar's link height because the
   legacy nav padding reaches the anchors inside it. */
.site-nav .lang-switcher { align-self: center; }
.site-nav .lang-switcher a {
  height: 27px !important;
  min-height: 0 !important;
  padding: 0 9px !important;
  line-height: 27px !important;
  margin: 0 !important;
}

/* =====================================================================
   30. THE DESIGN SYSTEM
   Taken from the Canadian Bilingual School reference in the screenshot
   set — the one that was already confirmed when the testimonial section
   was built to it. Six rules, applied everywhere, so the site reads as
   one design instead of a series of sections:

     1. Warm paper ground, near-black ink. White is for cards only.
     2. Display type is CONDENSED, UPPERCASE and large.
     3. Every section opens with a small gold eyebrow label.
     4. One action colour (gold). Blue is the institution, never decoration.
     5. Photographs group as one large frame plus two small ones.
     6. Hairline rules instead of borders on everything.
   ===================================================================== */

:root {
  --font-display: "Oswald", "Archivo Narrow", "Arial Narrow", system-ui, sans-serif;
  --paper: #f2f0eb;
  --paper-deep: #e9e6df;
  --ink: #0d2233;
  --ink-soft: #5b6b78;
  --line: #dcd8d0;
}

body { background: var(--paper); color: var(--ink); }

/* --- 2. DISPLAY TYPE -------------------------------------------------
   The single biggest difference from what the site was doing. Section
   headings are set large, condensed and uppercase, two lines where the
   words allow it, with no drop shadow. */
.section-title,
h1.section-title,
h2.section-title,
.hero-content h1, .hero-content .hero-h,
.page-hero h1,
.school-hero h1,
.tm-title,
.rsc-display {
  font-family: var(--font-display) !important;
  text-transform: uppercase;
  font-weight: 600;
  line-height: .95;
  letter-spacing: .004em;
  color: var(--ink);
  text-shadow: none !important;
  margin-bottom: 18px;
}

h2.section-title,
.section .section-title { font-size: clamp(30px, 4.4vw, 60px); }
.section-title.tight { font-size: clamp(28px, 3.6vw, 48px); }

/* Sub-headings keep the display face but stay sentence case: school
   names are long, and "RAINBOW BILINGUAL KINDERGARTEN & PRIMARY
   SCHOOLS" in caps is a wall, not a title. */
.campus-copy h3,
.masonry .gallery-card h3,
.leadership-grid .leader-name,
.visual-copy h3,
.rc-titles h1 {
  font-family: var(--font-display) !important;
  font-weight: 500;
  letter-spacing: .005em;
  text-transform: none;
}

/* Body stays Poppins. Reading French at length in a condensed face is
   hard work, and parents read these paragraphs. */
body, p, li, td, th, input, button, .section-copy, .section-lead {
  font-family: var(--font-body);
}

/* --- 3. THE EYEBROW --------------------------------------------------
   A small gold label above the heading, as in the reference. */
.eyebrow,
.tm-eyebrow,
.rsc-eyebrow {
  display: block;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--accent-dark, #0d3c5a);
  margin: 0 0 12px;
  background: none;
  padding: 0;
  border: 0;
}

/* --- 1 & 6. GROUND AND RULES ----------------------------------------- */
.section { padding-top: clamp(56px, 8vw, 104px); padding-bottom: clamp(56px, 8vw, 104px); }
.section.bg-soft,
.bg-soft { background: var(--paper-deep) !important; }
.section + .section { border-top: 1px solid var(--line); }

.campus-card,
.masonry .gallery-card,
.leadership-grid .leader-card,
.report-card {
  background: #fff;
  border-color: var(--line);
}

/* --- 4. ONE ACTION COLOUR -------------------------------------------- */
.btn-pill.btn-gold,
.btn-hero,
.nav-cta {
  font-family: var(--font-body);
  font-weight: 600;
  letter-spacing: .01em;
}

/* Primary action carries a circular arrow badge, as in the reference. */
.btn-hero,
.hero-content .btn-pill:first-child,
.cta-panel .button-row .btn-pill:first-child {
  display: inline-flex;
  align-items: center;
  gap: 11px;
}
.btn-hero::after,
.hero-content .btn-pill:first-child::after,
.cta-panel .button-row .btn-pill:first-child::after {
  content: "\2192";
  display: grid;
  place-items: center;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: rgba(20, 15, 3, .16);
  font-size: 12px;
  line-height: 1;
  flex: none;
}

/* --- 5. PHOTO GROUPS -------------------------------------------------
   One large frame, two small beside it. A row of three equal tiles is
   the layout every template uses; the reference does not. */
@media (min-width: 900px) {
  .masonry {
    grid-template-columns: 1.35fr 1fr 1fr;
    /* grid-auto-rows: 1fr removed - see section 69. Equal rows are what
       stretched every card to the tallest in its row and left the slab of
       white under the short ones. */
  }
  .masonry .gallery-card:first-child { grid-row: span 2; }
  .masonry .gallery-card:first-child img { aspect-ratio: 4 / 5; }
  .masonry .gallery-card:first-child h3 { font-size: 23px; }
}

/* --- section lead paragraph ------------------------------------------ */
.section-lead,
.section-copy {
  font-size: clamp(15px, 1.35vw, 17px);
  line-height: 1.7;
  color: var(--ink-soft);
  max-width: 62ch;
}

/* The three-card rhythm gets more air between the heading and the cards. */
.mt-5 { margin-top: clamp(28px, 3.4vw, 46px) !important; }

/* =====================================================================
   31. THE HERO
   Two problems, both named: the headline is small for the space it sits
   in, and the video still reads as a video. A visitor is not meant to
   watch it — it is there to say "this is a real campus" and then get
   out of the way of the words. So it is darkened much further and
   genuinely blurred, the way the reference heroes treat their photos.
   ===================================================================== */

/* The media itself: softened and desaturated a little, so no single
   moving detail pulls the eye off the headline. */
.hero video.hero-video-bg,
.hero img.hero-video-bg,
.page-hero video.hero-video-bg,
.page-hero img.hero-video-bg,
.school-hero img.hero-video-bg,
.school-hero video.hero-video-bg {
  filter: blur(7px) saturate(.72) brightness(.62) !important;
  transform: scale(1.06);
  /* scale hides the soft edge blur leaves behind */
}

/* And a heavy graded wash over the top, darkest where the words are. */
.hero .carousel-inner > .item::after,
.page-hero::after,
.school-hero::after {
  content: "" !important;
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(100deg, rgba(6, 16, 26, .90) 0%, rgba(6, 16, 26, .74) 42%, rgba(6, 16, 26, .48) 100%),
    linear-gradient(0deg, rgba(6, 16, 26, .60) 0%, rgba(6, 16, 26, 0) 48%);
}
.hero .carousel-inner > .item > .container,
.page-hero > .container,
.school-hero > .container { position: relative; z-index: 2; }

/* The headline fills the space it was given. */
.hero-content h1, .hero-content .hero-h,
.page-hero h1,
.school-hero h1 {
  font-size: clamp(38px, 6.4vw, 92px);
  line-height: .93;
  max-width: 17ch;
  color: #fff;
  margin-bottom: 20px;
}
.hero-content p,
.page-hero > .container > p,
.school-hero > .container > p {
  font-size: clamp(16px, 1.5vw, 19px);
  line-height: 1.65;
  color: rgba(255, 255, 255, .92);
  max-width: 54ch;
  margin-bottom: 30px;
}
.hero-content { max-width: 940px; }

.hero-badge {
  display: inline-block;
  margin-bottom: 16px;
  padding: 0;
  background: none;
  border: 0;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--accent, #14577f);
}

@media (max-width: 767px) {
  .hero-content h1, .hero-content .hero-h,
  .page-hero h1,
  .school-hero h1 { font-size: clamp(32px, 9.4vw, 46px); max-width: none; }
}

/* =====================================================================
   32. THE VERIFICATION TICK
   It was drawn in the institutional navy, which does not read as
   "verified" — the mark people recognise is the bright blue one.
   The badge is drawn with fill="currentColor", so the colour has to be
   set on the wrapper. It was inheriting the pill's navy text colour,
   which is why it read as a dark shape rather than a verification mark.
   ===================================================================== */
.verified-tick {
  display: inline-flex;
  align-items: center;
  width: auto; height: auto;
  color: #1d9bf0 !important;
}
.verified-tick svg { width: 16px; height: 16px; display: block; }
.rsc-trusted-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: #fff;
  border: 1px solid var(--line, #dcd8d0);
}

/* The eyebrow was still picking up a grey pill from the legacy layer. */
.eyebrow,
.tm-eyebrow,
.rsc-eyebrow,
.hero .eyebrow,
.page-hero .eyebrow,
.section .eyebrow {
  background: none !important;
  border: 0 !important;
  border-radius: 0 !important;
  padding: 0 !important;
  box-shadow: none !important;
  width: auto !important;
}
.page-hero .eyebrow,
.school-hero .eyebrow,
.hero .eyebrow { color: var(--accent, #14577f) !important; }

/* =====================================================================
   33. CAMPUS MAPS
   Four campuses, four maps, two by two. Three in a row left the fourth
   stranded on its own line.
   ===================================================================== */
.map-grid-4 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 22px;
}
.map-grid-4 .map-embed-card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--line, #dcd8d0);
  border-radius: var(--r-card, 14px);
  box-shadow: var(--e1);
}
.map-grid-4 .map-frame { position: relative; height: 0; padding-bottom: 56%; }
.map-grid-4 .map-frame iframe {
  position: absolute; inset: 0;
  width: 100%; height: 100%; border: 0; display: block;
}
.map-grid-4 .map-body { padding: 18px 20px 20px; display: flex; flex-direction: column; flex: 1; }
.map-grid-4 .map-body h3 {
  font-family: var(--font-display);
  font-size: 18px; font-weight: 500; line-height: 1.25;
  margin: 0 0 6px; color: var(--ink, #0d2233);
}
.map-grid-4 .map-body p {
  font-size: 14px; line-height: 1.55; color: var(--ink-soft, #5b6b78); margin: 0 0 14px; flex: 1;
}
.map-grid-4 .map-body p em { font-style: normal; color: #9aa4ae; font-size: 13px; }
.map-grid-4 .map-directions {
  font-family: var(--font-body); font-size: 14px; font-weight: 600;
  color: var(--brand, #14577f);
}
@media (max-width: 767px) { .map-grid-4 { grid-template-columns: 1fr; } }

/* =====================================================================
   34. CHOOSING A RESULT
   A parent does not think in workbooks. They think "my daughter", then
   "her second-term report". So after the child comes a plain choice
   between the sequence result and the term report card, with only the
   captures the school has actually published on offer, and earlier
   years kept separate underneath.
   ===================================================================== */
.portal-year-block + .portal-year-block { margin-top: 26px; }
.portal-year-label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--accent-dark, #0d3c5a);
  margin: 0 0 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--line, #dcd8d0);
}
.portal-year-block + .portal-year-block .portal-year-label { color: var(--ink-soft, #5b6b78); }

.portal-results {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(216px, 1fr));
  gap: 12px;
}
.portal-result-btn {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  padding: 15px 17px;
  text-align: left;
  background: #fff;
  border: 1px solid var(--line, #dcd8d0);
  border-radius: var(--r-card, 14px);
  cursor: pointer;
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.portal-result-btn:hover {
  border-color: var(--brand, #14577f);
  box-shadow: var(--e2);
  transform: translateY(-2px);
}
.portal-result-btn .prb-kind {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--brand, #14577f);
}
.portal-result-btn .prb-label {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 500;
  line-height: 1.2;
  color: var(--ink, #0d2233);
}
.portal-result-btn .prb-year {
  font-family: var(--font-body);
  font-size: 12.5px;
  color: var(--ink-soft, #5b6b78);
  font-variant-numeric: lining-nums tabular-nums;
}

.portal-note {
  margin: 20px 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-soft, #5b6b78);
}

.portal-child-meta { color: var(--ink-soft, #5b6b78); }

/* =====================================================================
   35. GALLERY, AND TWO THINGS THE SYSTEM GOT TOO ENTHUSIASTIC ABOUT
   ===================================================================== */

/* The eyebrow stretched the full column because it was display:block, so
   any background or reveal effect on it drew a bar across the page. */
.eyebrow,
.tm-eyebrow,
.rsc-eyebrow { display: inline-block !important; }

/* "One large, two small" is right for the three cards on the homepage and
   wrong for a filterable album grid, where every album is equal. */
#galleryGrid.masonry { grid-template-columns: repeat(3, minmax(0, 1fr)); }
#galleryGrid.masonry .gallery-card:first-child { grid-row: auto; }
#galleryGrid.masonry .gallery-card:first-child img { aspect-ratio: 4 / 3; }
#galleryGrid.masonry .gallery-card:first-child h3 { font-size: 19px; }

/* Albums are cards of equal height with the action pinned to the bottom,
   so the row does not look ragged. */
#galleryGrid .gallery-card { display: flex; flex-direction: column; }
#galleryGrid .gallery-card > *:last-child { margin-top: auto; }
#galleryGrid .gallery-card .btn-pill,
#galleryGrid .gallery-card .btn-link-inline {
  align-self: flex-start;
  margin: 0 20px 20px;
}

/* The filter row belongs with the grid, not floating above a gap. */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 9px;
  margin: 26px 0 0;
}
.filter-bar .filter-btn {
  padding: 9px 18px;
  border-radius: var(--r-pill);
  border: 1px solid var(--line, #dcd8d0);
  background: #fff;
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 500;
  color: var(--ink, #0d2233);
  cursor: pointer;
  transition: background .18s ease, color .18s ease, border-color .18s ease;
}
.filter-bar .filter-btn:hover { border-color: var(--brand, #14577f); }
.filter-bar .filter-btn.active {
  background: var(--brand, #14577f);
  border-color: var(--brand, #14577f);
  color: #fff;
}

@media (max-width: 991px) { #galleryGrid.masonry { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px)  { #galleryGrid.masonry { grid-template-columns: 1fr; } }

/* A sub-heading inside a section, for a block that used to be a section
   of its own before it was merged in. */
.rsc-subhead {
  font-family: var(--font-display);
  font-size: clamp(20px, 2.2vw, 28px);
  font-weight: 500;
  text-transform: none;
  letter-spacing: .005em;
  color: var(--ink, #0d2233);
  margin: clamp(30px, 4vw, 52px) 0 18px;
  padding-top: clamp(24px, 3vw, 38px);
  border-top: 1px solid var(--line, #dcd8d0);
}

/* =====================================================================
   36. THREE COLOURS. NOT FOUR, NOT FIVE.
   Counted on the page as it stood: cream ground, white cards, navy text,
   blue headings, grey body text, gold buttons, a second blue in the
   footer, a third in "Continue exploring". That is a palette by
   accident, not by decision.

   From here the whole site is built from three, and every other value on
   the page is one of those three at a different opacity — which the eye
   reads as one colour, not another one:

       INK    #0d2233   text, dark panels, the footer
       BLUE   #14577f   every action, every link, every accent
       PAPER  #f2f0eb   the ground everything sits on

   The gold is gone. --accent now points at the blue, so every rule in
   the older stylesheets that reached for the accent gets the blue
   instead, without having to be hunted down one at a time.
   ===================================================================== */
:root {
  --ink:          #0d2233;
  --ink-soft:     rgba(13, 34, 51, .64);
  --ink-faint:    rgba(13, 34, 51, .44);

  --brand:        #14577f;
  --brand-dark:   #0d3c5a;
  --brand-soft:   rgba(20, 87, 127, .09);

  --paper:        #f2f0eb;
  --paper-2:      #e9e6df;
  --paper-deep:   #e9e6df;
  --surface:      #faf8f4;

  --line:         rgba(13, 34, 51, .13);
  --border:       rgba(13, 34, 51, .13);

  /* the gold is retired: anything still asking for the accent gets blue */
  --accent:       #14577f;
  --accent-dark:  #0d3c5a;
  --soft:         #f2f0eb;
  --navy-deep:    #0d2233;
  --text:         #0d2233;
  --muted:        rgba(13, 34, 51, .64);
}

body { background: var(--paper); color: var(--ink); }

/* Anything the older layers painted gold by hand. */
.btn-gold, .btn-hero, .nav-cta,
.marquee-bar, .footer-brandbar .btn-pill,
.tm-dot.is-active, .rsc-partnership-divider-badge {
  background-color: var(--brand) !important;
  border-color: var(--brand) !important;
  color: #fff !important;
}
.btn-gold:hover, .btn-hero:hover, .nav-cta:hover,
.footer-brandbar .btn-pill:hover {
  background-color: var(--brand-dark) !important;
  border-color: var(--brand-dark) !important;
  color: #fff !important;
}
.btn-hero::after,
.hero-content .btn-pill:first-child::after,
.cta-panel .button-row .btn-pill:first-child::after {
  background: rgba(255, 255, 255, .22);
  color: #fff;
}
.eyebrow, .tm-eyebrow, .rsc-eyebrow,
.hero-badge, .blog-post-category, .portal-year-label,
.leadership-grid .leader-role, .rsc-trusted-label {
  color: var(--brand) !important;
}
.leadership-grid .leader-quote { border-left-color: var(--brand); }
.tm-mark, .leader-sign { color: var(--brand); }
.verified-tick { color: var(--brand) !important; }

/* One ground, one card. A card is the same paper, lifted — not a
   different colour. */
.campus-card, .masonry .gallery-card, .leadership-grid .leader-card,
.map-grid-4 .map-embed-card, .portal-result-btn, .portal-card,
.team-card, .about-card, .panel, .filter-bar .filter-btn,
.rsc-trusted-pill, .rsc-partnership-card, .rsc-partnership-logo-box,
.faq-item, .news-card, .blog-card, .tm-slide {
  background: var(--surface) !important;
  border-color: var(--line) !important;
}
.section.bg-soft, .bg-soft { background: var(--paper-2) !important; }

/* Text hierarchy comes from opacity, not from new hues. */
.section-copy, .section-lead, .campus-copy p, .masonry .gallery-card p,
.map-grid-4 .map-body p, .portal-sub, .portal-note, .small-copy,
.tm-who em, .leader-title, .blog-post-meta, .rsc-trusted-pill {
  color: var(--ink-soft) !important;
}
.campus-copy .campus-tag, .cards-grid .campus-tag { color: var(--brand) !important; }

/* The dark panels were three different blues. They are one now, and it
   is the same one the footer uses, so the bottom of every page reads as
   a single block instead of three stacked bands. */
.cta-panel, .site-footer, .internal-links-strip,
.marquee-bar, .footer-glow {
  background: var(--ink) !important;
  color: #fff;
}
.internal-links-strip { border-top: 1px solid rgba(255, 255, 255, .1); }
.internal-links-strip h3,
.internal-links-strip a,
.internal-links-strip p { color: #fff !important; }
.internal-links-strip a {
  display: block;
  background: rgba(255, 255, 255, .07) !important;
  border: 1px solid rgba(255, 255, 255, .14) !important;
}
.internal-links-strip a:hover { background: rgba(255, 255, 255, .14) !important; }
.footer-glow { opacity: .35; }
.cta-panel::before, .cta-panel::after { opacity: .3; }

/* The scroll rail had picked up a gradient of its own. */
.rsc-rail-fill { background: var(--brand) !important; }
.rsc-rail-track { background: rgba(13, 34, 51, .12); }
.rsc-top { color: var(--brand); border-color: var(--line); background: var(--surface); }
.rsc-top:hover { background: var(--brand); color: #fff; border-color: var(--brand); }

/* The announcement, in the same family. */
.rsc-news { background: var(--surface); border-color: var(--line); border-left-color: var(--brand); }
.rsc-news-tag, .rsc-news-cta { color: var(--brand); }
.rsc-news-body { color: var(--ink-soft); }

/* Filter pills and dots. */
.filter-bar .filter-btn.active { background: var(--brand) !important; border-color: var(--brand) !important; color: #fff !important; }
.cc-dot.is-on { background: #fff; }

/* =====================================================================
   37. THE HEADER AND THE HERO ARE ONE THING
   There were three bands stacked at the top of every page: a blue strip,
   a cream navigation bar, then the photograph. Three edges, three
   colours, before a visitor has read a word.

   The strip is gone. The navigation now sits ON the photograph — no
   background, white type — and only takes a solid ground once the page
   has been scrolled past the hero, where it needs one to stay readable.
   ===================================================================== */
.utility-bar { display: none !important; }

.site-nav {
  background: transparent !important;
  border: 0 !important;
  box-shadow: none !important;
  transition: background .28s ease, box-shadow .28s ease;
}
body.nav-over-hero .site-nav .navbar-nav > li > a,
body.nav-over-hero .site-nav .navbar-brand span {
  color: #fff !important;
}
body.nav-over-hero .site-nav .navbar-brand img {
  background: #fff;
  border-radius: 50%;
  padding: 3px;
}
body.nav-over-hero .site-nav .navbar-nav > li > a:hover,
body.nav-over-hero .site-nav .navbar-nav > li.open > a { color: #fff !important; opacity: .82; }
body.nav-over-hero .site-nav .caret { border-top-color: #fff; }
body.nav-over-hero .site-nav .icon-bar { background: #fff !important; }

/* Once scrolled, it lands on the ink and behaves like a normal bar. */
body.nav-stuck .site-nav {
  background: var(--ink) !important;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .08);
}
body.nav-stuck .site-nav .navbar-nav > li > a,
body.nav-stuck .site-nav .navbar-brand span { color: #fff !important; }

/* Pages with no hero photograph start on the ink straight away, so the
   type is never white on paper. */
body:not(.nav-over-hero) .site-nav { background: var(--ink) !important; }
body:not(.nav-over-hero) .site-nav .navbar-nav > li > a,
body:not(.nav-over-hero) .site-nav .navbar-brand span { color: #fff !important; }
body:not(.nav-over-hero) .site-nav .caret { border-top-color: #fff; }
body:not(.nav-over-hero) .site-nav .icon-bar { background: #fff !important; }

/* The CTA and the switcher have to read on a dark bar. */
.site-nav .nav-cta {
  background: #fff !important;
  color: var(--ink) !important;
  border: 0 !important;
}
.site-nav .nav-cta:hover { background: rgba(255, 255, 255, .86) !important; color: var(--ink) !important; }

/* The hero starts at the very top and runs under the bar. */
.hero, .page-hero, .school-hero { margin-top: 0 !important; position: relative; }
.hero .hero-content,
.page-hero > .container,
.school-hero > .container { padding-top: clamp(96px, 13vh, 168px); }

/* The dropdown used to break the moment the pointer left the link, because
   there was a gap between the two. The gap is bridged. */
.site-nav .dropdown > .dropdown-menu { margin-top: 0; }
.site-nav .dropdown::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 100%;
  height: 14px;
}
@media (min-width: 992px) {
  .site-nav .dropdown:hover > .dropdown-menu { display: block; }
}

/* The location line belongs in the mobile menu, not in a band of its own. */
.nav-place { display: none; }
@media (max-width: 991px) {
  .nav-place {
    display: block;
    padding: 14px 0 4px;
    font-family: var(--font-body);
    font-size: 12px;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--ink-soft);
  }
  body.nav-over-hero .nav-place,
  body:not(.nav-over-hero) .nav-place { color: rgba(255, 255, 255, .7); }
}

/* =====================================================================
   38. THE HERO MEDIA
   Two things were wrong. The blur was heavy enough that the campus was
   unreadable — it should be softened, not hidden. And it was only being
   applied to the one slide that has a <video>; the other four carry the
   photograph as a background-image, which a filter cannot reach. Both
   are handled in one place now, by blurring what is BEHIND the wash
   rather than the element itself.
   ===================================================================== */
.hero video.hero-video-bg,
.hero img.hero-video-bg,
.page-hero video.hero-video-bg,
.page-hero img.hero-video-bg,
.school-hero img.hero-video-bg,
.school-hero video.hero-video-bg {
  filter: none !important;
  transform: none;
}

/* This layer is the PANE. Its shape is declared here and its glass is
   declared once, in section 72 - three earlier attempts each restated the
   blur and the wash a few hundred lines further down, and the one that
   won was not the one anybody was reading. */
.hero .carousel-inner > .item::after,
.page-hero::after,
.school-hero::after {
  content: "" !important;
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
}

/* Three lines is the limit. Below about 1200px the headline steps down
   rather than wrapping onto a fourth. */
.hero-content h1, .hero-content .hero-h,
.page-hero h1,
.school-hero h1 {
  font-size: clamp(34px, 5.2vw, 76px);
  line-height: .96;
  max-width: 15ch;
}
@media (max-width: 1199px) { .hero-content h1, .hero-content .hero-h, .page-hero h1, .school-hero h1 { font-size: clamp(32px, 5vw, 58px); } }
@media (max-width: 767px)  { .hero-content h1, .hero-content .hero-h, .page-hero h1, .school-hero h1 { font-size: clamp(29px, 8vw, 40px); max-width: none; } }

/* =====================================================================
   39. TESTIMONIAL CARDS
   Three problems: the video was a still that only played in a lightbox,
   the cards ended in a slab of empty white, and the line under the
   heading was pale blue on paper, which is close to invisible.
   ===================================================================== */

/* A testimonial grid is a grid of equals — no hero card. */
#testimonialGrid.masonry { grid-template-columns: repeat(3, minmax(0, 1fr)); }
#testimonialGrid.masonry .testimonial-card:first-child { grid-row: auto; }
@media (max-width: 991px) { #testimonialGrid.masonry { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 640px)  { #testimonialGrid.masonry { grid-template-columns: 1fr; } }

/* The card is only as tall as what is in it, and what is in it reaches
   both edges. No trailing slab of empty card. */
#testimonialGrid .testimonial-card {
  display: flex;
  flex-direction: column;
  align-content: start;
  padding: 0 0 18px;
  overflow: hidden;
  border-radius: var(--r-card, 14px);
  height: auto;
  min-height: 0;
}
#testimonialGrid .testimonial-card > .avatar,
#testimonialGrid .testimonial-card > .avatar-photo { margin: 20px 22px 0; }
#testimonialGrid .testimonial-card > .quote {
  margin: 14px 22px 0;
  font-size: 15px;
  line-height: 1.65;
  color: var(--ink);
}
#testimonialGrid .testimonial-card > .meta {
  margin: 14px 22px 0;
  font-size: 13.5px;
  color: var(--ink-soft) !important;
}
#testimonialGrid .testimonial-card > .meta:last-child { margin-bottom: 0; }

/* The video fills the top of the card. */
.testimonial-video-thumb,
.tm-video {
  position: relative;
  margin: 0;
  background-size: cover;
  background-position: center;
}
#testimonialGrid .testimonial-video-thumb { border-radius: 0; }
.testimonial-video-thumb.has-inline-video { background-image: none !important; padding-bottom: 0 !important; height: auto !important; }
.testimonial-video-thumb.has-inline-video .gallery-open-link,
.tm-video.has-inline-video .tm-play { display: none !important; }

.rsc-inline-video {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  background: var(--ink);
  border: 0;
}
.tm-video.has-inline-video {
  height: auto !important;
  padding-bottom: 0 !important;
  min-height: 0 !important;
  border-radius: var(--r-card, 14px);
  overflow: hidden;
}
.tm-video.has-inline-video::after { content: none !important; }
.tm-video.has-inline-video .rsc-inline-video { aspect-ratio: 16 / 9; }

/* "Parents, students and alumni are welcome to share theirs" was pale
   blue on paper. */
.testimonial-card p,
.testimonial-card .quote,
.section .section-copy,
.cta-card p, .share-card p { color: var(--ink-soft) !important; }
.testimonial-card.is-invite,
#testimonialGrid .testimonial-card:last-child { justify-content: center; }

/* =====================================================================
   40. CARDS DO NOT END IN EMPTY SPACE
   Wherever a grid stretches cards to a common height, the last element
   in the card takes the slack instead of leaving a blank slab.
   ===================================================================== */
/* .masonry .gallery-card no longer stretches - section 69 owns the
   gallery grid's heights now, and stretching here is what put the slack
   back that 69 removes. The others keep it: they are not photo cards and
   their rows do look better level. */
.cards-grid .campus-card,
.leadership-grid .leader-card,
.map-grid-4 .map-embed-card {
  align-self: stretch;
}
.masonry .gallery-card > *:last-child,
.map-grid-4 .map-body > *:last-child { margin-bottom: 0; }
.masonry .gallery-card p { flex: 0 1 auto; }
.masonry .gallery-card .btn-link-inline,
.masonry .gallery-card .btn-pill { margin-top: auto; }

/* =====================================================================
   41. THE NAVIGATION GROUND, SETTLED
   Three older rules were still painting the bar white, each one more
   specific than the last: .site-nav in compat, .navbar.site-nav in the
   theme, and body.has-hero-page .site-nav:not(.nav-scrolled) in the
   hotfix. Rather than out-shout them one at a time, every state is
   stated here at a specificity that covers all three.
   ===================================================================== */
body.nav-over-hero .site-nav,
body.nav-over-hero .navbar.site-nav,
body.nav-over-hero.has-hero-page .site-nav:not(.nav-scrolled),
body.nav-over-hero.has-hero-page .navbar.site-nav:not(.nav-scrolled) {
  background: transparent !important;
  background-color: transparent !important;
  box-shadow: none !important;
  border: 0 !important;
}

body.nav-stuck .site-nav,
body.nav-stuck .navbar.site-nav,
body.nav-stuck.has-hero-page .site-nav:not(.nav-scrolled),
body.nav-stuck.has-hero-page .navbar.site-nav:not(.nav-scrolled),
body:not(.nav-over-hero) .site-nav,
body:not(.nav-over-hero) .navbar.site-nav,
body:not(.nav-over-hero).has-hero-page .site-nav:not(.nav-scrolled) {
  background: var(--ink) !important;
  background-color: var(--ink) !important;
  box-shadow: none !important;
  border: 0 !important;
}

/* With the strip gone the bar belongs at the very top, and the
   photograph starts there too rather than 108px down. */
.site-nav, .navbar.site-nav { top: 0 !important; }
.hero, .page-hero, .school-hero,
body .hero { padding-top: 0 !important; }
.section.top-spacer { padding-top: clamp(104px, 13vh, 150px) !important; }
.section[style*="padding-top:140px"] { padding-top: clamp(104px, 13vh, 150px) !important; }

/* The mobile menu panel is paper, not a fourth white. */
@media (max-width: 991px) {
  .site-nav .navbar-collapse,
  .site-nav .navbar-collapse.collapse,
  .navbar-collapse { background: var(--surface) !important; border-color: var(--line) !important; }
  body.nav-over-hero .site-nav .navbar-collapse .navbar-nav > li > a,
  body:not(.nav-over-hero) .site-nav .navbar-collapse .navbar-nav > li > a { color: var(--ink) !important; }
  .nav-place, body.nav-over-hero .nav-place { color: var(--ink-soft) !important; }
  .site-nav .navbar-collapse .nav-cta { background: var(--brand) !important; color: #fff !important; }
}

/* The dropdown panel, same family. */
.site-nav .dropdown-menu { background: var(--surface) !important; border: 1px solid var(--line) !important; }
.site-nav .dropdown-menu > li > a { color: var(--ink) !important; }
.site-nav .dropdown-menu > li > a:hover,
.site-nav .dropdown-menu > li > a:focus {
  background: var(--brand-soft) !important;
  color: var(--brand) !important;
}

/* The bar has to leave the flow, or it reserves 84px of paper above the
   photograph and the two are separate bands again. */
body.nav-float .site-nav,
body.nav-float .navbar.site-nav {
  position: fixed !important;
  top: 0 !important;
  left: 0; right: 0;
  z-index: 1300;
}

/* =====================================================================
   42. TWO LEFTOVERS FROM THE GOLD
   A warm glow was still sitting under every pill button, which is the
   old accent showing through a box-shadow, and the language control
   still read as two separate chips rather than one switch.
   ===================================================================== */
.btn-hero, .btn-pill, .btn-secondary-hero, .nav-cta,
.hero-content .btn-pill, .cta-panel .btn-pill {
  box-shadow: none !important;
  text-shadow: none !important;
  filter: none !important;
}
.btn-hero:hover, .btn-pill:hover, .nav-cta:hover {
  box-shadow: 0 6px 18px rgba(13, 34, 51, .18) !important;
}
.btn-secondary-hero {
  background: rgba(255, 255, 255, .95) !important;
  color: var(--ink) !important;
  border: 0 !important;
}
.btn-secondary-hero:hover { background: #fff !important; color: var(--ink) !important; }

/* One switch, one moving part. */
.lang-switcher {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0;
  padding: 3px;
  border-radius: 999px;
  background: rgba(13, 34, 51, .10);
  border: 1px solid rgba(13, 34, 51, .10);
  overflow: hidden;
}
body.nav-over-hero .site-nav .lang-switcher {
  background: rgba(255, 255, 255, .16);
  border-color: rgba(255, 255, 255, .26);
}
body.nav-stuck .site-nav .lang-switcher,
body:not(.nav-over-hero) .site-nav .lang-switcher {
  background: rgba(255, 255, 255, .14);
  border-color: rgba(255, 255, 255, .22);
}
.lang-switcher a {
  position: relative;
  z-index: 2;
  display: inline-grid;
  place-items: center;
  min-width: 38px;
  height: 26px !important;
  padding: 0 10px !important;
  line-height: 26px !important;
  border-radius: 999px;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .06em;
  background: none !important;
  color: rgba(13, 34, 51, .55) !important;
  transition: color .2s ease;
}
body.nav-over-hero .site-nav .lang-switcher a,
body.nav-stuck .site-nav .lang-switcher a,
body:not(.nav-over-hero) .site-nav .lang-switcher a { color: rgba(255, 255, 255, .72) !important; }

.lang-switcher a.lang-active { color: var(--ink) !important; }
body.nav-over-hero .site-nav .lang-switcher a.lang-active,
body.nav-stuck .site-nav .lang-switcher a.lang-active,
body:not(.nav-over-hero) .site-nav .lang-switcher a.lang-active { color: var(--ink) !important; }

/* the knob */
.lang-switcher::before {
  content: "";
  position: absolute;
  z-index: 1;
  top: 3px; bottom: 3px;
  left: 3px;
  width: calc(50% - 3px);
  border-radius: 999px;
  background: #fff;
  transition: transform .24s cubic-bezier(.16, 1, .3, 1);
}
.lang-switcher:has(a:last-of-type.lang-active)::before { transform: translateX(100%); }
.lang-switcher .lang-div { display: none; }
.lang-switcher a:hover { color: var(--ink) !important; }
body.nav-over-hero .site-nav .lang-switcher a:hover { color: #fff !important; }

/* =====================================================================
   43. GALLERY CARDS
   The card was a filled blue capsule sitting on a white panel on a cream
   ground, under a black heading and grey body copy. Counted as colour
   that is four things fighting inside one small rectangle.

   The whole card already opens the gallery, so the button does not need
   to shout — it becomes a quiet line of type in the one blue, and the
   photograph does the work.
   ===================================================================== */
.gallery-card,
.campus-gallery-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 0 0 18px !important;
  overflow: hidden;
  cursor: pointer;
  transition: border-color .2s ease, transform .2s ease;
}
.gallery-card:hover { transform: translateY(-3px); border-color: var(--brand) !important; }

.gallery-card > img,
.campus-gallery-card > img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 0 !important;
  margin: 0 0 16px !important;
  height: auto !important;
  display: block;
}
.gallery-card > h3 { margin: 0 20px 6px !important; font-size: 19px; }
.gallery-card > p  { margin: 0 20px 14px !important; font-size: 14.5px; line-height: 1.55; }

.gallery-open-btn {
  align-self: flex-start;
  margin: auto 20px 0 !important;
  padding: 0 !important;
  border: 0 !important;
  background: none !important;
  box-shadow: none !important;
  border-radius: 0 !important;
  font-family: var(--font-body);
  font-size: 14.5px;
  font-weight: 600;
  color: var(--brand) !important;
  cursor: pointer;
}
.gallery-open-btn::after { content: " \2192"; margin-left: 5px; }
.gallery-open-btn:hover { color: var(--ink) !important; }

/* The play badge on a card that holds a video, in the same family. */
.gallery-card .gallery-open-link,
.testimonial-video-thumb .gallery-open-link {
  background: rgba(13, 34, 51, .55) !important;
  color: #fff !important;
  border: 0 !important;
}

/* Without the flag the partner block needs its own top spacing back. */
.rsc-partnership-logo-box.is-partner { padding-top: 22px; }

/* =====================================================================
   44. TWO FAULTS FOUND IN THE SCROLLED HEADER
   The fixed bar was only as wide as the container, so the ink stopped
   short of the right edge; and the rule that turns every nav link white
   was also catching the call to action, giving white text on a white
   pill.
   ===================================================================== */
body.nav-float .site-nav,
body.nav-float .navbar.site-nav {
  width: 100% !important;
  right: 0 !important;
  margin: 0 !important;
}

/* The white-link rules must not reach the CTA. */
body.nav-over-hero .site-nav .navbar-nav > li > a.nav-cta,
body.nav-stuck .site-nav .navbar-nav > li > a.nav-cta,
body:not(.nav-over-hero) .site-nav .navbar-nav > li > a.nav-cta,
.site-nav .navbar-nav > li > a.nav-cta,
.site-nav a.nav-cta {
  background: #fff !important;
  color: var(--ink) !important;
  border: 0 !important;
  font-weight: 700 !important;
}
body.nav-over-hero .site-nav .navbar-nav > li > a.nav-cta:hover,
body.nav-stuck .site-nav .navbar-nav > li > a.nav-cta:hover,
.site-nav a.nav-cta:hover {
  background: rgba(255, 255, 255, .88) !important;
  color: var(--ink) !important;
}

/* Any warm halo still sitting under a button, wherever it comes from. */
.btn-pill, .btn-hero, .btn-gold, .nav-cta,
.footer-brandbar .btn-pill, .cta-panel .btn-pill {
  filter: none !important;
  -webkit-filter: none !important;
}
.btn-pill::before, .btn-hero::before,
.footer-brandbar .btn-pill::before { content: none !important; }

/* The headline was breaking to a fourth line because the measure was a
   touch too tight for the longest of the five. */
.hero-content h1, .hero-content .hero-h,
.page-hero h1,
.school-hero h1 {
  font-size: clamp(34px, 4.9vw, 70px);
  max-width: 18ch;
}

/* The active side of the switch sits on the white knob, so it has to be
   ink whatever the bar is doing behind it. */
body .site-nav .lang-switcher a.lang-active,
body.nav-over-hero .site-nav .lang-switcher a.lang-active,
body.nav-stuck .site-nav .lang-switcher a.lang-active,
body:not(.nav-over-hero) .site-nav .lang-switcher a.lang-active {
  color: var(--ink) !important;
  font-weight: 700 !important;
}

/* ==========================================================================
   45. THE REPORT CARD SAYS WHAT IT IS
   A parent holding two printouts could not tell the sequence result from the
   term report: the only difference was a small "TERM 2" in a corner cell.
   The kind of document is now stated once, in full, under the crest.
   ========================================================================== */
.rc-kind {
  margin: 10px 0 0;
  padding: 8px 12px;
  border: 1px solid var(--ink);
  border-left-width: 5px;
  background: #eef4f8;
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}
.rc-kind-title {
  margin: 0;
  font-family: "Oswald", "Helvetica Neue", Arial, sans-serif;
  font-size: 15px;
  letter-spacing: .06em;
  font-weight: 600;
  color: var(--ink);
  text-transform: uppercase;
}
.rc-kind-sub {
  margin: 2px 0 0;
  font-size: 11.5px;
  letter-spacing: .04em;
  color: #3a5468;
}
/* A sequence is one snapshot inside a term; a term report closes the term.
   Different left edges so the two are told apart at arm's length. */
.report-card.is-sequence .rc-kind { border-left-color: #7aa7c2; }
.report-card.is-term .rc-kind { border-left-color: var(--brand); }

.rc-scope {
  margin: 8px 0 0;
  font-size: 11px;
  font-style: italic;
  color: #55707f;
}

/* The verdict used to sit in its own row beside the conduct boxes. Those
   boxes are gone — this platform does not collect absence, conduct, human
   investment or fees — so the verdict joins the summary row. */
.rc-summary .rc-verdict-box {
  flex: 1 1 auto;
  border: 1px solid #9fb6c4;
  padding: 6px 10px;
  font-size: 11px;
}

@media (max-width: 640px) {
  .rc-kind-title { font-size: 13px; }
}

@media print {
  body.printing-report .rc-kind { margin-top: 6px; padding: 5px 9px; }
  body.printing-report .rc-kind-title { font-size: 12pt; }
  body.printing-report .rc-kind-sub { font-size: 8pt; }
  body.printing-report .rc-scope { font-size: 7.5pt; margin-top: 4px; }
}

/* =====================================================================
   46. THE HEADER AND THE TOP OF THE PAGE
   Everything in this section is one complaint each, so each rule says
   which one it answers.
   ===================================================================== */

/* The hero glass is declared once, in section 72. The block that used to
   restate it here was the second of three, and deleting it is what stopped
   the three from fighting. */

/* --- "there is a white gap between the hero and the body" -----------
   Every light section carried a 60px white-to-transparent fade across
   its top edge. Under the hero that fade reads as a white band between
   the photograph and the page, and everywhere else it is simply a
   fourth colour laid over the paper. */
.section:not(.bg-dark)::before {
  background: none !important;
  height: 0 !important;
}

/* --- "at the top they are still blue" ------------------------------
   Belt and braces: hero.css no longer fights this, but the header has
   one owner now and it should not be possible to lose again. */
body.nav-over-hero .site-nav:not(.nav-scrolled) .navbar-nav > li > a:not(.nav-cta),
body.nav-over-hero .site-nav:not(.nav-scrolled) .navbar-brand span,
body.nav-over-hero .site-nav:not(.nav-scrolled) .brand span {
  color: #fff !important;
  text-shadow: 0 1px 12px rgba(6, 24, 42, .35);
}

/* --- "the underline kinds of wants to cancel out the writing" -------
   The hover underline was drawn 18px up from the bottom of a 74px tall
   link, which put it straight through the middle of the word. It now
   sits below the text, is a hairline rather than a bar, and takes the
   colour of the type it belongs to instead of the accent. */
.site-nav .navbar-nav > li > a::after {
  left: 15px !important;
  right: 15px !important;
  bottom: 12px !important;
  height: 1.5px !important;
  border-radius: 0 !important;
  background: currentColor !important;
  opacity: .55;
}
.site-nav .navbar-nav > li > a.nav-cta::after { content: none !important; }

/* --- "let's try and make it uniform" -------------------------------
   Scrolled, the bar used to land on solid ink while the page behind it
   was paper, so it read as a separate dark object with a hard edge
   under it. It now takes the colour of the page and frosts what passes
   beneath, which is the "glow" of the body showing through rather than
   a band sitting on top of it. */
body.nav-stuck .site-nav,
body.nav-stuck .navbar.site-nav,
body:not(.nav-over-hero) .site-nav,
body:not(.nav-over-hero) .navbar.site-nav,
body:not(.nav-over-hero).has-hero-page .site-nav:not(.nav-scrolled) {
  background: rgba(242, 240, 235, .82) !important;
  -webkit-backdrop-filter: blur(18px) saturate(1.25);
  backdrop-filter: blur(18px) saturate(1.25);
  box-shadow: 0 1px 0 rgba(13, 34, 51, .07), 0 10px 26px -22px rgba(13, 34, 51, .55) !important;
  border-bottom: 0 !important;
}
body.nav-stuck .site-nav .navbar-nav > li > a:not(.nav-cta),
body.nav-stuck .site-nav .navbar-brand span,
body:not(.nav-over-hero) .site-nav .navbar-nav > li > a:not(.nav-cta),
body:not(.nav-over-hero) .site-nav .navbar-brand span {
  color: var(--ink) !important;
  text-shadow: none !important;
}
body.nav-stuck .site-nav .caret,
body:not(.nav-over-hero) .site-nav .caret { border-top-color: var(--ink) !important; }
body.nav-stuck .site-nav .icon-bar,
body:not(.nav-over-hero) .site-nav .icon-bar { background: var(--ink) !important; }
/* The logo needs no white disc once the bar is pale. */
body.nav-stuck .site-nav .navbar-brand img,
body:not(.nav-over-hero) .site-nav .navbar-brand img {
  background: none;
  padding: 0;
}
/* A white pill is invisible on paper, so on the pale bar the call to
   action is the blue one. */
body.nav-stuck .site-nav .navbar-nav > li > a.nav-cta,
body.nav-stuck .site-nav a.nav-cta,
body:not(.nav-over-hero) .site-nav .navbar-nav > li > a.nav-cta,
body:not(.nav-over-hero) .site-nav a.nav-cta {
  background: var(--brand) !important;
  color: #fff !important;
}
body.nav-stuck .site-nav .navbar-nav > li > a.nav-cta:hover,
body:not(.nav-over-hero) .site-nav .navbar-nav > li > a.nav-cta:hover {
  background: var(--ink) !important;
  color: #fff !important;
}
/* ...and the switch has to be readable on paper too. */
body.nav-stuck .site-nav .lang-switcher,
body:not(.nav-over-hero) .site-nav .lang-switcher {
  background: rgba(13, 34, 51, .08) !important;
  border-color: rgba(13, 34, 51, .12) !important;
}
/* The quiet half only. Left as "a", it also painted the active half and
   then had to be undone below, and at 55% it did not read on paper. */
body.nav-stuck .site-nav .lang-switcher a:not(.lang-active),
body:not(.nav-over-hero) .site-nav .lang-switcher a:not(.lang-active) {
  color: rgba(13, 34, 51, .72) !important;
}
body.nav-stuck .site-nav .lang-switcher a.lang-active,
body:not(.nav-over-hero) .site-nav .lang-switcher a.lang-active {
  color: var(--ink) !important;
}
body.nav-stuck .site-nav .lang-switcher::before,
body:not(.nav-over-hero) .site-nav .lang-switcher::before {
  background: #fff;
  box-shadow: 0 1px 3px rgba(13, 34, 51, .18);
}

/* --- "one of the buttons is circle one of the other is a square" ----
   The two arrows were already the same; the slide markers were not -
   the current slide was a rounded bar and the rest were dots. One
   shape, one size, and the current one is simply filled. */
.hero .carousel-indicators li,
.hero .carousel-indicators li.active,
.rsc-carousel-dots button,
.rsc-carousel-dots button.is-active {
  width: 9px !important;
  height: 9px !important;
  margin: 0 5px !important;
  border-radius: 50% !important;
  border: 1px solid rgba(255, 255, 255, .7) !important;
  background: transparent !important;
  text-indent: -9999px;
}
.hero .carousel-indicators li.active,
.rsc-carousel-dots button.is-active {
  background: #fff !important;
  border-color: #fff !important;
}
.rsc-carousel-prev,
.rsc-carousel-next {
  width: 52px !important;
  height: 52px !important;
  border-radius: 50% !important;
  background: rgba(255, 255, 255, .14) !important;
  border: 2px solid rgba(255, 255, 255, .4) !important;
  display: grid !important;
  place-items: center !important;
  padding: 0 !important;
}
.rsc-carousel-prev:hover,
.rsc-carousel-next:hover {
  background: rgba(255, 255, 255, .26) !important;
  border-color: #fff !important;
}

@media (max-width: 991px) {
  /* The open mobile panel is paper whatever the bar is doing. */
  body.nav-over-hero .site-nav .navbar-collapse,
  body.nav-stuck .site-nav .navbar-collapse,
  body:not(.nav-over-hero) .site-nav .navbar-collapse {
    background: var(--paper) !important;
  }
  body.nav-over-hero .site-nav .navbar-collapse .navbar-nav > li > a,
  body.nav-stuck .site-nav .navbar-collapse .navbar-nav > li > a,
  body:not(.nav-over-hero) .site-nav .navbar-collapse .navbar-nav > li > a {
    color: var(--ink) !important;
    text-shadow: none !important;
  }
}


/* =====================================================================
   47. THE VIDEO TESTIMONIALS
   They were not playing at all. Four things were wrong: the files for
   them are not in the repository yet; the element carrying the video
   was the still itself, and the code only ever looked at its children,
   so not one player was built; the slide holding a video is never the
   one on screen first, so nothing started; and there was no way to
   reach a full-size player, because clicking the video has to be left
   to the video's own controls.
   ===================================================================== */

/* "crop toward the top of the frame" - a face sits in the upper third,
   so a centred crop takes the chin off. */
.rsc-inline-video,
.rsc-player-video { object-position: center 28%; }

/* The expand control: small, in the corner, clear of the scrub bar that
   runs along the bottom. */
.rsc-video-expand {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 6;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: rgba(13, 34, 51, .55);
  color: #fff;
  cursor: pointer;
  opacity: .82;
  transition: opacity .18s ease, background .18s ease;
}
.rsc-video-expand:hover { opacity: 1; background: rgba(13, 34, 51, .78); }
.rsc-video-expand svg {
  width: 17px; height: 17px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}

/* A card whose file is missing keeps the photograph and the play badge,
   which opens the lightbox exactly as it did before. */
.tm-video.video-missing .tm-play,
.testimonial-video-thumb.video-missing .gallery-open-link { display: grid !important; }

/* ---- the full-size player ---- */
.rsc-player {
  position: fixed;
  inset: 0;
  z-index: 3000;
  display: grid;
  place-items: center;
  padding: 24px;
}
.rsc-player[hidden] { display: none; }
.rsc-player-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(6, 24, 42, .88);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.rsc-player-box {
  position: relative;
  z-index: 1;
  width: min(1100px, 100%);
}
.rsc-player-video {
  display: block;
  width: 100%;
  max-height: 78vh;
  border-radius: 12px;
  background: #000;
  box-shadow: 0 30px 80px -30px rgba(0, 0, 0, .8);
}
.rsc-player-title {
  margin: 12px 2px 0;
  color: rgba(255, 255, 255, .82);
  font-size: 14.5px;
  letter-spacing: .01em;
}
.rsc-player-close {
  position: absolute;
  top: -44px;
  right: -4px;
  width: 38px;
  height: 38px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .14);
  color: #fff;
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
}
.rsc-player-close:hover { background: rgba(255, 255, 255, .28); }
body.rsc-player-open { overflow: hidden; }

@media (max-width: 767px) {
  .rsc-player { padding: 14px; }
  .rsc-player-close { top: -40px; right: 0; }
  .rsc-player-video { max-height: 64vh; }
}

/* The lightbox's own "View photos" bar was sitting across the top of the
   playing video, under the expand control and over the picture. A card
   that plays where it stands does not need a second way in. */
.tm-video.has-inline-video .gallery-open-link,
.tm-video.has-inline-video .gallery-open-btn,
.campus-video.has-inline-video .gallery-open-link,
.testimonial-video-thumb.has-inline-video .gallery-open-btn { display: none !important; }
.rsc-video-expand { z-index: 6; }

/* =====================================================================
   48. THE RESULTS BAND
   Two numbers sat in a half-empty two-column grid with a hairline
   running down the middle - and the hairline ran straight down the side
   of the words "Honour roll", because the right-hand half had 34px of
   padding on its right and none on its left.

   The two facts now sit inside one panel with equal air either side of
   the rule, the call to action moves up beside the heading so the row
   is not left half full, and a line of provenance closes it.
   ===================================================================== */
.results-band-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}
.results-band-head .section-title { margin-bottom: 0; }
.results-band-cta { flex: 0 0 auto; margin-bottom: 4px; }

.results-band-grid.stat-grid-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  margin-top: 34px;
  border: 1px solid rgba(13, 34, 51, .14);
  border-radius: var(--r-card, 14px);
  background: rgba(255, 255, 255, .42);
  overflow: hidden;
}
.results-band-grid .stat-card {
  padding: 34px 38px !important;
  border: 0 !important;
  background: none !important;
}
/* One rule, between the two, with the same air on both sides of it. */
.results-band-grid .stat-card + .stat-card {
  box-shadow: inset 1px 0 0 rgba(13, 34, 51, .14);
}
.results-band-grid .stat-card h3 {
  margin: 0 0 8px;
  font-family: "Oswald", "Helvetica Neue", Arial, sans-serif;
  font-size: clamp(30px, 3.4vw, 46px);
  line-height: 1.02;
  color: var(--brand);
}
.results-band-grid .stat-card p {
  margin: 0;
  max-width: 30ch;
  color: var(--ink-soft) !important;
}
.results-band-note {
  margin: 16px 2px 0;
  font-size: 13.5px;
  color: var(--ink-soft);
}

@media (max-width: 767px) {
  .results-band-grid.stat-grid-2 { grid-template-columns: 1fr; }
  .results-band-grid .stat-card + .stat-card {
    box-shadow: inset 0 1px 0 rgba(13, 34, 51, .14);
  }
  .results-band-cta { margin-bottom: 0; }
}

/* =====================================================================
   49. INSIDE OUR CAMPUSES
   The three cards sat in a masonry grid, so each one was as tall as its
   photograph happened to be: the primary card ran to twice the height
   of the other two and the row never lined up. "The card should not be
   dependent on the picture" - so the picture gets a fixed shape, the
   card gets a fixed grid, and every card ends where the link ends.

   Each one now carries five photographs with next and previous, and a
   View photos button that opens the whole set full size.
   ===================================================================== */
.campus-tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 26px;
  align-items: stretch;
}
.campus-tile {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid rgba(13, 34, 51, .10);
  border-radius: var(--r-card, 14px);
  overflow: hidden;
}
.campus-tile .campus-carousel {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  height: auto;
  min-height: 0;
  background: #dfe6ec;
  flex: 0 0 auto;      /* the photograph never decides the card's height */
}
.campus-tile .cc-slide {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  opacity: 0;
  transition: opacity .55s ease;
}
.campus-tile .cc-slide.is-on { opacity: 1; }

.campus-tile-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  padding: 20px 22px 20px;
  gap: 6px;
}
.campus-tile-eyebrow {
  font-family: var(--font-body);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--brand);
}
.campus-tile-body h3 {
  margin: 0;
  font-size: 21px;
  line-height: 1.16;
  color: var(--ink);
}
.campus-tile-body p {
  margin: 0;
  color: var(--ink-soft) !important;
  font-size: 15px;
}
/* The link sits on the bottom edge of every card, at the same height,
   whatever the copy above it does. */
.campus-tile-body .btn-link-inline { margin-top: auto; padding-top: 12px; }

/* View photos: the whole set, full size, from the card. */
.campus-tile-open {
  position: absolute;
  left: 12px;
  bottom: 12px;
  z-index: 5;
  padding: 7px 13px;
  border: 0;
  border-radius: 999px;
  background: rgba(13, 34, 51, .62);
  color: #fff;
  font-family: var(--font-body);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .02em;
  cursor: pointer;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity .2s ease, transform .2s ease, background .2s ease;
}
.campus-tile:hover .campus-tile-open,
.campus-tile:focus-within .campus-tile-open { opacity: 1; transform: none; }
.campus-tile-open:hover { background: rgba(13, 34, 51, .85); }
.campus-tile-open::after { content: " \2192"; }
/* On a touch screen there is no hover, so it is simply always there. */
@media (hover: none) {
  .campus-tile-open { opacity: 1; transform: none; }
}

@media (max-width: 991px) {
  .campus-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
}
@media (max-width: 640px) {
  .campus-tiles { grid-template-columns: 1fr; }
}

/* --- one shape for every marker, here too ---------------------------
   The slide markers inside these cards were the last place where the
   current one was a bar and the rest were dots. */
.cc-dot,
.cc-dot.is-on {
  width: 8px !important;
  height: 8px !important;
  margin: 0 4px !important;
  padding: 0 !important;
  border-radius: 50% !important;
  border: 1px solid rgba(255, 255, 255, .8) !important;
  background: transparent !important;
}
.cc-dot.is-on { background: #fff !important; border-color: #fff !important; }

/* ...and one shape for both arrows. */
.cc-nav,
.cc-prev,
.cc-next {
  width: 36px !important;
  height: 36px !important;
  border-radius: 50% !important;
  display: grid !important;
  place-items: center !important;
  padding: 0 !important;
  border: 1px solid rgba(255, 255, 255, .55) !important;
  background: rgba(13, 34, 51, .38) !important;
  color: #fff !important;
}
.cc-nav:hover { background: rgba(13, 34, 51, .66) !important; border-color: #fff !important; }

/* =====================================================================
   50. THE QUESTIONS BLOCK
   "the edges are too square" - the home page accordion was a single
   hard-cornered rectangle with hairlines across it, sitting in the left
   half of the row with nothing in the right half.

   Each question is now its own rounded card, and the heading moves
   beside the stack so the row is used.
   ===================================================================== */
.home-faq-split {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: 48px;
  align-items: start;
}
.home-faq-intro .section-title { margin-bottom: 10px; }
.home-faq-intro .section-lead { max-width: 30ch; }

.home-faq-grid {
  display: flex;
  flex-direction: column;
  gap: 12px;
  border: 0 !important;
  background: none !important;
  border-radius: 0 !important;
}
.home-faq-grid .faq-item,
.faq-layout .faq-item {
  border: 1px solid rgba(13, 34, 51, .13) !important;
  border-radius: 16px !important;
  background: #fbfaf7 !important;
  overflow: hidden;              /* the inner button cannot square the corner */
  transition: border-color .2s ease, box-shadow .2s ease;
}
.home-faq-grid .faq-item:hover,
.faq-layout .faq-item:hover {
  border-color: rgba(20, 87, 127, .38) !important;
  box-shadow: 0 8px 22px -18px rgba(13, 34, 51, .6);
}
.home-faq-grid .faq-question,
.faq-layout .faq-question {
  border-radius: 16px !important;
  background: none !important;
  border: 0 !important;
}
.home-faq-grid .faq-item.is-open,
.faq-layout .faq-item.is-open { border-color: rgba(20, 87, 127, .45) !important; }

@media (max-width: 991px) {
  .home-faq-split { grid-template-columns: 1fr; gap: 26px; }
  .home-faq-intro .section-lead { max-width: none; }
}

/* =====================================================================
   51. THE SOCIAL ICONS
   In the footer they were dark blue on a slightly-less-dark blue chip,
   sitting on the ink footer - all but invisible. On the contact page
   the same markup had white glyphs on a white panel, so they only
   appeared when the cursor was over them.

   One treatment everywhere: a white glyph on a quiet chip, and on hover
   the chip takes the network's own colour. That is the only place on
   the site where a colour outside the three is allowed, and it lasts
   exactly as long as the cursor is on it.
   ===================================================================== */
.social-icons a,
.social-icons.modern-icons a {
  display: inline-grid !important;
  place-items: center !important;
  width: 38px;
  height: 38px;
  border-radius: 50% !important;
  color: #fff !important;
  background: var(--ink) !important;          /* on a pale panel */
  border: 1px solid transparent !important;
  transition: background .18s ease, transform .18s ease, box-shadow .18s ease;
}
.social-icons a i,
.social-icons a svg { color: #fff !important; fill: currentColor; }
.social-icons a svg { width: 17px; height: 17px; }

/* On the ink footer the chip is a wash of white instead, so the row does
   not read as six black dots. */
.site-footer .social-icons a,
.bg-dark .social-icons a,
.footer-brandbar .social-icons a {
  background: rgba(255, 255, 255, .12) !important;
  border-color: rgba(255, 255, 255, .22) !important;
}

.social-icons a:hover,
.social-icons a:focus-visible { transform: translateY(-2px); border-color: transparent !important; }

/* ...and on hover, the real thing. */
.social-icons a[href*="facebook"]:hover  { background: #1877f2 !important; }
.social-icons a[href*="instagram"]:hover { background: #e1306c !important; }
.social-icons a[href*="linkedin"]:hover  { background: #0a66c2 !important; }
.social-icons a[href*="youtube"]:hover   { background: #ff0000 !important; }
.social-icons a[href*="wa.me"]:hover,
.social-icons a[href*="whatsapp"]:hover  { background: #25d366 !important; }
/* X and TikTok are black, which needs a ring to show on the ink footer. */
.social-icons a[href*="x.com"]:hover,
.social-icons a[href*="twitter"]:hover,
.social-icons a[href*="tiktok"]:hover {
  background: #000 !important;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .6);
}

/* =====================================================================
   52. TYPE ON A HERO IS LIGHT TYPE
   The about page put its standfirst in ink at 64% on a dark navy hero,
   and its eyebrow in the brand blue on the same dark ground. Both were
   set for a pale page and never restated for a dark one. The same rule
   was hiding the lead on the primary school page.

   Everything inside a hero that is not the headline now reads as light
   type, once, for every hero on the site.
   ===================================================================== */
.page-hero .eyebrow,
.school-hero .eyebrow,
.hero .eyebrow,
.hero-content .eyebrow {
  color: rgba(255, 255, 255, .78) !important;
  background: rgba(255, 255, 255, .12) !important;
  border-color: rgba(255, 255, 255, .22) !important;
}
.page-hero p,
.school-hero p,
.hero-content p,
.page-hero .lead, .school-hero .lead, .hero-content .lead,
.page-hero li, .school-hero li,
.page-hero .section-lead, .school-hero .section-lead {
  color: rgba(255, 255, 255, .88) !important;
}
.page-hero h1, .school-hero h1, .hero-content h1, .hero-content .hero-h,
.page-hero h2, .school-hero h2 { color: #fff !important; }
.page-hero a:not(.btn-pill):not(.btn-hero),
.school-hero a:not(.btn-pill):not(.btn-hero) { color: #fff !important; }

/* A hero with no photograph behind it is the exception: there the page
   is paper, so the type stays ink. */
.page-hero.is-plain .eyebrow,
.page-hero.is-plain p,
.page-hero.is-plain h1 { color: var(--ink) !important; }

/* The about page overview used a two-column split whose left column was
   an empty div, so half the row was literally nothing. The visual takes
   the whole measure instead. */
.about-visual-wrap { display: block; }
.about-visual-wrap .about-visual {
  position: relative;
  width: 100%;
  border-radius: var(--r-card, 14px);
  overflow: hidden;
}

/* The eyebrow on a hero is .hero-badge, not .eyebrow, which is why the
   rule above did not reach it: brand blue on dark navy, exactly the
   "not the best colour because the background is a bit dark" that was
   reported. It also still carried a shimmer sweep from the days when it
   was a filled chip - with no chip left to sweep, that animation was
   just a pale smear crossing the words. */
.page-hero .hero-badge,
.school-hero .hero-badge,
.hero .hero-badge,
.hero-content .hero-badge {
  color: rgba(255, 255, 255, .86) !important;
  background: none !important;
  overflow: visible;
}
.page-hero .hero-badge::after,
.school-hero .hero-badge::after,
.hero .hero-badge::after,
.hero-content .hero-badge::after { content: none !important; animation: none !important; }

/* Two campuses side by side use the same tile as the home page, so the
   site reads as one thing: the cards were bare text slabs with square
   corners, no photograph, and two links that did the same job - one
   written into the page and one added by the gallery script. */
.campus-tiles-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 767px) { .campus-tiles-2 { grid-template-columns: 1fr; } }
.campus-tile .campus-tile-body p { overflow-wrap: anywhere; }
/* the gallery script adds its own button to anything it recognises */
.campus-tile .gallery-open-btn,
.campus-tile .gallery-open-link:not(.campus-tile-open) { display: none !important; }

/* =====================================================================
   53. THE GALLERY
   Twenty-two identical rectangles in three columns, each showing one
   photograph out of the three or four it actually holds. It read as a
   contact sheet, and the only way to see a second picture was to open
   the album.

   Three things are combined here: a lead album that runs across the
   top with its caption over the picture; a mosaic that lets one card in
   seven run wide so the grid has a rhythm; and, on every card, its own
   next and previous with the album still one click away.
   ===================================================================== */
#galleryGrid.masonry,
.gallery-grid.masonry {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-auto-flow: dense;
  gap: 22px;
  /* align-items: stretch removed - see section 69. This selector carries
     an id, so it beat every later attempt to let a card be its own
     height, and the slab of white under the short captions survived
     three fixes because of it. */
  align-items: start;
}
.gallery-card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: var(--r-card, 14px);
  border: 1px solid rgba(13, 34, 51, .10);
  background: #fff;
  padding: 0 !important;
  height: auto !important;
}

/* the picture */
.gc-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  background: #dfe6ec;
  overflow: hidden;
  flex: 0 0 auto;
}
.gc-shot {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  opacity: 0;
  transition: opacity .5s ease;
}
.gc-shot.is-on { opacity: 1; }

.gc-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 4;
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .55);
  background: rgba(13, 34, 51, .40);
  color: #fff;
  opacity: 0;
  transition: opacity .18s ease, background .18s ease;
  cursor: pointer;
}
.gc-prev { left: 10px; }
.gc-next { right: 10px; }
.gallery-card:hover .gc-nav,
.gallery-card:focus-within .gc-nav { opacity: 1; }
.gc-nav:hover { background: rgba(13, 34, 51, .72); border-color: #fff; }
@media (hover: none) { .gc-nav { opacity: 1; } }

.gc-dots {
  position: absolute;
  left: 0; right: 0; bottom: 10px;
  z-index: 3;
  display: flex;
  justify-content: center;
  gap: 6px;
  pointer-events: none;
}
.gc-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .85);
  background: transparent;
}
.gc-dot.is-on { background: #fff; }

/* how many photographs are in there, so the arrows are not a surprise */
.gc-count {
  position: absolute;
  top: 10px; right: 10px;
  z-index: 3;
  min-width: 24px;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(13, 34, 51, .55);
  color: #fff;
  font-family: var(--font-body);
  font-size: 11.5px;
  font-weight: 700;
  text-align: center;
}

/* the caption */
.gallery-card h3 {
  margin: 0;
  padding: 16px 18px 0;
  font-size: 19px;
  line-height: 1.18;
  color: var(--ink);
}
.gallery-card p {
  margin: 0;
  padding: 6px 18px 0;
  font-size: 14.5px;
  color: var(--ink-soft) !important;
}
.gallery-card .gallery-open-btn,
.gallery-card .gallery-open-link {
  margin: auto 0 0;
  padding: 14px 18px 16px;
}

/* --- the lead album ------------------------------------------------
   Across two columns, taller, with the caption over the picture. */
/* The picture is absolutely positioned, so it gives the card no height
   of its own: without this the lead album collapsed to the height of
   its caption the moment the grid stopped spanning two rows. */
.gallery-card.gc-lead {
  grid-column: span 2;
  grid-row: span 2;
  position: relative;
  min-height: 420px;
}
.gallery-card.gc-lead .gc-stage { aspect-ratio: auto; height: 100%; min-height: 380px; }
.gallery-card.gc-lead h3,
.gallery-card.gc-lead p,
.gallery-card.gc-lead .gallery-open-btn,
.gallery-card.gc-lead .gallery-open-link {
  position: relative;
  z-index: 3;
  color: #fff !important;
}
/* theme-2026 uses .gallery-card::after for a shimmer sweep that is kept
   at opacity 0 until hover, so the scrim under the lead caption was
   invisible until the cursor arrived - white type on a bright photo the
   rest of the time. This one is not a hover effect. */
.gallery-card.gc-lead::after {
  content: "" !important;
  position: absolute;
  left: 0 !important;
  right: 0;
  top: auto !important;
  bottom: 0;
  width: auto !important;
  height: 62% !important;
  z-index: 2;
  opacity: 1 !important;
  transform: none !important;
  animation: none !important;
  pointer-events: none;
  background: linear-gradient(0deg, rgba(6, 24, 42, .90) 0%, rgba(6, 24, 42, .58) 45%, rgba(6, 24, 42, 0) 100%) !important;
}
.gallery-card.gc-lead:hover::after { animation: none !important; }
.gallery-card.gc-lead .gc-stage { position: absolute; inset: 0; z-index: 1; }
/* The caption belongs at the bottom, where the scrim is. Left at the top
   it was white type over the bright part of the photograph. */
/* Section 40 sets these margins with !important, so the caption block
   cannot be moved to the foot of the lead card without matching it. */
.gallery-card.gc-lead > h3 {
  margin: auto 0 0 !important;
  padding: 0 22px 0 !important;
  font-size: clamp(22px, 2.2vw, 30px);
}
.gallery-card.gc-lead > p {
  margin: 0 !important;
  padding: 8px 22px 0 !important;
}
.gallery-card.gc-lead .gallery-open-btn,
.gallery-card.gc-lead .gallery-open-link {
  margin: 0 !important;
  padding: 12px 22px 20px !important;
}
.gallery-card.gc-lead .gc-count { top: 14px; right: 14px; }
.gallery-card.gc-lead .gc-dots { bottom: auto; top: 18px; left: 22px; right: auto; justify-content: flex-start; }

/* --- one in seven runs wide --------------------------------------- */
.gallery-card.gc-wide { grid-column: span 2; }
.gallery-card.gc-wide .gc-stage { aspect-ratio: 16 / 9; }

@media (max-width: 991px) {
  #galleryGrid.masonry, .gallery-grid.masonry { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gallery-card.gc-lead { grid-row: span 1; min-height: 360px; }
}
@media (max-width: 640px) {
  #galleryGrid.masonry, .gallery-grid.masonry { grid-template-columns: 1fr; }
  .gallery-card.gc-lead,
  .gallery-card.gc-wide { grid-column: span 1; }
  .gallery-card.gc-lead { min-height: 320px; }
}

/* =====================================================================
   54. EVERYTHING THAT FLOATS TAKES THE COLOUR OF THE PAGE
   "wherever the headers are, it takes the exact colour of the
   background" - the header does that now, and so should everything
   else that hovers over the page: the announcement, the back-to-top
   button and the mobile menu panel. They were all on #faf8f4, which is
   a fourth shade sitting a hair off the paper and reading as a
   separate white object.
   ===================================================================== */
.rsc-news,
.rsc-top,
.site-nav .navbar-collapse {
  background: rgba(242, 240, 235, .88) !important;
  -webkit-backdrop-filter: blur(16px) saturate(1.2);
  backdrop-filter: blur(16px) saturate(1.2);
  border: 1px solid rgba(13, 34, 51, .10) !important;
  box-shadow: 0 18px 40px -28px rgba(13, 34, 51, .65) !important;
}
.rsc-news, .rsc-news *:not(a):not(.rsc-news-eyebrow) { color: var(--ink); }
.rsc-top { color: var(--ink) !important; }
.rsc-top:hover {
  background: rgba(13, 34, 51, .92) !important;
  color: #fff !important;
}
/* A browser without backdrop-filter gets the flat paper instead of a
   translucent panel it cannot blur. */
@supports not (backdrop-filter: blur(4px)) {
  .rsc-news, .rsc-top, .site-nav .navbar-collapse { background: var(--paper) !important; }
}

/* =====================================================================
   55. THE LAST OF THE GOLD
   A sweep of every computed colour on seventeen pages turned up six
   more places where #f1a005 was still being painted - never as a fill,
   always as a glow or a drop shadow, which is why they survived the
   palette rewrite and the pixel audit: too diffuse to register as a
   block of colour, plenty strong enough to see.
   ===================================================================== */
.fb-cta,
#portalLoginForm button[type="submit"],
.portal-card button[type="submit"],
.result-search button {
  box-shadow: 0 12px 26px -14px rgba(13, 34, 51, .55) !important;
}
.cta-panel::before,
.cta-panel::after,
.footer-glow::before,
.footer-glow::after {
  background-image: radial-gradient(circle, rgba(20, 87, 127, .35), rgba(0, 0, 0, 0) 65%) !important;
}
.footer-glow::before { background-image: radial-gradient(circle, rgba(255, 255, 255, .10), rgba(0, 0, 0, 0) 60%) !important; }

/* The sign-in button had near-black type on the brand blue - the same
   fault as the call-to-action panel, in the one place a parent has to
   press to see their child's results. */
#portalLoginForm button[type="submit"],
.portal-card button[type="submit"],
.portal-form button[type="submit"] {
  color: #fff !important;
  font-weight: 700 !important;
}

/* =====================================================================
   56. WHAT A CONTRAST SWEEP OF EIGHTEEN PAGES FOUND
   Every piece of text on the site was measured against the colour
   actually painted behind it. These are the ones that failed, and they
   are all the same fault reported three times in three different
   places: type coloured for a pale page, left sitting on a dark one,
   or the reverse.
   ===================================================================== */

/* The blue call-to-action panel is dark, so everything in it is light.
   The standfirst was ink at 64% on ink - a ratio of 1.00, which is to
   say invisible. */
.cta-panel,
.cta-panel p,
.cta-panel .section-lead,
.cta-panel .section-copy,
.cta-panel li,
.cta-panel h2,
.cta-panel h3,
.cta-panel .section-title {
  color: #fff !important;
}
.cta-panel .section-lead,
.cta-panel p { color: rgba(255, 255, 255, .88) !important; }
.cta-panel .eyebrow {
  color: rgba(255, 255, 255, .80) !important;
  background: rgba(255, 255, 255, .12) !important;
}

/* The caption over the campus video: the heading was white and the line
   under it was the brand blue at 9 per cent. */
.about-visual .visual-copy h3 { color: #fff !important; }
.about-visual .visual-copy p { color: rgba(255, 255, 255, .88) !important; }

/* The X mark in the social row carries its own colour, so the rule that
   turned the icons white never reached it: dark blue on the ink footer. */
.social-icons a .x-icon,
.social-icons .x-icon,
.social-icons a span { color: #fff !important; }

/* Two "Start admission" buttons had near-black brown type on the brand
   blue - the same fault as the panel, in the two places it is pressed
   most. */
.fb-cta,
.footer-brandbar .btn-pill,
.btn-pill.is-solid,
a.btn-pill[class*="fb-"] { color: #fff !important; }
.footer-brandbar .btn-pill,
.fb-cta { background: var(--brand) !important; font-weight: 700 !important; }
.footer-brandbar .btn-pill:hover,
.fb-cta:hover { background: #fff !important; color: var(--ink) !important; }

/* The site credit in the footer was brand blue on ink. theme-2026 sets
   it through .footer-credit .kaevor-brand with !important, so this has
   to match that reach. */
/* The site credit is owned by section 73. */

/* An eyebrow on a dark panel reads light, like every other eyebrow on a
   dark ground. */
.cta-panel .eyebrow,
.bg-dark .eyebrow,
.site-footer .eyebrow { color: rgba(255, 255, 255, .78) !important; }

/* Notes set in a pale grey that only just missed. */
.map-note, .map-grid em, .map-card em { color: #5b6b78 !important; }

/* The quiet half of the language switch was a shade too quiet to read. */
.lang-switcher a:not(.lang-active) { color: rgba(13, 34, 51, .70) !important; }
body.nav-over-hero .site-nav .lang-switcher a:not(.lang-active) {
  color: rgba(255, 255, 255, .80) !important;
}

/* =====================================================================
   57. THE QUIET BUTTONS, AFTER THE GOLD WAS REMOVED
   theme-2026 sets the type on every .btn-pill with !important, from
   when every pill was a filled gold one. Those hexes have been changed
   from the gold-era brown to white, which is right for a filled button
   and wrong for an outlined one - and rsc.css turns most pills into
   outlined ones. So the outlined pills state their own colour here,
   with the same weight.
   ===================================================================== */
.btn-pill.btn-quiet,
.section .btn-pill:not(.btn-gold):not(.btn-hero):not(.nav-cta):not(.btn-filled),
.button-row .btn-pill:not(.btn-gold):not(.btn-hero):not(.nav-cta):not(.btn-filled),
.results-band-cta,
.news-card .btn-pill,
.rsc-partnership-actions .btn-pill,
.about-partner-feature .btn-pill {
  color: var(--brand, #14577f) !important;
  background: transparent !important;
  border: 1px solid var(--line, #dcd8d0) !important;
}
.btn-pill.btn-quiet:hover,
.section .btn-pill:not(.btn-gold):not(.btn-hero):not(.nav-cta):hover,
.button-row .btn-pill:not(.btn-gold):not(.btn-hero):not(.nav-cta):hover,
.results-band-cta:hover,
.news-card .btn-pill:hover,
.rsc-partnership-actions .btn-pill:hover,
.about-partner-feature .btn-pill:hover {
  color: #fff !important;
  background: var(--brand, #14577f) !important;
  border-color: var(--brand, #14577f) !important;
}

/* Inside the dark admission panel the same pills are light-on-dark, and
   the first one is the filled action. */
.cta-panel .btn-pill,
.cta-panel .button-row .btn-pill:not(.btn-gold):not(.btn-hero) {
  color: #fff !important;
  background: transparent !important;
  border: 1px solid rgba(255, 255, 255, .34) !important;
}
.cta-panel .button-row .btn-pill:first-child,
.cta-panel a.btn-pill:first-child {
  background: #fff !important;
  color: var(--ink) !important;
  border-color: #fff !important;
}
.cta-panel .btn-pill:hover {
  background: rgba(255, 255, 255, .16) !important;
  color: #fff !important;
}
.cta-panel .button-row .btn-pill:first-child:hover,
.cta-panel a.btn-pill:first-child:hover {
  background: rgba(255, 255, 255, .88) !important;
  color: var(--ink) !important;
}

/* On a hero the buttons sit on a photograph: the first is solid, the
   second is an outline in white. */
.hero-content .btn-pill:not(.btn-hero),
.page-hero .btn-pill:not(.btn-hero),
.school-hero .btn-pill:not(.btn-hero),
.btn-secondary-hero {
  color: #fff !important;
  background: transparent !important;
  border: 1px solid rgba(255, 255, 255, .45) !important;
}
.btn-secondary-hero:hover,
.hero-content .btn-pill:not(.btn-hero):hover {
  background: rgba(255, 255, 255, .16) !important;
  color: #fff !important;
}

/* =====================================================================
   58. A TESTIMONIAL WITH A FACE
   The carousel avatars are initials in a circle; this one is a
   photograph, so it needs the same circle and a cover fit rather than
   the grid centring the initials used.
   ===================================================================== */
.tm-avatar-photo {
  display: block !important;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  object-fit: cover;
  /* the photograph is a selfie, so the face sits right of centre and a
     little high - this puts it in the middle of the circle */
  object-position: 62% 38%;
  background: var(--brand-soft, #e7ecef);
}
#testimonialGrid .testimonial-card > img.avatar-photo {
  object-position: 62% 38%;
  border-color: rgba(13, 34, 51, .10);
}

/* =====================================================================
   59. THE GALLERY, BUILT FROM YOUR THREE REFERENCES
   All three, rather than one of them:

     the fan of angled cards, from "Award Winning Creators";

     the way the row reads as a stage with the neighbours turned in
     toward the middle, from "Explore Our Gallery";

     and the mixed-size mosaic with a Load More from the Bootstrap
     reference, which is the grid below (section 53).

   Five cards, not seven, and the row ends where every other element on
   the page ends: "it should end in line with the other elements, it
   should not cross and go right to the borders". The two that used to
   run off the edges are gone.
   ===================================================================== */
.gal-arc {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(10px, 1.4vw, 22px);
  margin: 34px 0 6px;
  padding: 30px 0 38px;
  perspective: 1100px;
}
.gal-arc-card {
  /* animations.css runs a "stagger-in" keyframe on children of a
     revealed block, and its last frame sets a transform. An animation's
     value beats a declared one for as long as it is filling, so every
     card in the arc sat perfectly flat and the fan never appeared. */
  animation: none !important;
  flex: 0 1 auto;
  width: clamp(120px, 15vw, 218px);
  height: clamp(164px, 20vw, 292px);
  padding: 0;
  border: 0;
  border-radius: 16px;
  background-color: #dfe6ec;
  background-size: cover;
  background-position: center;
  box-shadow: 0 26px 52px -30px rgba(13, 34, 51, .8);
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transform-style: preserve-3d;
  transition: transform .45s cubic-bezier(.16, 1, .3, 1), box-shadow .3s ease;
}
/* Turned a little further from the centre each step, and lifted, so the
   row curves toward the reader. */
.gal-arc-card:nth-child(1) { transform: rotateY(30deg) translateZ(-30px) translateY(-6px); }
.gal-arc-card:nth-child(2) { transform: rotateY(16deg) translateZ(-8px) translateY(-18px); }
.gal-arc-card:nth-child(3) {
  transform: none;
  width: clamp(148px, 18.5vw, 268px);
  height: clamp(200px, 24vw, 348px);
}
.gal-arc-card:nth-child(4) { transform: rotateY(-16deg) translateZ(-8px) translateY(-18px); }
.gal-arc-card:nth-child(5) { transform: rotateY(-30deg) translateZ(-30px) translateY(-6px); }

/* The gallery script adds a "View photos" button to anything it
   recognises as an album. These are photographs, not album cards; the
   whole card is the button. */
.gal-arc-card .gallery-open-btn,
.gal-arc-card .gallery-open-link,
.gal-arc-card .gc-stage,
.gal-arc-card .gc-count,
.gal-arc-card .gc-nav,
.gal-arc-card .gc-dots,
.gal-arc-card h3,
.gal-arc-card p { display: none !important; }

.gal-arc-card::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, rgba(6, 24, 42, .80) 0%, rgba(6, 24, 42, 0) 62%);
  opacity: 0;
  transition: opacity .25s ease;
}
.gal-arc-label {
  position: absolute;
  left: 12px; right: 12px; bottom: 12px;
  z-index: 2;
  color: #fff;
  font-family: var(--font-body);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .02em;
  text-align: left;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity .25s ease, transform .25s ease;
}
.gal-arc-card:hover,
.gal-arc-card:focus-visible {
  transform: rotateY(0deg) translateY(-14px) scale(1.05);
  box-shadow: 0 36px 64px -28px rgba(13, 34, 51, .85);
  z-index: 3;
}
.gal-arc-card:hover::after,
.gal-arc-card:focus-visible::after { opacity: 1; }
.gal-arc-card:hover .gal-arc-label,
.gal-arc-card:focus-visible .gal-arc-label { opacity: 1; transform: none; }

@media (max-width: 991px) { .gal-arc { padding: 22px 0 28px; } }

/* On a phone the fan is kept, just flatter and with the labels always
   showing - "it should have that kind of view that it had on desktop".
   A row of plain photographs with no state is what it looked like
   before, and that is what was reported. */
@media (max-width: 640px) {
  .gal-arc { gap: 10px; perspective: 700px; padding: 16px 0 24px; }
  .gal-arc-card { width: 28vw; height: 38vw; border-radius: 12px; }
  .gal-arc-card:nth-child(1) { transform: rotateY(18deg) translateZ(-12px) translateY(-4px); }
  .gal-arc-card:nth-child(2) { transform: rotateY(9deg) translateY(-9px); }
  .gal-arc-card:nth-child(3) { width: 34vw; height: 46vw; }
  .gal-arc-card:nth-child(4) { transform: rotateY(-9deg) translateY(-9px); }
  .gal-arc-card:nth-child(5) { transform: rotateY(-18deg) translateZ(-12px) translateY(-4px); }
  .gal-arc-card::after { opacity: 1; }
  .gal-arc-label { opacity: 1; transform: none; font-size: 10.5px; left: 8px; right: 8px; bottom: 8px; }
}

/* Five albums fanned across a 390px screen leaves each one about 100px
   wide, and "Science laboratory" was cut off mid-word inside it. The two
   outermost turn away from the reader anyway, so on a phone the fan is
   three: the same three cards, big enough to carry their own names.
   "There are three cards here; when I click on them the name shows, but
   it should have that view it had on desktop." */
@media (max-width: 575px) {
  .gal-arc { gap: 10px; padding: 14px 0 22px; }
  .gal-arc-card:nth-child(1),
  .gal-arc-card:nth-child(5) { display: none; }
  .gal-arc-card { width: 30vw; height: 41vw; }
  .gal-arc-card:nth-child(2) { transform: rotateY(15deg) translateZ(-10px) translateY(-8px); }
  .gal-arc-card:nth-child(3) { width: 36vw; height: 49vw; transform: none; }
  .gal-arc-card:nth-child(4) { transform: rotateY(-15deg) translateZ(-10px) translateY(-8px); }
  /* The scrim reaches further up the picture so a two-line name still
     sits on ink, not on a bright patch of the photograph. */
  .gal-arc-card::after {
    opacity: 1;
    background: linear-gradient(0deg, rgba(6, 24, 42, .88) 0%, rgba(6, 24, 42, .20) 48%, rgba(6, 24, 42, 0) 74%);
  }
  .gal-arc-label {
    font-size: 11px;
    line-height: 1.22;
    letter-spacing: 0;
    left: 9px; right: 9px; bottom: 9px;
    overflow-wrap: anywhere;
  }
}
@media (prefers-reduced-motion: reduce) {
  .gal-arc-card { transition: none; }
  .gal-arc-card:hover { transform: none; }
}

/* Load More is gone - see section 74. Nothing on the gallery is held
   back any more, and an album added to the page simply appears. These two
   rules stay only so a page still carrying the old markup does not show a
   dead button or hide an album behind a class nothing sets. */
.gal-more-wrap { display: none !important; }
.gallery-card.is-held { display: flex !important; }

/* The "Continue exploring" strip is ink with white type. On the two
   announcement posts its inner block had picked up a white card
   background, so the heading and the line under it were white on white
   and the strip opened with a blank white box in it. Found by the
   contrast sweep, not by eye. */
.internal-links-strip .strip-copy,
.internal-links-strip .strip-inner > div:first-child {
  background: transparent !important;
  box-shadow: none !important;
  border: 0 !important;
  padding: 0 !important;
}
.internal-links-strip .strip-copy h3,
.internal-links-strip .strip-copy p { color: #fff !important; }
.internal-links-strip .strip-copy p { opacity: .82; }

/* =====================================================================
   60. (retired - see section 72, which owns the hero glass)
   ===================================================================== */

/* =====================================================================
   61. THE LANGUAGE SWITCH, PROPERLY MADE
   It works, but it was a plain pill with a plain knob. Same two
   colours, more care: a ring that reads as a control, a knob that
   moves with weight behind it, and a state you can see at a glance
   from either side.
   ===================================================================== */
.site-nav .lang-switcher {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0;
  padding: 3px;
  border-radius: 999px;
  overflow: visible;
  transition: background .2s ease, border-color .2s ease, box-shadow .2s ease;
}
.site-nav .lang-switcher::before {
  top: 3px; bottom: 3px; left: 3px;
  width: calc(50% - 3px);
  border-radius: 999px;
  box-shadow: 0 1px 2px rgba(13, 34, 51, .22), 0 4px 10px -6px rgba(13, 34, 51, .5);
  transition: transform .3s cubic-bezier(.16, 1, .3, 1), box-shadow .2s ease;
}
.site-nav .lang-switcher a {
  min-width: 40px;
  height: 27px !important;
  line-height: 27px !important;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .09em;
  transition: color .22s ease, opacity .22s ease;
}
.site-nav .lang-switcher a.lang-active { letter-spacing: .09em; }
/* The half that is not chosen lifts a little on hover, so it reads as
   the thing you press rather than a label. */
.site-nav .lang-switcher a:not(.lang-active):hover { opacity: 1; }
.site-nav .lang-switcher:hover::before { box-shadow: 0 2px 4px rgba(13, 34, 51, .26), 0 6px 14px -6px rgba(13, 34, 51, .55); }
.site-nav .lang-switcher:focus-within {
  box-shadow: 0 0 0 3px rgba(20, 87, 127, .28);
}
body.nav-over-hero .site-nav .lang-switcher:focus-within {
  box-shadow: 0 0 0 3px rgba(255, 255, 255, .38);
}

/* =====================================================================
   62. EVERY CARD ENDS WHERE ITS CONTENT ENDS
   "You should not have cards where there is white space after the card.
   The gap between the last thing inside a card and the space down
   should not be too much." Named: the RIC "a clear path" card on
   desktop, and the gap between a gallery card's title and View photos.

   The cause is always the same. A grid stretches every card in a row to
   the height of the tallest one, and the slack lands at the bottom. So
   the LAST element in a card takes the slack instead: it is pushed to
   the foot of the card, and the empty run appears above it as spacing
   rather than below it as a hole.
   ===================================================================== */
.gallery-card,
.campus-tile,
.news-card,
.campus-gallery-card,
.about-card,
.result-card,
.contact-card,
.team-card,
.school-photo-card,
.panel,
.year-card,
.campus-card {
  display: flex;
  flex-direction: column;
}
/* The link or button at the foot of a card sits on the bottom edge. */
.gallery-card > .gallery-open-btn,
.gallery-card > .gallery-open-link,
.gallery-card > .btn-link-inline,
.campus-tile .campus-tile-body > .btn-link-inline,
.news-card > .btn-pill,
.news-card > .btn-link-inline,
.campus-gallery-card .copy > .btn-link-inline,
.about-card > .btn-link-inline,
.result-card > .btn-link-inline,
.contact-card > .btn-link-inline,
.panel > .btn-link-inline,
.panel > .button-row:last-child { margin-top: auto !important; }

/* ...and where a card has no such link, the copy is what ends it, so
   the card is only as tall as the copy needs. A row of cards still
   lines up, because the grid handles that; what it must not do is leave
   a blank slab under the words. */
.about-card > *:last-child,
.result-card > *:last-child,
.contact-card > *:last-child,
.panel > *:last-child,
.year-card > *:last-child,
.team-card .team-body > *:last-child,
.campus-gallery-card .copy > *:last-child { margin-bottom: 0 !important; }

/* The gallery card's caption block, so the title and the line under it
   stay together and the button goes to the foot rather than the title
   floating alone with a hole beneath it. */
.gallery-card > h3 { margin-bottom: 0 !important; }
.gallery-card > p { margin-bottom: 0 !important; padding-bottom: 14px !important; }

/* A card with a picture and only a heading (no paragraph) was the worst
   of them: the heading sat near the top and the button at the bottom,
   with the whole middle empty. */
.gallery-card > h3:last-of-type:not(:has(+ p)) { padding-bottom: 4px; }

/* =====================================================================
   63. ONE SYSTEM FOR TEXT COLOUR
   "Some writings are in blue, some are in black, some are in a grey" -
   said of the three-schools cards, and true across the site. A sweep of
   every visible string on eight pages found twelve different text
   colours in use. Most were the three at different opacities, which is
   the system working; three were not.

   The system, stated once:

     headings and body        ink            #0d2233
     supporting / secondary   ink at 64%
     links and eyebrows       brand blue     #14577f
     anything on a dark band  white, or white at 72-88%

   Nothing else. A fourth tone, however slight, is what reads as "not
   clean" even when nobody can name it.
   ===================================================================== */

/* The pale blue in the footer was a fourth tone. */
.site-footer,
.site-footer p,
.site-footer li,
.site-footer .fb-motto,
.site-footer .contact-mini,
.site-footer .footer-links a,
.footer-bottom,
.footer-policy-links a { color: rgba(255, 255, 255, .72) !important; }
.site-footer .ft-brand, .site-footer .ft-col, .site-footer strong { color: #fff !important; }
.site-footer a:hover, .footer-policy-links a:hover { color: #fff !important; }

/* The second blue on the wordmark. */
.navbar-brand.brand,
.navbar-brand.brand span { color: inherit !important; }

/* The stray grey. */
.small-copy, .meta, .utility-note, .ticker-date,
.map-note, .campus-gallery-card .copy p { color: var(--ink-soft) !important; }

/* --- inside a card, one weight per job ------------------------------
   The three-schools cards carried four: a blue eyebrow, an ink
   heading, a 64% line, a blue link and then a SECOND link set in the
   same 64% as the body copy, so one of the two links did not read as a
   link at all. Links are blue; the difference between the primary and
   the secondary one is size and weight, not a third colour. */
.campus-card .campus-prospectus,
.campus-copy .campus-prospectus,
.gallery-card .btn-link-inline,
.news-card .btn-link-inline {
  color: var(--brand) !important;
  font-weight: 600;
  font-size: 13.5px;
  opacity: .82;
}
.campus-card .campus-prospectus:hover,
.campus-copy .campus-prospectus:hover { opacity: 1; color: var(--ink) !important; }

/* =====================================================================
   64. THE BLOG POST HEADER
   Two faults, both reported:

   The capsule beside "Back to News & Blog" was brand blue type on a
   brand blue fill. Blue on blue: the word "Announcement" was there the
   whole time and could not be seen.

   The date and the byline were set in ink at 64%, which is right for a
   pale page and invisible on the dark photograph the post hero uses.

   The little calendar and pencil beside them were emoji. They go: the
   line reads as type now, which is also what the rest of the site does.
   ===================================================================== */
.blog-post-hero .blog-post-category,
.blog-post-category {
  background: #fff !important;
  color: var(--ink) !important;
  border: 0 !important;
  font-family: var(--font-body);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  padding: 6px 14px !important;
  border-radius: 999px !important;
}
.blog-post-hero .blog-post-meta,
.blog-post-hero .blog-post-date,
.blog-post-hero .blog-post-author,
.blog-post-meta .blog-post-date,
.blog-post-meta .blog-post-author {
  color: rgba(255, 255, 255, .84) !important;
  font-size: 14px;
}
.blog-post-meta .blog-post-date::before,
.blog-post-meta .blog-post-author::before,
.blog-post-date::before,
.blog-post-author::before { content: none !important; }
/* one hairline between them instead of two emoji */
.blog-post-meta .blog-post-author { position: relative; padding-left: 16px; }
.blog-post-meta .blog-post-author::after {
  content: "";
  position: absolute;
  left: 6px; top: 50%;
  width: 4px; height: 1px;
  background: rgba(255, 255, 255, .55);
}
.blog-post-hero a[href*="news"],
.blog-post-hero .back-link { color: #fff !important; }
.blog-post-hero h1 { text-shadow: 0 2px 22px rgba(6, 24, 42, .45) !important; }

/* =====================================================================
   73. THE SITE CREDIT, QUIETLY
   It was asked to stand out once, and then asked back down: "make it
   subtle, it should not be really this visible". It is a signature at the
   foot of somebody else's school, so it reads at the weight of the line
   it sits in and only lifts when somebody actually points at it.
   ===================================================================== */
.site-footer .footer-credit {
  color: rgba(255, 255, 255, .38) !important;
  font-size: 12.5px;
  letter-spacing: .01em;
}
.footer-credit .kaevor-brand,
.site-footer .kaevor-brand,
.kaevor-brand {
  color: rgba(255, 255, 255, .52) !important;
  font-weight: 500 !important;
  letter-spacing: .01em;
  border-bottom: 0;
  padding-bottom: 0;
  transition: color .2s ease;
}
.footer-credit .kaevor-brand:hover,
.footer-credit .kaevor-brand:focus-visible,
.site-footer .kaevor-brand:hover,
.kaevor-brand:hover {
  color: rgba(255, 255, 255, .88) !important;
  border-bottom: 0;
}

/* =====================================================================
   66. THE GAP UNDER THE MENU ON A PHONE
   "There's too much white space on mobile between where the menu ends
   and the text of the hero." On a page with no photograph behind the
   header, the first section was adding about 110px of its own padding
   ON TOP of the space the fixed bar already occupies, so the page
   opened with an empty band and the heading sat below the fold.
   ===================================================================== */
@media (max-width: 767px) {
  body .section[style*="padding-top:140px"],
  body .section.top-spacer,
  body .top-spacer { padding-top: 34px !important; }
  body .page-hero, body .school-hero { padding-top: 26px !important; }
  /* and the space under the last thing in that first block */
  .section .section-copy:last-child { margin-bottom: 0; }
}
@media (max-width: 991px) and (min-width: 768px) {
  body .section[style*="padding-top:140px"],
  body .section.top-spacer,
  body .top-spacer { padding-top: 54px !important; }
}

/* =====================================================================
   67. THE PLACE KEPT FOR A THIRD VOICE
   Three videos and three testimonials, no more. Two of the three
   testimonials are real; the third is a marked slot, so the shape of
   the section is right now and the words drop in when they arrive.
   It is obviously a placeholder - it does not pretend to be a quote.
   ===================================================================== */
.tm-avatar-waiting,
.testimonial-card-waiting .avatar-photo {
  background: transparent !important;
  border: 1.5px dashed rgba(13, 34, 51, .30) !important;
  color: rgba(13, 34, 51, .45) !important;
  font-size: 20px !important;
  font-weight: 400 !important;
}
.tm-quote-waiting,
.testimonial-card-waiting .quote {
  color: var(--ink-soft) !important;
  font-style: italic;
}
.testimonial-card-waiting {
  border: 1.5px dashed rgba(13, 34, 51, .22) !important;
  background: transparent !important;
  box-shadow: none !important;
}
.testimonial-card-waiting .meta { color: var(--ink-soft) !important; }

/* ==========================================================================
   68. THE WALK TO A RESULT
   Rewritten for the step-by-step portal: one question per screen. Some of
   these parents are opening a website to look at school marks for the first
   time, so every choice is a large target with its own line of plain words
   under it, and nothing on the screen is smaller than a phone keyboard key.
   ========================================================================== */

.portal-step-card h2 {
  font-family: var(--font-display);
  font-size: clamp(22px, 4.4vw, 30px);
  line-height: 1.15;
  margin: 0 0 4px;
  color: var(--ink);
}
.portal-step-card .portal-sub { margin-bottom: 18px; }

/* Sequence or term report card. Two doors, side by side, each saying what is
   behind it. */
.portal-kinds {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 12px;
  margin-top: 6px;
}
.portal-kind {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
  width: 100%;
  padding: 20px 20px 22px;
  text-align: left;
  background: #fff;
  border: 1px solid var(--line, #dcd8d0);
  border-left: 5px solid var(--brand, #14577f);
  border-radius: var(--r-card, 14px);
  cursor: pointer;
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.portal-kind:hover,
.portal-kind:focus-visible {
  box-shadow: var(--e2);
  transform: translateY(-2px);
  border-color: var(--brand, #14577f);
}
.portal-kind .pk-title {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 600;
  line-height: 1.2;
  color: var(--ink, #0d2233);
}
.portal-kind .pk-sub {
  font-size: 14px;
  line-height: 1.45;
  color: var(--ink-soft, #5b6b78);
}

/* The door off to the side: previous years. Deliberately quieter than the
   two choices above it, because nine parents in ten want this term. */
.portal-years {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 18px;
  padding: 11px 18px;
  background: transparent;
  border: 1px solid var(--brand, #14577f);
  border-radius: var(--r-pill, 999px);
  color: var(--brand, #14577f);
  font-family: var(--font-body);
  font-size: 14.5px;
  font-weight: 600;
  cursor: pointer;
  transition: background .18s ease, color .18s ease;
}
.portal-years:hover,
.portal-years:focus-visible {
  background: var(--brand, #14577f);
  color: #fff;
}

.portal-years-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(216px, 1fr));
  gap: 12px;
  margin-top: 6px;
}
.portal-year-btn {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  padding: 16px 18px;
  text-align: left;
  background: #fff;
  border: 1px solid var(--line, #dcd8d0);
  border-radius: var(--r-card, 14px);
  cursor: pointer;
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.portal-year-btn:hover,
.portal-year-btn:focus-visible {
  border-color: var(--brand, #14577f);
  box-shadow: var(--e2);
  transform: translateY(-2px);
}
.portal-year-btn .py-year {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 600;
  color: var(--ink, #0d2233);
  font-variant-numeric: lining-nums tabular-nums;
}
.portal-year-btn .py-count {
  font-size: 13px;
  color: var(--ink-soft, #5b6b78);
}

/* Said plainly, not as an error: the school has not published it yet. */
.portal-empty {
  margin: 6px 0 0;
  padding: 18px 20px;
  background: var(--paper, #f2f0eb);
  border: 1px dashed var(--line, #dcd8d0);
  border-radius: var(--r-card, 14px);
  font-size: 15px;
  color: var(--ink-soft, #5b6b78);
}

/* The back link is the escape hatch on a small screen, so it is a target,
   not a word. */
.portal-back {
  display: inline-block;
  min-height: 44px;
  line-height: 30px;
}

@media (max-width: 575px) {
  .portal-kinds,
  .portal-results,
  .portal-years-list { grid-template-columns: 1fr; }
  .portal-kind { padding: 17px 17px 18px; }
  .portal-years { width: 100%; justify-content: center; }
}

/* ==========================================================================
   69. NO SLAB UNDER THE WORDS
   Section 62 pushed a card's last link to the foot so the slack in a
   stretched row would read as spacing rather than a hole. On the gallery
   grid that turned out to be the wrong half of the fix: the slack was
   still there, just above the link instead of below it, and "Sports &
   inter-school matches" still had a hand's width of nothing between its
   description and View photos.

   The real answer is not to create the slack. A grid row stretches every
   card to the tallest; told to start instead, each card is exactly as tall
   as what is in it, and the row still lines up along its top edge because
   that is what a grid does. Only the cards that deliberately span two rows
   - the lead album, the wide one - are stretched back.
   ========================================================================== */
.masonry,
.cards-grid,
.campus-tiles,
.campus-tiles-2,
.leadership-grid,
.team-grid,
.tm-grid,
.home-faq-grid,
.results-band-grid { align-items: start; }

/* These two earn their height: they span two rows on purpose and carry
   their caption over the picture. */
.masonry .gallery-card.gc-lead,
.masonry .gallery-card.gc-wide { align-self: stretch; }

/* With no slack left to absorb, the foot link sits under the copy at its
   own spacing rather than being pushed away from it. */
.gallery-card > .gallery-open-btn,
.gallery-card > .gallery-open-link,
.gallery-card > .btn-link-inline { margin-top: 12px !important; }
.masonry .gallery-card.gc-lead > .gallery-open-btn,
.masonry .gallery-card.gc-lead > .gallery-open-link,
.masonry .gallery-card.gc-wide > .gallery-open-btn,
.masonry .gallery-card.gc-wide > .gallery-open-link { margin-top: auto !important; }

/* ==========================================================================
   70. THE BLOG CARD, BUILT LIKE A GALLERY CARD
   "The cards at the end of each block you would have to edit that too, or
   give it a better design using those screenshots."

   The screenshots are the gallery cards, and the shape is the same one:
   the photograph is the top edge of the card, not a picture floating in a
   padded box; then a small brand-blue line saying when and what; then the
   headline, the standfirst, and the link directly under the words.

   One block of rules, because the blog card is one component used in three
   places - the News & Blog page, the "More from Rainbow School Complex"
   strip at the foot of all 27 posts, and the French mirror of both.
   ========================================================================== */
.news-card {
  padding: 0 !important;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  height: auto !important;
  background: var(--surface, #fff);
  border: 1px solid rgba(13, 34, 51, .10);
  border-radius: var(--r-card, 14px);
  box-shadow: var(--e1);
  transition: box-shadow .22s ease, transform .22s ease, border-color .22s ease;
}
.news-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--e3);
  border-color: rgba(20, 87, 127, .30);
}

/* The picture is the card's top edge. */
.news-card > img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  height: auto !important;
  object-fit: cover;
  margin: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: var(--brand-soft, #e7ecef);
}

/* When and what, in the same small capitals the gallery uses for its
   photo count and the portal uses for its kind line. */
.news-card > .small-copy {
  margin: 0 !important;
  padding: 15px 18px 0;
  font-family: var(--font-body);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--brand, #14577f) !important;
}
.news-card > h3 {
  margin: 0 !important;
  padding: 6px 18px 0;
  font-size: 19px;
  line-height: 1.18;
  color: var(--ink, #0d2233);
}
.news-card > p {
  margin: 0 !important;
  padding: 7px 18px 0;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--ink-soft, #5b6b78) !important;
}

/* Under the words, not pushed away from them. A pill with a 210px floor
   filled the whole card and read as a banner; this is a link with a
   shape, the width of what it says. */
.news-card > .btn-pill,
.news-card > .btn-link-inline,
.news-card > .news-toggle {
  align-self: flex-start;
  min-width: 0 !important;
  width: auto !important;
  margin: 13px 18px 18px !important;
  padding: 10px 20px;
}

/* An expanded news body keeps the same left and right edge as the copy. */
.news-card .news-body { margin: 0 !important; }
.news-card .news-body > * { padding-left: 18px; padding-right: 18px; }
.news-card .news-body p { margin: 0 0 12px !important; }

/* The photo count on a campus carousel, matching the gallery card's. */
.campus-carousel { position: relative; }
.cc-count {
  position: absolute;
  top: 10px; right: 10px;
  z-index: 3;
  min-width: 24px;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(13, 34, 51, .55);
  color: #fff;
  font-family: var(--font-body);
  font-size: 11.5px;
  font-weight: 700;
  text-align: center;
  pointer-events: none;
}

/* ==========================================================================
   71. height:100% IS WHY THE CARDS HAD FLOORS
   compat.css, the oldest stylesheet here, ends its card rule with
   `height:100%`. In a grid that makes a card as tall as its whole row
   whatever is in it - which is how "What parents can expect from the
   general path" came to have a hand's depth of empty paper under two
   sentences, next to a photograph that set the row's height.

   Sections 62 and 69 both aimed at this and both missed, because they
   moved the slack about instead of removing the rule that creates it.
   The cards below are now as tall as what is in them. Rows still line up:
   the grid does that, and where a row genuinely should be level -
   .cards-grid, .leadership-grid, the map cards - section 40 still says so.
   ========================================================================== */
.panel,
.school-panel,
.about-card,
.media-pill,
.result-card,
.contact-card,
.testimonial-card,
.team-card,
.year-card,
.campus-card { height: auto !important; }

/* In a two-column split the card sits beside a picture that is taller than
   it. Centred next to the picture reads as deliberate; stretched to the
   picture's height reads as a mistake. */
.split > .panel,
.split > .about-card { align-self: center; }

/* ==========================================================================
   72. THE HERO IS A PANE OF GLASS, NOT A SHEET OVER THE LEFT HALF
   Three earlier attempts all did the same wrong thing: they raised the
   blur and then leaned a DIAGONAL wash across the picture, dark on the
   left where the headline sits and nearly clear on the right. That is
   what reads as "that sheet is only towards the left section". A pane of
   glass does not have a dark end.

   So the wash is even from edge to edge, and it is light - the work of
   hiding detail is done by the blur and by knocking the whole picture
   back a stop, which is what glass actually does to what is behind it.
   The result is the one asked for: you can see through it, you cannot
   read it. A person is plainly a person; whose face it is, you cannot
   say.
   ========================================================================== */
.hero .carousel-inner > .item::after,
.page-hero::after,
.school-hero::after {
  -webkit-backdrop-filter: blur(15px) saturate(.88) brightness(.66);
  backdrop-filter: blur(15px) saturate(.88) brightness(.66);
  /* Even across. The only gradient left runs bottom to top, and it is
     there because the buttons sit at the foot, not because the headline
     sits on the left. */
  background: linear-gradient(0deg,
      rgba(13, 34, 51, .40) 0%,
      rgba(13, 34, 51, .18) 42%,
      rgba(13, 34, 51, .14) 100%) !important;
}

/* Safari and older Android have no backdrop-filter, so there is no glass
   to see through and the wash has to do all of it. Kept even. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hero .carousel-inner > .item::after,
  .page-hero::after,
  .school-hero::after {
    background: linear-gradient(0deg,
        rgba(13, 34, 51, .78) 0%,
        rgba(13, 34, 51, .62) 42%,
        rgba(13, 34, 51, .58) 100%) !important;
  }
}

/* The bar across the top of the photograph. It had a pane of its own on
   top of the hero's, and two panes stacked is not glass any more, it is
   frosting - "with that glass now something in the video is not really
   legible". One pane only: the bar borrows the hero's. */
body.nav-over-hero .site-nav,
body.nav-over-hero .navbar.site-nav {
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
}

/* The headline has to carry on a pane this light, and it does it with its
   own shadow rather than by darkening the picture behind it - a shadow is
   local to the letters, a wash is a sheet over the campus. */
.hero-content h1, .hero-content .hero-h,
.page-hero h1,
.school-hero h1 {
  text-shadow: 0 2px 22px rgba(6, 20, 34, .55), 0 1px 3px rgba(6, 20, 34, .40);
}
.hero-content p,
.page-hero .section-copy,
.school-hero .section-copy {
  text-shadow: 0 1px 14px rgba(6, 20, 34, .50);
}
.hero-badge,
.page-hero .hero-badge {
  text-shadow: none;
}

/* --- where the pane actually has to live -----------------------------
   The home hero is a Bootstrap carousel, and Bootstrap puts a transform
   on .item. A transform makes a new stacking context, and backdrop-filter
   can only reach what is painted inside its own context - so the glass
   declared on .item::after was being drawn perfectly and filtering
   nothing, because the video is a sibling of the carousel, outside it.
   Three rounds of "make it blurrier" changed a number that never had any
   effect on the picture.

   The pane goes on the carousel itself, which is painted after the videos
   and has no transform. Everything that carries type - .hero-slide, the
   container, the controls - is inside .item and paints above it. */
.hero > .carousel::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  -webkit-backdrop-filter: blur(15px) saturate(.88) brightness(.66);
  backdrop-filter: blur(15px) saturate(.88) brightness(.66);
  /* Even from edge to edge. What varies is top to bottom, and only
     because the menu sits on the top edge and the buttons on the foot -
     both need ink under white type. */
  background: linear-gradient(0deg,
      rgba(13, 34, 51, .42) 0%,
      rgba(13, 34, 51, .18) 34%,
      rgba(13, 34, 51, .17) 66%,
      rgba(13, 34, 51, .40) 100%);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hero > .carousel::before {
    background: linear-gradient(0deg,
        rgba(13, 34, 51, .78) 0%,
        rgba(13, 34, 51, .62) 42%,
        rgba(13, 34, 51, .58) 100%);
  }
}
.hero > .carousel > .carousel-inner { position: relative; z-index: 1; }
.hero > .carousel > .carousel-control,
.hero > .carousel > .carousel-indicators { z-index: 3; }

/* ==========================================================================
   74. THE GALLERY: A WAVE IN, AND ONE ALBUM IN FOCUS
   "This show more I don't like it here in the gallery. It is just
   supposed to be all visible - a complete page that has everything, so
   each time we add things it will just automatically fit in."
   "From the onset when somebody loads and enters the page it should be
   like it has that wave effect, like a wave is passing from the top left
   down to the bottom right, so all the cards just have that wave effect
   like a sea."
   "Where my mouse is hovering over, it should actually be the focus. The
   other section should not be the focus."

   The delay per card is set in JavaScript from where the card actually
   sits in the grid, and arrives here as --wave. Nothing is hard coded to
   a number of albums or a number of columns, so the crest still crosses
   the page correctly the day somebody adds a twenty-third album.
   ========================================================================== */
.masonry.is-waving .gallery-card {
  opacity: 0;
  transform: translate3d(0, 26px, 0) scale(.975);
}
.masonry.is-waving .gallery-card.wave-in {
  opacity: 1;
  transform: none;
  transition:
    opacity .62s cubic-bezier(.22, 1, .32, 1) var(--wave, 0ms),
    transform .72s cubic-bezier(.22, 1, .32, 1) var(--wave, 0ms);
}
.masonry.is-waving .gallery-card.wave-done {
  transition: none;
}

/* The focus. The album under the pointer comes forward; the rest step
   back a little and lose some colour, so the eye has one place to be. */
.masonry .gallery-card {
  transition:
    transform .38s cubic-bezier(.22, 1, .32, 1),
    box-shadow .38s ease,
    filter .38s ease,
    opacity .38s ease,
    border-color .22s ease;
  will-change: transform;
}
.masonry.has-focus .gallery-card {
  filter: saturate(.55) brightness(.94);
  opacity: .72;
  transform: scale(.985);
}
.masonry.has-focus .gallery-card.is-focus {
  filter: none;
  opacity: 1;
  transform: scale(1.035);
  z-index: 5;
  box-shadow: 0 30px 60px -28px rgba(13, 34, 51, .55);
  border-color: rgba(20, 87, 127, .35);
}
/* The lead album is already the largest thing on the grid, so it grows
   less - at full scale it would push past the edge of the page. */
.masonry.has-focus .gallery-card.gc-lead.is-focus,
.masonry.has-focus .gallery-card.gc-wide.is-focus { transform: scale(1.015); }

/* A finger has no hover. Nothing dims on a phone, and the wave is the
   only motion. */
@media (hover: none) {
  .masonry.has-focus .gallery-card {
    filter: none;
    opacity: 1;
    transform: none;
  }
  .masonry.has-focus .gallery-card.is-focus { transform: none; box-shadow: var(--e2); }
}

@media (prefers-reduced-motion: reduce) {
  .masonry.is-waving .gallery-card,
  .masonry.is-waving .gallery-card.wave-in {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .masonry .gallery-card { transition: none; will-change: auto; }
}

/* ==========================================================================
   75. THE PICTURE PANELS ON THE SCHOOL PAGES
   "When you say hands-on sessions, the parents should see the hands-on
   session even before being able to click and see the pictures. Right now
   it feels like we are trying to hide the pictures."

   The photograph is the card. The words sit on a pane of glass over it -
   the same pane as the hero, so the site has one idea of what glass is -
   and the album is still one tap away underneath.
   ========================================================================== */
.picture-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 330px;
  padding: 0 !important;
  overflow: hidden;
  border-radius: var(--r-card, 14px);
  border: 1px solid rgba(13, 34, 51, .10);
  background: var(--brand-soft, #e7ecef);
  box-shadow: var(--e1);
  cursor: pointer;
  transition: box-shadow .28s ease, transform .28s ease, border-color .22s ease;
}
.picture-panel:hover,
.picture-panel:focus-within {
  transform: translateY(-3px);
  box-shadow: var(--e3);
  border-color: rgba(20, 87, 127, .30);
}

/* The photograph, behind everything, filling the card. */
.pp-stage {
  position: absolute !important;
  inset: 0;
  z-index: 0;
  aspect-ratio: auto !important;
  border-radius: 0;
}
.pp-stage .gc-shot { transition: opacity .9s ease; }
/* A slow drift, so a still photograph behind text is not quite still. */
.pp-stage .gc-shot.is-on { animation: pp-drift 18s ease-in-out infinite alternate; }
@keyframes pp-drift {
  from { transform: scale(1.03) translate3d(0, 0, 0); }
  to   { transform: scale(1.09) translate3d(-1.2%, -1.2%, 0); }
}
.pp-stage .gc-dots { bottom: auto; top: 12px; left: 12px; right: auto; justify-content: flex-start; }
.pp-stage .gc-count { top: 12px; right: 12px; }
.pp-stage .gc-nav { opacity: 0; }
.picture-panel:hover .gc-nav,
.picture-panel:focus-within .gc-nav { opacity: 1; }
@media (hover: none) { .pp-stage .gc-nav { opacity: 1; } }

/* The pane. */
.pp-body {
  position: relative;
  z-index: 2;
  margin: auto 10px 10px;
  padding: 15px 17px 16px;
  border-radius: 12px;
  -webkit-backdrop-filter: blur(14px) saturate(.9) brightness(.62);
  backdrop-filter: blur(14px) saturate(.9) brightness(.62);
  background: rgba(13, 34, 51, .26);
  border: 1px solid rgba(255, 255, 255, .13);
  color: #fff;
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .pp-body { background: rgba(13, 34, 51, .80); }
}
.pp-body > h3,
.pp-body > h4 {
  margin: 0 0 5px !important;
  font-family: var(--font-display);
  font-size: 18.5px;
  line-height: 1.16;
  color: #fff !important;
}
.pp-body > p {
  margin: 0 !important;
  font-size: 14px;
  line-height: 1.5;
  color: rgba(255, 255, 255, .88) !important;
}
.pp-body > p:last-of-type { margin-bottom: 0 !important; }
.pp-body .gallery-open-btn,
.pp-body .gallery-open-link,
.pp-body .btn-link-inline {
  margin: 11px 0 0 !important;
  padding: 0 !important;
  background: none !important;
  border: 0 !important;
  color: #fff !important;
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: .01em;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: rgba(255, 255, 255, .45);
  cursor: pointer;
}
.pp-body .gallery-open-btn:hover,
.pp-body .gallery-open-link:hover { text-decoration-color: #fff; }
/* Any list or tick-list inside a picture panel is white too. */
.pp-body ul,
.pp-body li,
.pp-body .small-copy,
.pp-body strong { color: rgba(255, 255, 255, .92) !important; }

/* A row of picture panels wants to be level: they carry no text of their
   own to be as tall as, and a ragged row of photographs reads as a mistake
   rather than as a mosaic. This is the one exception to section 69. */
.school-band,
.stats-three { align-items: stretch; }
.school-band .picture-panel,
.stats-three .picture-panel { align-self: stretch; height: auto !important; }

@media (max-width: 575px) {
  .picture-panel { min-height: 280px; }
  .pp-body { margin: auto 8px 8px; padding: 13px 14px 14px; }
  .pp-body > h3, .pp-body > h4 { font-size: 17px; }
}
@media (prefers-reduced-motion: reduce) {
  .pp-stage .gc-shot.is-on { animation: none; transform: none; }
  .picture-panel { transition: none; }
}

/* ==========================================================================
   76. THE SCHOOL CARDS COME FORWARD
   "When I hover over a certain card, it zooms and comes a bit in front -
   occupies, like it tries to cover the other two cards. Then the others
   become a bit smaller. It creates that dynamic feel."

   Done with the pointer on the ROW rather than on each card, so the two
   that are not being pointed at know to step back. The lifted card is
   allowed to overlap its neighbours, which is the whole effect; the row
   therefore cannot clip its own children.
   ========================================================================== */
.cards-grid,
.campus-tiles,
.campus-tiles-2 { overflow: visible; }

/* The entrance animation has to let go of the card when it finishes.
   theme-2026 gives every child of a revealed block `stagger-in ... both`,
   and a filling animation beats a declared transform for as long as it
   fills - which is forever with `both`. That is why three rounds of hover
   effects on these cards did nothing at all: the rule was right, the
   animation simply outranked it. `backwards` keeps the entrance (the card
   is still hidden through its delay and still slides up) and then hands
   the transform back. */
.cards-grid.reveal.is-visible > .campus-card,
.campus-tiles.reveal.is-visible > .campus-tile,
.masonry.reveal.is-visible > .gallery-card,
.school-band.reveal.is-visible > .picture-panel,
.stats-three.reveal.is-visible > .picture-panel {
  animation-fill-mode: backwards;
}

.cards-grid .campus-card,
.campus-tiles .campus-tile {
  position: relative;
  z-index: 1;
  transform-origin: center;
  transition:
    transform .42s cubic-bezier(.2, .9, .25, 1.06),
    box-shadow .42s ease,
    filter .42s ease,
    opacity .42s ease;
  will-change: transform;
}

/* Everything in the row steps back while one of them is being looked at. */
.cards-grid:hover .campus-card,
.cards-grid:focus-within .campus-card,
.campus-tiles:hover .campus-tile,
.campus-tiles:focus-within .campus-tile {
  transform: scale(.935);
  filter: saturate(.7) brightness(.96);
  opacity: .82;
}

/* And the one being looked at comes forward over them. */
.cards-grid .campus-card:hover,
.cards-grid .campus-card:focus-within,
.campus-tiles .campus-tile:hover,
.campus-tiles .campus-tile:focus-within {
  transform: scale(1.085);
  filter: none;
  opacity: 1;
  z-index: 6;
  box-shadow: 0 42px 80px -34px rgba(13, 34, 51, .62);
}

/* The first and last card lean inward rather than off the edge of the
   page, so nothing is ever cut off by the window. */
.cards-grid .campus-card:first-child:hover,
.campus-tiles .campus-tile:first-child:hover { transform: scale(1.085) translateX(2.2%); }
.cards-grid .campus-card:last-child:hover,
.campus-tiles .campus-tile:last-child:hover { transform: scale(1.085) translateX(-2.2%); }

/* A finger has no hover, and a card that grows under a thumb is a card
   that has moved before the tap lands. */
@media (hover: none) {
  .cards-grid:hover .campus-card,
  .campus-tiles:hover .campus-tile,
  .cards-grid .campus-card:hover,
  .campus-tiles .campus-tile:hover {
    transform: none;
    filter: none;
    opacity: 1;
  }
}
@media (prefers-reduced-motion: reduce) {
  .cards-grid .campus-card,
  .campus-tiles .campus-tile { transition: none; will-change: auto; }
  .cards-grid:hover .campus-card,
  .campus-tiles:hover .campus-tile { transform: none; filter: none; opacity: 1; }
  .cards-grid .campus-card:hover,
  .campus-tiles .campus-tile:hover { transform: none; box-shadow: var(--e3); }
}

/* ==========================================================================
   77. THE ONE DIALOG, FOR EVERY PICTURE AND EVERY FILM
   It replaces the photo lightbox and the video player, which were two
   different dialogs with two different manners. "That's too simple. It
   should be very, very beautiful - a card that comes out clean."

   A card on a pane of the blurred page, with a heading that says what you
   are looking at, a counter, a strip of the rest of the album along the
   foot, and arrows on the mat. Three colours, as everywhere else.
   ========================================================================== */
body.rsc-lb-open { overflow: hidden; }

.rsc-lb {
  position: fixed;
  inset: 0;
  z-index: 3000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(12px, 3vw, 40px);
}
.rsc-lb[hidden] { display: none; }

.rsc-lb-veil {
  position: absolute;
  inset: 0;
  background: rgba(8, 22, 36, .74);
  -webkit-backdrop-filter: blur(18px) saturate(.8) brightness(.72);
  backdrop-filter: blur(18px) saturate(.8) brightness(.72);
  opacity: 0;
  transition: opacity .26s ease;
}
.rsc-lb.is-open .rsc-lb-veil { opacity: 1; }

/* The card. */
.rsc-lb-card {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  width: min(1120px, 100%);
  max-height: 100%;
  padding: 18px 18px 14px;
  border-radius: 20px;
  background: var(--paper, #f2f0eb);
  box-shadow: 0 60px 120px -40px rgba(4, 16, 28, .85);
  opacity: 0;
  transform: translateY(16px) scale(.965);
  transition: opacity .3s cubic-bezier(.22, 1, .32, 1),
              transform .34s cubic-bezier(.22, 1, .32, 1);
}
.rsc-lb.is-open .rsc-lb-card { opacity: 1; transform: none; }

.rsc-lb-head {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 0 2px 12px;
}
.rsc-lb-heading { flex: 1 1 auto; min-width: 0; }
.rsc-lb-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(17px, 2.1vw, 21px);
  line-height: 1.16;
  color: var(--ink, #0d2233);
}
.rsc-lb-desc {
  margin: 3px 0 0;
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--ink-soft, #5b6b78);
}
.rsc-lb-count {
  flex: none;
  align-self: center;
  padding: 4px 11px;
  border-radius: 999px;
  background: rgba(13, 34, 51, .07);
  color: var(--ink-soft, #5b6b78);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .06em;
  font-variant-numeric: tabular-nums;
}
.rsc-lb-close {
  flex: none;
  width: 38px; height: 38px;
  display: grid;
  place-items: center;
  padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(13, 34, 51, .14);
  background: #fff;
  color: var(--ink, #0d2233);
  cursor: pointer;
  transition: background .18s ease, color .18s ease, border-color .18s ease;
}
.rsc-lb-close svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 2.1; stroke-linecap: round; }
.rsc-lb-close:hover { background: var(--ink, #0d2233); color: #fff; border-color: var(--ink, #0d2233); }

/* The mat the picture sits on. */
.rsc-lb-stage {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 14px;
  background: var(--ink, #0d2233);
  overflow: hidden;
}
.rsc-lb-frame {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}
.rsc-lb-media {
  display: block;
  max-width: 100%;
  max-height: min(70vh, 720px);
  width: auto;
  height: auto;
  object-fit: contain;
  opacity: 0;
  transform: scale(.985);
  transition: opacity .34s ease, transform .34s cubic-bezier(.22, 1, .32, 1);
}
.rsc-lb-media.is-in { opacity: 1; transform: none; }
video.rsc-lb-media { width: 100%; background: #000; }

.rsc-lb-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 46px; height: 46px;
  display: grid;
  place-items: center;
  padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .34);
  background: rgba(13, 34, 51, .42);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: #fff;
  cursor: pointer;
  transition: background .18s ease, border-color .18s ease, transform .18s ease;
}
.rsc-lb-arrow svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2.1; stroke-linecap: round; stroke-linejoin: round; }
.rsc-lb-arrow:hover { background: rgba(13, 34, 51, .82); border-color: #fff; }
.rsc-lb-prev { left: 14px; }
.rsc-lb-next { right: 14px; }
.rsc-lb-arrow[hidden] { display: none; }

/* The rest of the album, along the foot. */
.rsc-lb-strip {
  flex: none;
  display: flex;
  gap: 8px;
  margin-top: 12px;
  padding: 2px 2px 4px;
  overflow-x: auto;
  scrollbar-width: thin;
}
.rsc-lb-strip[hidden] { display: none; }
.rsc-lb-thumb {
  flex: 0 0 auto;
  width: 78px;
  height: 54px;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 8px;
  background: var(--brand-soft, #e7ecef) center / cover no-repeat;
  cursor: pointer;
  opacity: .62;
  transition: opacity .18s ease, border-color .18s ease, transform .18s ease;
}
.rsc-lb-thumb:hover { opacity: 1; transform: translateY(-2px); }
.rsc-lb-thumb.is-on { opacity: 1; border-color: var(--brand, #14577f); }
/* A film in the strip says so. */
.rsc-lb-thumb.is-film { position: relative; }
.rsc-lb-thumb.is-film::after {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  width: 0; height: 0;
  transform: translate(-40%, -50%);
  border-left: 11px solid #fff;
  border-top: 7px solid transparent;
  border-bottom: 7px solid transparent;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, .6));
}

@media (max-width: 767px) {
  .rsc-lb { padding: 0; align-items: flex-end; }
  .rsc-lb-card {
    width: 100%;
    max-height: 96vh;
    border-radius: 18px 18px 0 0;
    padding: 14px 12px 10px;
  }
  .rsc-lb-media { max-height: 56vh; }
  .rsc-lb-arrow { width: 40px; height: 40px; }
  .rsc-lb-prev { left: 8px; }
  .rsc-lb-next { right: 8px; }
  .rsc-lb-thumb { width: 62px; height: 44px; }
}

@media (prefers-reduced-motion: reduce) {
  .rsc-lb-card,
  .rsc-lb-veil,
  .rsc-lb-media { transition: none; }
  .rsc-lb-card { transform: none; }
}

/* The two dialogs this one replaces. Left in place only so a page that
   still carries their markup does not show an empty box. */
.modal-gallery,
.rsc-player { display: none !important; }

/* ==========================================================================
   78. THE TESTIMONIALS
   "The quotes you have put up, it is going out of that card slightly. And
   the person's picture is too tightly closed there, right there at the
   edge. It needs to have some breathing space."

   The card had a background and no padding, so the opening quote mark sat
   on the top edge and the photograph sat on the bottom one. Everything
   inside a card should be able to see the wall from where it stands.
   ========================================================================== */
.tm-slide,
.tm-grid .tm-slide {
  padding: clamp(24px, 3vw, 34px) clamp(22px, 3vw, 34px) clamp(22px, 2.6vw, 30px);
  border-radius: var(--r-card, 14px);
  border: 1px solid rgba(13, 34, 51, .09);
  box-shadow: var(--e1);
}
/* The mark belongs to the quotation, not to the corner of the card. */
.tm-slide .tm-mark {
  margin: 0 0 4px;
  font-size: clamp(46px, 5vw, 58px);
  line-height: .72;
  color: var(--brand, #14577f);
  opacity: .34;
}
.tm-slide .tm-quote { margin: 0 0 22px; }
/* And the person has room under the words and away from the edge. */
.tm-slide .tm-person {
  gap: 14px;
  padding-top: 16px;
  border-top: 1px solid rgba(13, 34, 51, .08);
}
.tm-slide .tm-avatar,
.tm-slide .tm-avatar-photo { width: 48px; height: 48px; }
.tm-slides { min-height: 0; }

/* The sound control on a film that starts by itself. */
.rsc-video-sound {
  position: absolute;
  left: 10px; bottom: 10px;
  z-index: 4;
  width: 40px; height: 40px;
  display: grid;
  place-items: center;
  padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .42);
  background: rgba(13, 34, 51, .52);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: #fff;
  cursor: pointer;
  transition: background .18s ease, border-color .18s ease, transform .18s ease;
}
.rsc-video-sound:hover { background: rgba(13, 34, 51, .84); border-color: #fff; transform: scale(1.05); }
.rsc-video-sound svg {
  width: 19px; height: 19px;
  fill: currentColor;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
}
.rsc-video-sound svg path:first-child { stroke-width: 1.2; }
.rsc-video-sound .ico-on { display: none; }
.rsc-video-sound.is-muted .ico-off { display: block; }
.rsc-video-sound.is-muted .ico-on { display: none; }
.rsc-video-sound:not(.is-muted) .ico-off { display: none; }
.rsc-video-sound:not(.is-muted) .ico-on { display: block; }

/* ==========================================================================
   79. "HAVE A RAINBOW STORY?"
   "Work on that card, it's not really the best."

   It was a white card with a white-ish button, sitting in a row of
   photographs and quotations and saying nothing for itself. It is an
   invitation, so it looks like one: the school's own blue, one line of
   welcome, and a button that is plainly a button.
   ========================================================================== */
.testimonial-card-cta {
  position: relative;
  display: flex !important;
  flex-direction: column;
  justify-content: center;
  gap: 8px;
  padding: 26px 24px 28px !important;
  border: 0 !important;
  border-radius: var(--r-card, 14px);
  background:
    radial-gradient(120% 140% at 0% 0%, rgba(255, 255, 255, .13) 0%, rgba(255, 255, 255, 0) 55%),
    var(--brand, #14577f);
  color: #fff;
  overflow: hidden;
  box-shadow: 0 24px 48px -26px rgba(13, 34, 51, .55);
}
/* A quiet WhatsApp glyph in the corner, so the card says how before it is
   read. Ink at low opacity, not a fourth colour. */
.testimonial-card-cta::after {
  content: "";
  position: absolute;
  right: -18px;
  bottom: -22px;
  width: 132px;
  height: 132px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .07);
}
.testimonial-card-cta > h3 {
  margin: 0 !important;
  font-family: var(--font-display);
  font-size: 21px;
  line-height: 1.16;
  color: #fff !important;
}
.testimonial-card-cta > p {
  margin: 0 !important;
  font-size: 14.5px;
  line-height: 1.55;
  color: rgba(255, 255, 255, .86) !important;
  max-width: 34ch;
}
.testimonial-card-cta .btn-pill {
  position: relative;
  z-index: 1;
  align-self: flex-start;
  margin: 14px 0 0 !important;
  min-width: 0 !important;
  width: auto !important;
  padding: 12px 22px;
  background: #fff !important;
  color: var(--brand, #14577f) !important;
  border: 0 !important;
  font-weight: 700;
  box-shadow: 0 10px 22px -12px rgba(4, 16, 28, .7);
  transition: transform .18s ease, box-shadow .18s ease;
}
.testimonial-card-cta .btn-pill:hover {
  transform: translateY(-2px);
  box-shadow: 0 16px 28px -12px rgba(4, 16, 28, .8);
  background: #fff !important;
  color: var(--accent-dark, #0d3c5a) !important;
}

/* A filled pill. The site's default is an outline pill inside a section,
   which is right nearly everywhere and wrong on a coloured panel, where an
   outline pill is the panel's own colour drawn on itself. Marking the pill
   .btn-filled is how a card says it needs the solid one; the outline rule
   excludes that class rather than being out-specified by a later block. */
.btn-pill.btn-filled {
  background: #fff !important;
  color: var(--brand, #14577f) !important;
  border: 0 !important;
}
.btn-pill.btn-filled:hover,
.btn-pill.btn-filled:focus-visible {
  background: #fff !important;
  color: var(--accent-dark, #0d3c5a) !important;
}

/* ==========================================================================
   80. A PILL ON A DARK PANEL IS A FILLED PILL
   The site's default is an outline pill inside a section. On the ink
   panels - "Ready to choose?", the footer bar, the continue-exploring
   strip - that draws the school's blue on the school's ink, which measures
   2.09:1 and reads, at arm's length, as a button with nothing written on
   it.

   The outline rule carries an id-free but five-class selector with
   !important, so the dark-panel case has to say more than it does. It
   does: "a pill on a dark panel", which is a narrower thing than "a pill
   in a section", and the selector says exactly that.
   ========================================================================== */
.cta-panel .btn-pill:not(.btn-gold):not(.btn-hero):not(.nav-cta):not(.btn-quiet),
.site-footer .btn-pill:not(.btn-gold):not(.btn-hero):not(.nav-cta):not(.btn-quiet),
.internal-links-strip .btn-pill:not(.btn-gold):not(.btn-hero):not(.nav-cta):not(.btn-quiet),
.bg-dark .btn-pill:not(.btn-gold):not(.btn-hero):not(.nav-cta):not(.btn-quiet) {
  background: #fff !important;
  color: var(--ink, #0d2233) !important;
  border: 0 !important;
}
.cta-panel .btn-pill:not(.btn-gold):not(.btn-hero):not(.nav-cta):not(.btn-quiet):hover,
.site-footer .btn-pill:not(.btn-gold):not(.btn-hero):not(.nav-cta):not(.btn-quiet):hover,
.internal-links-strip .btn-pill:not(.btn-gold):not(.btn-hero):not(.nav-cta):not(.btn-quiet):hover,
.bg-dark .btn-pill:not(.btn-gold):not(.btn-hero):not(.nav-cta):not(.btn-quiet):hover {
  background: var(--brand-soft, #e7ecef) !important;
  color: var(--accent-dark, #0d3c5a) !important;
}

/* The second button in a row on a dark panel stays an outline, so the two
   are not the same weight - but it is a WHITE outline on the ink, not the
   blue one. */
.cta-panel .button-row .btn-pill:nth-child(n+2):not(.btn-gold):not(.btn-hero),
.bg-dark .button-row .btn-pill:nth-child(n+2):not(.btn-gold):not(.btn-hero) {
  background: transparent !important;
  color: #fff !important;
  border: 1px solid rgba(255, 255, 255, .42) !important;
}
.cta-panel .button-row .btn-pill:nth-child(n+2):not(.btn-gold):not(.btn-hero):hover,
.bg-dark .button-row .btn-pill:nth-child(n+2):not(.btn-gold):not(.btn-hero):hover {
  background: rgba(255, 255, 255, .12) !important;
  color: #fff !important;
  border-color: #fff !important;
}

/* The pane on a picture panel carries white type over whatever photograph
   the school puts behind it, and some of those are bright. A little more
   ink in the glass costs nothing and takes the worst case off the table. */
.pp-body {
  -webkit-backdrop-filter: blur(15px) saturate(.9) brightness(.52);
  backdrop-filter: blur(15px) saturate(.9) brightness(.52);
  background: rgba(13, 34, 51, .34);
}

/* ==========================================================================
   81. ONE PHOTO CARD, EVERYWHERE
   "You have that glass like down with the text and yet it doesn't really
   immerse with the whole picture card. The idea is that maybe the downer
   section is really just simply blurred for the writing to be clear but it
   blends into the picture... keep the description simple, minimal, and then
   you make the cards beautiful."
   "I want this gallery to be designed exactly like the five cards we have
   above... when you hover over a card it comes in front... I prefer the one
   that zooms and comes in front and then the others can just blur a bit
   behind, not that they go white and black."

   So there is now one photo card on this website. The photograph is the
   card. The words sit at the foot of it on a blur that FADES OUT UPWARD -
   a mask on the backdrop-filter itself, so there is no edge, no floating
   slab, no second rectangle sitting on the picture. Where it meets the
   photograph you cannot say where the glass ends.

   The same card is the album card in the campus gallery and the section
   card on a school page. One rule set, one hover, one set of arrows.
   ========================================================================== */

/* --- the caption: a blur with no edge ---------------------------------- */
.pp-body {
  position: relative;
  z-index: 2;
  margin: auto 0 0 !important;
  padding: 58px 20px 18px !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: none !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
  color: #fff;
  isolation: isolate;
}
/* the blur, masked so it dissolves into the photograph */
.pp-body::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  -webkit-backdrop-filter: blur(13px) saturate(.94);
  backdrop-filter: blur(13px) saturate(.94);
  -webkit-mask-image: linear-gradient(to top, #000 0%, #000 44%, rgba(0, 0, 0, .58) 72%, rgba(0, 0, 0, 0) 100%);
  mask-image: linear-gradient(to top, #000 0%, #000 44%, rgba(0, 0, 0, .58) 72%, rgba(0, 0, 0, 0) 100%);
}
/* the ink, so white type is legible over a bright photograph */
.pp-body::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(0deg,
    rgba(6, 24, 42, .88) 0%,
    rgba(6, 24, 42, .74) 30%,
    rgba(6, 24, 42, .42) 62%,
    rgba(6, 24, 42, 0) 100%);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .pp-body::after {
    background: linear-gradient(0deg,
      rgba(6, 24, 42, .94) 0%,
      rgba(6, 24, 42, .82) 34%,
      rgba(6, 24, 42, .48) 66%,
      rgba(6, 24, 42, 0) 100%);
  }
}
.pp-body > h3,
.pp-body > h4 {
  margin: 0 0 4px !important;
  padding: 0 !important;
  font-family: var(--font-display);
  font-size: clamp(17px, 1.35vw, 20px);
  line-height: 1.14;
  letter-spacing: .005em;
  color: #fff !important;
  text-shadow: 0 1px 14px rgba(6, 24, 42, .45);
}
.pp-body > p {
  margin: 0 !important;
  padding: 0 !important;
  font-size: 13.5px;
  line-height: 1.48;
  color: rgba(255, 255, 255, .86) !important;
}
.pp-body .gallery-open-btn,
.pp-body .gallery-open-link,
.pp-body .btn-link-inline {
  margin: 10px 0 0 !important;
  padding: 0 !important;
}

/* --- the arrows: quiet, on the picture, clear of the words ------------- */
/* "The button is slightly above this card and the card is dark, the button
   is a bit bright." It now sits in the middle of the PICTURE rather than
   the middle of the card, and it is smoked glass rather than a white ring. */
.gc-nav {
  top: 40% !important;
  width: 32px;
  height: 32px;
  border: 1px solid rgba(255, 255, 255, .22) !important;
  background: rgba(6, 24, 42, .28) !important;
  -webkit-backdrop-filter: blur(8px) saturate(.9);
  backdrop-filter: blur(8px) saturate(.9);
  color: rgba(255, 255, 255, .82) !important;
  font-size: 15px;
  box-shadow: 0 10px 22px -14px rgba(6, 24, 42, .9);
  transition: opacity .2s ease, background .2s ease, border-color .2s ease, color .2s ease;
}
.gc-nav:hover,
.gc-nav:focus-visible {
  background: rgba(6, 24, 42, .58) !important;
  border-color: rgba(255, 255, 255, .48) !important;
  color: #fff !important;
}
.gc-prev { left: 12px; }
.gc-next { right: 12px; }
.gc-count {
  background: rgba(6, 24, 42, .38);
  -webkit-backdrop-filter: blur(7px);
  backdrop-filter: blur(7px);
  border: 1px solid rgba(255, 255, 255, .16);
  font-size: 11px;
  font-weight: 600;
}
.gc-dot { border-color: rgba(255, 255, 255, .7); }

/* --- the picture panel, restated -------------------------------------- */
.picture-panel {
  border: 0;
  box-shadow: 0 24px 50px -32px rgba(6, 24, 42, .62);
}
.picture-panel:hover,
.picture-panel:focus-within {
  border-color: transparent;
  box-shadow: 0 34px 66px -30px rgba(6, 24, 42, .74);
}

/* ==========================================================================
   82. THE CAMPUS GALLERY GRID IS THE SAME CARD
   "Some cards are big, some cards are smaller... those five cards above are
   exactly how I wanted the other cards to be."
   The lead album and the one-in-seven wide album are retired: every album
   is the same card, the same size, and the row reads as one family.
   ========================================================================== */
#galleryGrid.masonry,
.gallery-grid.masonry {
  gap: 24px;
  /* the focused card grows past its cell; without room it is clipped by the
     section's own overflow on a narrow window */
  padding: 6px 0 10px;
}
.masonry .gallery-card {
  aspect-ratio: 4 / 3.15;
  min-height: 232px;
  border: 0 !important;
  border-radius: 16px;
  background: #dfe6ec !important;
  box-shadow: 0 24px 50px -32px rgba(6, 24, 42, .62);
}
/* the lead and the wide album: retired (section 53 built them) */
.gallery-card.gc-lead,
.gallery-card.gc-wide {
  grid-column: auto !important;
  grid-row: auto !important;
  min-height: 232px;
}
.gallery-card.gc-lead::after { content: none !important; }
.gallery-card.gc-lead > h3 {
  margin: 0 0 4px !important;
  padding: 0 !important;
  font-size: clamp(17px, 1.35vw, 20px) !important;
}
.gallery-card.gc-lead > p { margin: 0 !important; padding: 0 !important; }
.gallery-card.gc-lead .gallery-open-btn,
.gallery-card.gc-lead .gallery-open-link { margin: 10px 0 0 !important; padding: 0 !important; }

/* In the grid the description and the invitation arrive on hover; the name
   is always there, so the page can still be read at a glance. */
.masonry .pp-body { padding-top: 44px !important; }
.masonry .pp-body > p,
.masonry .pp-body .gallery-open-btn,
.masonry .pp-body .gallery-open-link {
  opacity: 0;
  max-height: 0;
  margin-top: 0 !important;
  overflow: hidden;
  transform: translate3d(0, 7px, 0);
  transition:
    opacity .26s ease,
    max-height .38s cubic-bezier(.22, 1, .32, 1),
    margin-top .38s cubic-bezier(.22, 1, .32, 1),
    transform .34s cubic-bezier(.22, 1, .32, 1);
}
.masonry .gallery-card:hover .pp-body > p,
.masonry .gallery-card:focus-within .pp-body > p {
  opacity: 1;
  max-height: 5.2em;
  margin-top: 5px !important;
  transform: none;
}
.masonry .gallery-card:hover .pp-body .gallery-open-btn,
.masonry .gallery-card:focus-within .pp-body .gallery-open-btn,
.masonry .gallery-card:hover .pp-body .gallery-open-link,
.masonry .gallery-card:focus-within .pp-body .gallery-open-link {
  opacity: 1;
  max-height: 2.4em;
  margin-top: 9px !important;
  transform: none;
}
/* the drift belongs on a section card, not on twenty-two of them at once */
.masonry .pp-stage .gc-shot.is-on { animation: none; transform: none; }

/* --- the focus: one card forward, the rest softly behind ---------------- */
/* "I prefer the one that zooms and comes in front and then the others can
   just blur a bit behind, not that they go white and black - white and
   black is not the best for UI UX purpose." */
.masonry.has-focus .gallery-card {
  filter: blur(2.6px) !important;
  opacity: .92 !important;
  transform: scale(.972) !important;
}
.masonry.has-focus .gallery-card.is-focus,
.masonry.has-focus .gallery-card.gc-lead.is-focus,
.masonry.has-focus .gallery-card.gc-wide.is-focus {
  filter: none !important;
  opacity: 1 !important;
  transform: scale(1.062) translateY(-6px) !important;
  z-index: 6;
  box-shadow: 0 46px 84px -34px rgba(6, 24, 42, .72) !important;
  border-color: transparent !important;
}
@media (hover: none) {
  .masonry.has-focus .gallery-card {
    filter: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .masonry.has-focus .gallery-card.is-focus { transform: none !important; }
  /* A finger has no hover, so the card shows everything it has. */
  .masonry .pp-body > p {
    opacity: 1; max-height: 5.2em; margin-top: 5px !important; transform: none;
  }
  .masonry .pp-body .gallery-open-btn,
  .masonry .pp-body .gallery-open-link {
    opacity: 1; max-height: 2.4em; margin-top: 9px !important; transform: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .masonry.has-focus .gallery-card,
  .masonry.has-focus .gallery-card.is-focus { filter: none !important; transform: none !important; }
}

/* --- the filter row is not the grid ------------------------------------ */
/* "They are just too close to the next card that comes. They actually touch
   the next card. Give some space before the next card starts following." */
.filter-bar {
  margin: 26px 0 0 !important;
  padding-bottom: 4px;
}
.filter-bar + .masonry,
.filter-bar + .gallery-grid,
.filter-bar + * { margin-top: 34px; }

@media (max-width: 991px) {
  .masonry .gallery-card { aspect-ratio: 4 / 3.3; }
}
@media (max-width: 640px) {
  #galleryGrid.masonry, .gallery-grid.masonry { gap: 18px; }
  /* On a phone the card shows its whole caption with no hover to open it, so
     it is given a floor and left to grow rather than being held to a ratio
     that would clip the last line. */
  .masonry .gallery-card { aspect-ratio: auto; min-height: 320px; }
  .pp-body { padding: 48px 16px 15px !important; }
  .filter-bar + * { margin-top: 26px; }
}

/* ==========================================================================
   83. THE SAME CARD AT THE FOOT OF A BLOG POST
   "Apply the gallery card design to every image card on the platform."
   A related post is a photograph with a name on it, like everything else.
   ========================================================================== */
.photo-card {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  aspect-ratio: 4 / 3.15;
  min-height: 232px;
  padding: 0 !important;
  margin: 0 !important;
  overflow: hidden;
  border: 0 !important;
  border-radius: 16px;
  background: #dfe6ec !important;
  box-shadow: 0 24px 50px -32px rgba(6, 24, 42, .62);
  transition: transform .38s cubic-bezier(.22, 1, .32, 1), box-shadow .38s ease;
}
.photo-card:hover,
.photo-card:focus-within {
  transform: translateY(-6px) scale(1.02);
  box-shadow: 0 40px 74px -32px rgba(6, 24, 42, .7);
}
.photo-card .pp-body { padding-top: 46px !important; }
.photo-card .pp-body > .small-copy,
.photo-card .pp-body > div.small-copy {
  margin: 0 0 6px !important;
  padding: 0 !important;
  font-size: 11.5px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .72) !important;
}
.photo-card .pp-body > h3 {
  margin: 0 0 4px !important;
  padding: 0 !important;
  font-family: var(--font-display);
  font-size: clamp(17px, 1.35vw, 20px);
  line-height: 1.16;
  color: #fff !important;
}
.photo-card .pp-body > p {
  margin: 0 !important;
  padding: 0 !important;
  font-size: 13.5px;
  line-height: 1.48;
  color: rgba(255, 255, 255, .86) !important;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* the invitation is a line of type on the photograph, not a pill */
.photo-card .pp-body > .btn-pill,
.photo-card .pp-body > a.btn-pill,
.photo-card .pp-body > a.btn-pill:link,
.photo-card .pp-body > a.btn-pill:visited,
.section .photo-card .pp-body > a.btn-pill,
.section .photo-card .pp-body > a.btn-pill:not(.btn-gold):not(.btn-hero):not(.nav-cta) {
  display: inline-block;
  margin: 9px 0 0 !important;
  padding: 0 !important;
  background: none !important;
  border: 0 !important;
  color: #fff !important;
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: rgba(255, 255, 255, .45);
  min-width: 0 !important;
  box-shadow: none !important;
}
.photo-card:hover .pp-body > a.btn-pill { text-decoration-color: #fff; }
/* the excerpt and the invitation arrive on hover, as in the gallery */
.photo-card .pp-body > p,
.photo-card .pp-body > .btn-pill {
  opacity: 0;
  max-height: 0;
  margin-top: 0 !important;
  overflow: hidden;
  transform: translate3d(0, 7px, 0);
  transition:
    opacity .26s ease,
    max-height .38s cubic-bezier(.22, 1, .32, 1),
    margin-top .38s cubic-bezier(.22, 1, .32, 1),
    transform .34s cubic-bezier(.22, 1, .32, 1);
}
.photo-card:hover .pp-body > p,
.photo-card:focus-within .pp-body > p { opacity: 1; max-height: 3.4em; margin-top: 5px !important; transform: none; }
.photo-card:hover .pp-body > .btn-pill,
.photo-card:focus-within .pp-body > .btn-pill { opacity: 1; max-height: 2.4em; margin-top: 9px !important; transform: none; }
/* the old body/toggle machinery has no place on a photograph */
.photo-card .news-body,
.photo-card .news-toggle { display: none !important; }

#relatedPosts,
.news-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 22px;
  align-items: start;
}
@media (hover: none) {
  .photo-card .pp-body > p,
  .photo-card .pp-body > .btn-pill { opacity: 1; max-height: 3.4em; margin-top: 6px !important; transform: none; }
}
@media (max-width: 991px) {
  #relatedPosts, .news-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  #relatedPosts, .news-grid { grid-template-columns: 1fr; gap: 18px; }
  .photo-card { aspect-ratio: auto; min-height: 300px; }
}

/* ==========================================================================
   84. LESS GLASS
   "The blur is a bit too much - if you can make the glass effect slightly
   visible than now, please do."
   "For the school cards with that glass effect it is not the best; try and
   just use a shade effect instead."

   Two decisions, and they are different decisions:

   - On a SCHOOL PAGE card the glass goes altogether. What carries the words
     there is a shade - one gradient, nothing filtered, nothing to look
     through. The photograph stays a photograph all the way down.
   - Everywhere the glass stays (the campus gallery, the cards at the foot of
     a blog post) it is halved: 6px rather than 13px, and the mask lets go of
     the picture sooner, so it reads as a breath on the glass rather than a
     frosted panel.
   ========================================================================== */

/* --- the school pages: a shade, not glass ------------------------------ */
.picture-panel:not(.gallery-card):not(.photo-card) > .pp-body::before {
  content: none;
}
.picture-panel:not(.gallery-card):not(.photo-card) > .pp-body::after {
  background: linear-gradient(0deg,
    rgba(6, 24, 42, .92) 0%,
    rgba(6, 24, 42, .80) 26%,
    rgba(6, 24, 42, .52) 56%,
    rgba(6, 24, 42, .18) 82%,
    rgba(6, 24, 42, 0) 100%);
}

/* --- where the glass stays, it stays quiet ----------------------------- */
.masonry .pp-body::before,
.photo-card .pp-body::before {
  -webkit-backdrop-filter: blur(6px) saturate(.96);
  backdrop-filter: blur(6px) saturate(.96);
  -webkit-mask-image: linear-gradient(to top, #000 0%, #000 34%, rgba(0, 0, 0, .42) 66%, rgba(0, 0, 0, 0) 94%);
  mask-image: linear-gradient(to top, #000 0%, #000 34%, rgba(0, 0, 0, .42) 66%, rgba(0, 0, 0, 0) 94%);
}
.masonry .pp-body::after,
.photo-card .pp-body::after {
  background: linear-gradient(0deg,
    rgba(6, 24, 42, .86) 0%,
    rgba(6, 24, 42, .70) 32%,
    rgba(6, 24, 42, .36) 66%,
    rgba(6, 24, 42, 0) 100%);
}

/* With no glass under them the words rest straight on the photograph, and
   a photograph has bright patches. A soft shadow holds the line over any of
   them and costs nothing - far better than making the shade heavier, which
   is what was wrong with the panel in the first place. */
.picture-panel:not(.gallery-card):not(.photo-card) > .pp-body > h3,
.picture-panel:not(.gallery-card):not(.photo-card) > .pp-body > h4 {
  text-shadow: 0 1px 2px rgba(6, 24, 42, .55), 0 2px 18px rgba(6, 24, 42, .5);
}
.picture-panel:not(.gallery-card):not(.photo-card) > .pp-body > p,
.picture-panel:not(.gallery-card):not(.photo-card) > .pp-body ul,
.picture-panel:not(.gallery-card):not(.photo-card) > .pp-body li,
.picture-panel:not(.gallery-card):not(.photo-card) > .pp-body .gallery-open-btn,
.picture-panel:not(.gallery-card):not(.photo-card) > .pp-body .gallery-open-link {
  text-shadow: 0 1px 2px rgba(6, 24, 42, .5), 0 2px 14px rgba(6, 24, 42, .45);
}

/* ==========================================================================
   85. THE FOOTER HEADINGS KEEP THEIR LOOK AFTER MOVING UP A LEVEL
   Every page's footer used <h4> for the school's name and <h5> for the three
   column labels, which jumped two levels down from the page's last <h2> and
   made the document outline wrong on all 85 pages. The tags are now <h3> and
   <h4>; these two rules hold the appearance exactly where it was, measured
   from the browser before the change and matched value for value.
   ========================================================================== */
.site-footer .ft-brand {
  font-family: var(--font-display) !important;
  font-size: 18px !important;
  font-weight: 600 !important;
  line-height: 1.1 !important;
  letter-spacing: -.015em !important;
  text-transform: none !important;
  margin: 0 0 10px !important;
  color: #fff !important;
}
.site-footer .ft-col {
  font-family: var(--font-body) !important;
  font-size: 13px !important;
  font-weight: 500 !important;
  line-height: 1.1 !important;
  letter-spacing: .08em !important;
  text-transform: uppercase !important;
  margin: 0 0 16px !important;
  color: #fff !important;
}

/* The "Continue exploring" strip is a section of the page, not a sub-heading
   of one, and on the policy and portal pages it followed the <h1> directly.
   It is an <h2> now; this holds the look exactly where it was. */
.internal-links-strip .strip-h {
  font-family: var(--font-display) !important;
  font-size: 24px !important;
  font-weight: 600 !important;
  line-height: 1.1 !important;
  letter-spacing: -.015em !important;
  text-transform: none !important;
  margin: 0 0 6px !important;
  color: #fff !important;
}

/* ==========================================================================
   86. A PORTRAIT VIDEO IS NOT A WIDE ONE
   "One of the videos is in portrait, one is in landscape - take account of
   that." The card was a wide strip, which is right for a landscape film and
   cuts the head off a portrait one. Each now gets the shape it was filmed
   in, and rsc-ui.js measures any video it has not been told about, so a film
   dropped in later lands correctly with nobody editing this file.
   ========================================================================== */
.tm-grid .tm-video-portrait,
.tm-video-portrait {
  max-width: 300px;
  padding-bottom: 0;
  height: auto;
  aspect-ratio: 9 / 16;
  min-height: 0;
  border-radius: 18px;
  background-position: center 22%;
  margin-left: auto;
  margin-right: auto;
}
.tm-grid .tm-video-landscape,
.tm-video-landscape {
  padding-bottom: 0;
  height: auto;
  aspect-ratio: 16 / 9;
  min-height: 0;
  border-radius: 16px;
  max-width: 560px;
}
/* The play button sits dead centre of whichever shape the card turned out
   to be, rather than in the middle of a strip that is no longer there. */
.tm-video-portrait .tm-play,
.tm-video-landscape .tm-play {
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
@media (max-width: 640px) {
  .tm-video-portrait { max-width: 232px; }
  .tm-video-landscape { max-width: none; }
}

/* The testimonials page grid: the same two shapes, inside a card. */
/* The card is a column flex container, so `margin: auto` on this one takes
   it out of the stretch and it is sized to its content instead - and its
   content is a background image, which is no content at all. It measured
   0 x 0. An explicit width is what makes `max-width` and `aspect-ratio`
   mean anything here. */
.testimonial-card-video .testimonial-video-thumb.is-portrait {
  aspect-ratio: 9 / 16;
  padding-bottom: 0;
  height: auto;
  width: 100%;
  max-width: 250px;
  margin-left: auto;
  margin-right: auto;
  background-position: center 22%;
}
.testimonial-card-video .testimonial-video-thumb.is-landscape {
  aspect-ratio: 16 / 9;
  padding-bottom: 0;
  height: auto;
  width: 100%;
}

/* =====================================================================
   87. A FILM IN A PORTRAIT CARD FILLS THE PORTRAIT CARD

   `.rsc-inline-video` carries `aspect-ratio: 16 / 10`, which is right for
   every film on the site except the two that are not wide. In a portrait
   card the card is 9:16 and the film was still drawn 16:10, so a 250px
   card reserved 444px of height and put a 156px film at the top of it,
   with 288px of nothing underneath.

   Where the card has already been given a shape - by `data-orient` in the
   markup or by the probe in rsc-ui.js - the film takes the card's shape
   instead of its own.
   ===================================================================== */
.testimonial-video-thumb.is-portrait .rsc-inline-video,
.testimonial-video-thumb.is-landscape .rsc-inline-video,
.tm-video.tm-video-portrait.has-inline-video .rsc-inline-video,
.tm-video.tm-video-landscape.has-inline-video .rsc-inline-video {
  aspect-ratio: auto;
  height: 100%;
  width: 100%;
}

/* Nothing is cropped off the top of a portrait film: it already is the
   shape of its box, so the 28% object-position that flatters a wide
   campus shot would only push a face out of frame. */
.testimonial-video-thumb.is-portrait .rsc-inline-video,
.tm-video.tm-video-portrait.has-inline-video .rsc-inline-video {
  object-position: center center;
}

/* =====================================================================
   88. THE HERO IS THE WHOLE FIRST SCREEN

   The pale band between the photograph and the first section was not a
   margin and not a gap. It was the top of the next section, showing in
   the ~118px the hero had been told to leave empty.

   Three rules were doing it, all written for a page this no longer is:

     hero.css       height: calc(100vh - 108px)  +  margin-top: 108px
     nav-hotfix.css max-height: calc(100vh - 118px) !important   (>=992)
     nav-hotfix.css max-height: calc(100vh - 114px) !important   (<=991)

   The nav-hotfix comment names the arithmetic: "utility-bar (38px) +
   sticky nav (~76px)". There is no utility bar on the page any more, and
   `.site-nav` is `position: fixed` with the body carrying `nav-over-hero`
   - it floats ON the hero and takes no space at all. So every one of those
   subtractions bought nothing and cost a hundred-odd pixels of hero.

   The hero is the first screen. All of it.

   `lvh` rather than `vh` or `svh` deliberately: on a phone the large
   viewport is the tallest the visible area ever gets, so the hero is never
   shorter than what is on screen and the band cannot come back when the
   address bar retracts. The cost is a few pixels of hero behind the
   address bar on first paint, which is the right way round.

   The `!important` here is not a preference. It is the only thing that
   answers an `!important` already in the cascade; this file loads last, so
   equal specificity plus equal weight resolves here.
   ===================================================================== */
header.hero {
  height: 100vh;                 /* every browser */
  height: 100lvh;                /* and the correct one where it is known */
  max-height: none !important;   /* answers nav-hotfix.css */
  margin-top: 0 !important;
  margin-bottom: 0 !important;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}

/* The carousel, the track and every slide fill the header exactly - no
   viewport arithmetic of their own, or they disagree with it again. */
header.hero .carousel,
header.hero .carousel-inner,
header.hero .carousel-inner .item,
header.hero .hero-slide {
  height: 100% !important;
  min-height: 0 !important;
  max-height: none !important;
}

@media (max-width: 991px) {
  header.hero {
    height: 100vh;
    height: 100lvh;
    max-height: none !important;
  }
}

/* =====================================================================
   90. THE SAME LIFT ON EVERY PICTURE CARD, NOT JUST TWO CONTAINERS

   The hover behaviour in section 76 - the row steps back, the card under
   the pointer comes forward with a deep shadow - was written against two
   selectors: `.cards-grid .campus-card` and `.campus-tiles .campus-tile`.

   The home page uses the first and the primary-school page the second, so
   both of those glow. **The RIC and RAIBICOL pages use neither.** Their
   picture cards sit in `.school-band` and `.stats-three`, which nothing in
   that section names, so nine cards on one page and twelve on the other
   sat flat while the same card on the home page lifted.

   Nothing about those two pages is different. The selector list was just
   short. Section 28 says the site has one photo card; this is the
   behaviour that goes with it.
   ===================================================================== */
.school-band > .picture-panel,
.stats-three > .picture-panel {
  position: relative;
  z-index: 1;
  transform-origin: center;
  transition:
    transform .42s cubic-bezier(.2, .9, .25, 1.06),
    box-shadow .42s ease,
    filter .42s ease,
    opacity .42s ease;
  will-change: transform;
}

/* The rest of the row steps back while one of them is being looked at. */
.school-band:hover > .picture-panel,
.school-band:focus-within > .picture-panel,
.stats-three:hover > .picture-panel,
.stats-three:focus-within > .picture-panel {
  transform: scale(.955);
  filter: saturate(.72) brightness(.965);
  opacity: .84;
}

/* And the one being looked at comes forward over them.

   A shade less than the home page's 1.085: these bands run three, four
   and even nine cards wide, and at that count the full lift has the row
   jumping rather than breathing. */
.school-band > .picture-panel:hover,
.school-band > .picture-panel:focus-within,
.stats-three > .picture-panel:hover,
.stats-three > .picture-panel:focus-within {
  transform: scale(1.055);
  filter: none;
  opacity: 1;
  z-index: 6;
  box-shadow: 0 38px 74px -32px rgba(13, 34, 51, .58);
}

/* The cards at each end lean inward rather than off the edge of the page. */
.school-band > .picture-panel:first-child:hover,
.stats-three > .picture-panel:first-child:hover { transform: scale(1.055) translateX(1.8%); }
.school-band > .picture-panel:last-child:hover,
.stats-three > .picture-panel:last-child:hover { transform: scale(1.055) translateX(-1.8%); }

/* A finger has no hover, and a card that grows under a thumb is a card
   that has moved before the tap lands. */
@media (hover: none) {
  .school-band:hover > .picture-panel,
  .stats-three:hover > .picture-panel,
  .school-band > .picture-panel:hover,
  .stats-three > .picture-panel:hover {
    transform: none;
    filter: none;
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .school-band > .picture-panel,
  .stats-three > .picture-panel { transition: none; will-change: auto; }
  .school-band:hover > .picture-panel,
  .stats-three:hover > .picture-panel { transform: none; filter: none; opacity: 1; }
  .school-band > .picture-panel:hover,
  .stats-three > .picture-panel:hover { transform: none; box-shadow: var(--e3); }
}
