
:root{
  --red:#c8102e; --red-dark:#9d0c24; --ink:#1c1c1c; --ink-2:#4a4a4a; --ink-3:#6b6a65;
  --line:#e3e0d9; --cream:#faf8f4; --sand:#f3efe7; --white:#fff;
  --max:1180px; --radius:10px;
  --shadow:0 1px 3px rgba(0,0,0,.06), 0 8px 24px rgba(0,0,0,.05);
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
html,body{max-width:100%;overflow-x:hidden}
body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  color:var(--ink);background:var(--white);font-size:16.5px;line-height:1.62;-webkit-font-smoothing:antialiased}
img{max-width:100%;height:auto;display:block}
/* Links carry an underline so they are distinguishable without colour.
   Navigation, buttons and card links are excluded: they have their own
   non-colour affordances (position, background, chevron). */
a{color:var(--red);text-decoration:underline;text-underline-offset:2px;
  text-decoration-thickness:1px}
a:hover{text-decoration-thickness:2px}
nav.main a,.brand,.brand:hover,a.btn,a.btn:hover,.card .more,.crumb a{text-decoration:none}
nav.main a:hover,.card .more:hover,.crumb a:hover{text-decoration:underline}
/* Contact links in the utility bar and footer sit inside plain text, so they
   keep their underline: colour alone would not distinguish them. */
.util a,footer.site a{text-decoration:underline;text-underline-offset:2px}
.wrap{max-width:var(--max);margin:0 auto;padding:0 22px}
.narrow{max-width:820px}

/* ---------- utility bar ---------- */
.util{background:var(--ink);color:#dcdcdc;font-size:13px}
.util .wrap{display:flex;flex-wrap:wrap;gap:6px 22px;justify-content:space-between;padding-top:8px;padding-bottom:8px}
.util a{color:#fff}
.util span{white-space:nowrap}
@media(max-width:520px){.util span{white-space:normal}
  .util .wrap{justify-content:flex-start;gap:2px 14px}}

/* ---------- header ----------
   Black, to match the footer. Every colour pair below was checked against
   #141414: nav 12.2:1, active state 15.9:1, toggle 12.2:1. */
header.site{position:sticky;top:0;z-index:60;background:rgba(20,20,20,.97);
  backdrop-filter:saturate(180%) blur(8px);border-top:1px solid #313131;border-bottom:1px solid #313131}
header.site .wrap{display:flex;align-items:center;justify-content:space-between;gap:18px;padding-top:12px;padding-bottom:12px}
.brand{display:flex;align-items:center;gap:12px;flex:none}
.brand img{height:54px;width:auto}
.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
nav.main ul{list-style:none;margin:0;padding:0}
nav.main > ul{display:flex;gap:2px;flex-wrap:wrap;align-items:center}
nav.main a{display:flex;align-items:center;gap:6px;color:#d8d8d8;font-size:14.5px;
  font-weight:520;padding:9px 12px;border-radius:6px}
nav.main a:hover{background:rgba(255,255,255,.13);color:#fff;text-decoration:none}
/* The section containing the current page is marked by weight and a red rule as
   well as colour, so it does not depend on colour alone. */
nav.main a.on{color:#fff;font-weight:680;box-shadow:inset 0 -2px 0 var(--red)}
nav.main .chev{opacity:.75;flex:none}

/* ---------- submenus ----------
   visibility (not display) so that the links inside become focusable exactly
   when the panel is revealed, which lets :focus-within do the keyboard work
   without a line of JavaScript. */
.has-sub{position:relative}
/* Right-aligned to the parent, not left. The nav itself sits against the right
   of a padded container, so opening leftward is the only alignment that cannot
   run off-screen at narrow desktop widths — left alignment put the last panel
   1px past the viewport, silently clipped by overflow-x:hidden. */
.sub{position:absolute;top:100%;right:0;left:auto;min-width:232px;padding:6px;
  background:#141414;border:1px solid #313131;border-radius:10px;
  box-shadow:0 12px 32px rgba(0,0,0,.4);
  visibility:hidden;opacity:0;transform:translateY(-4px);
  transition:opacity .14s ease, transform .14s ease, visibility .14s}
.has-sub:hover > .sub,.has-sub:focus-within > .sub{visibility:visible;opacity:1;transform:none}
.sub a{padding:9px 12px;border-radius:6px;font-weight:520;white-space:nowrap}
/* Second-level items sit under "Courses" as an indent rather than a nested
   flyout, which is fiddly with a pointer and unusable on touch. */
.sub li.sub2 a{padding-left:26px;font-size:14px;color:#bdbdbd}
.sub li.sub2 a:hover{color:#fff}
.sub li.sub2 + li:not(.sub2){margin-top:6px;border-top:1px solid #313131;padding-top:6px}
.sub a[aria-current]{color:#fff;font-weight:680;box-shadow:inset 3px 0 0 var(--red)}
nav.main a:focus-visible{outline:3px solid #fff;outline-offset:-3px}

.navtog{display:none;background:none;border:1px solid #4a4a4a;border-radius:6px;
  padding:8px 12px;font:inherit;font-size:14px;cursor:pointer;color:#d8d8d8}
.navtog:hover{background:rgba(255,255,255,.13);color:#fff}

@media(max-width:960px){
  nav.main{display:none;width:100%;padding-bottom:10px}
  nav.main.open{display:block}
  nav.main > ul{flex-direction:column;align-items:stretch;gap:0}
  nav.main a{padding:12px;border-bottom:1px solid #313131;border-radius:0}
  nav.main a.on{box-shadow:inset 3px 0 0 var(--red)}
  nav.main .chev{display:none}
  /* No hover on touch, so the whole tree is simply shown, children indented. */
  .sub{position:static;visibility:visible;opacity:1;transform:none;min-width:0;
    padding:0;background:none;border:0;border-radius:0;box-shadow:none;transition:none}
  /* Needs to out-specify `nav.main a` above, or the indent is silently lost and
     children read as siblings of their parent. */
  nav.main > ul > li > a{font-weight:660}
  nav.main .sub a{padding-left:32px;font-size:14px;color:#b9b9b9;white-space:normal}
  nav.main .sub a[aria-current]{color:#fff}
  .navtog{display:block}
  header.site .wrap{flex-wrap:wrap}
}
@media(prefers-reduced-motion:reduce){.sub{transition:none}}

/* ---------- WhatsApp launcher ----------
   Fixed, above the sticky header (z-index 60). The dark ring is deliberate:
   WhatsApp green against a white page is only 2:1, which would fail WCAG 1.4.11
   for a graphical control, so the ring supplies the boundary contrast while the
   recognisable brand colour is kept. */
.wa{position:fixed;z-index:90;display:flex;align-items:center;gap:0;
  right:calc(18px + env(safe-area-inset-right));
  bottom:calc(18px + env(safe-area-inset-bottom));
  height:56px;padding:0 13px;border-radius:28px;
  background:#25D366;color:#fff;text-decoration:none;
  box-shadow:0 3px 8px rgba(0,0,0,.18), 0 10px 28px rgba(0,0,0,.16);
  box-sizing:border-box;
  transition:transform .18s ease, box-shadow .18s ease, gap .18s ease}
.wa::after{content:"";position:absolute;inset:0;border-radius:inherit;
  border:1px solid rgba(0,0,0,.28);pointer-events:none}
.wa svg{flex:none}
/* The label is collapsed rather than absent, so it can widen on hover without
   ever adding to document width — a fixed element that grows would still push
   nothing, but the collapsed max-width keeps the 320px overflow test honest. */
.wa-label{max-width:0;overflow:hidden;white-space:nowrap;font-weight:640;
  font-size:15px;line-height:1;transition:max-width .18s ease}
@media(hover:hover) and (pointer:fine){
  .wa:hover,.wa:focus-visible{gap:9px;transform:translateY(-2px);
    box-shadow:0 4px 10px rgba(0,0,0,.2), 0 14px 34px rgba(0,0,0,.2)}
  .wa:hover .wa-label,.wa:focus-visible .wa-label{max-width:150px}
}
.wa:focus-visible{outline:3px solid var(--ink);outline-offset:3px}
@media(prefers-reduced-motion:reduce){.wa,.wa-label{transition:none}
  .wa:hover,.wa:focus-visible{transform:none}}
@media print{.wa{display:none}}

/* ---------- hero ---------- */
.hero{position:relative;background:var(--sand);overflow:hidden}
.hero .wrap{display:grid;grid-template-columns:1.15fr .85fr;gap:44px;align-items:center;
  padding-top:56px;padding-bottom:56px}
.hero.solo .wrap{grid-template-columns:1fr}
.hero.solo h1,.hero.solo p.lede{max-width:24ch}
.hero.solo p.lede{max-width:70ch}
.hero h1{font-size:clamp(28px,4.2vw,44px);line-height:1.12;margin:0 0 14px;letter-spacing:-.02em;font-weight:720}
.hero p.lede{font-size:18px;color:var(--ink-2);margin:0 0 22px;max-width:62ch}
.hero img{border-radius:var(--radius);box-shadow:var(--shadow)}
.eyebrow{display:inline-block;font-size:12px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--red);margin-bottom:12px}
@media(max-width:860px){.hero .wrap{grid-template-columns:1fr;gap:26px;padding-top:36px;padding-bottom:36px}}

/* ---------- buttons ---------- */
.btn{display:inline-block;background:var(--red);color:#fff;padding:13px 26px;border-radius:6px;
  font-weight:640;font-size:15.5px;border:1px solid var(--red)}
.btn:hover{background:var(--red-dark);border-color:var(--red-dark);text-decoration:none;color:#fff}
.btn.ghost{background:transparent;color:var(--ink);border-color:var(--ink)}
.btn.ghost:hover{background:var(--ink);color:#fff}
.btnrow{display:flex;gap:12px;flex-wrap:wrap;margin:22px 0}
/* The hero column is about 600px on a desktop container, and three buttons at
   the standard 26px side padding come to roughly 690px, so the third dropped to
   its own line. Tightened here only: elsewhere buttons keep their full size. */
/* A second row of calls to action that belongs to the first: normal .btnrow
   margins would open a gap that reads as a separate section. */
.btnrow.next{margin-top:-10px}
.hero .btnrow{gap:10px}
.hero .btnrow .btn{padding:13px 20px}
@media(max-width:860px){.hero .btnrow .btn{padding:13px 22px}}
/* ---------- the four course-page calls to action ----------
   Three buttons on the first line, the online application centred beneath the
   middle one. Centring it needs the width of "See fees" and of the button
   above it, and neither is a number we can hardcode - the labels are
   translatable, the font is not guaranteed, and a browser zoom changes both.

   So: a grid. The three place themselves into columns 1-3, the application
   takes column 2 on row 2, and justify-self:center centres it ON that column.
   A grid item wider than its track overflows it symmetrically, which is
   exactly the alignment wanted: the button is far wider than "See fees" but
   shares its centre line. No measurements, and it stays correct if a label
   changes length.

   Only above 1080px, where the three genuinely fit on one line. Narrower than
   that the flex fallback lets them wrap as they always did - a grid would hold
   three columns it cannot afford and push the row off the side of the page. */
@media(min-width:1081px){
  /* 1fr auto 1fr inside an INLINE grid: the container sizes to its content,
     and the two fr tracks equalise to the wider of the two download buttons.
     Once the outer columns are equal, the centre of the whole row IS the
     centre of "See fees" - so the application button can span 1/-1 and simply
     centre itself, which is a thing CSS can do without knowing any widths.
     Placing it in column 2 instead does not work: an item is sized to fit its
     track when it is not stretched, so it would squash to the width of "See
     fees" and wrap into four lines. */
  .cta{display:inline-grid;grid-template-columns:1fr auto 1fr;gap:12px 10px;vertical-align:top}
  .cta .apply{grid-column:1/-1;justify-self:center;width:max-content}
}
@media(max-width:1080px){
  .cta .apply{flex:1 1 100%;text-align:center}
}

/* ---------- apply menu ----------
   The five application forms, hung off one button. Same mechanism as the header
   submenus: visibility rather than display, so :focus-within can do the
   keyboard and touch work without JavaScript. A <button> is the trigger
   precisely because tapping it gives it focus on a touch screen, where there is
   no hover to open the panel with. */
.applymenu{position:relative;display:inline-block}
.applymenu > button{cursor:pointer;font-family:inherit;line-height:normal;
  display:inline-flex;align-items:center;gap:9px}
.applymenu > button .chev{opacity:.85;flex:none;transition:transform .14s ease}
.applymenu:hover > button .chev,.applymenu:focus-within > button .chev{transform:rotate(180deg)}
/* width:max-content so the longest item sets the width, capped at whatever room
   is left to the right of the button. Wrapping "Apply for Distance Learning"
   over two lines made the panel read as a paragraph rather than a list. */
.applymenu > ul{position:absolute;top:calc(100% + 6px);left:0;z-index:40;
  list-style:none;margin:0;padding:6px;min-width:100%;width:max-content;
  max-width:calc(100vw - 44px);
  background:#fff;border:1px solid var(--line);border-radius:10px;
  box-shadow:0 12px 32px rgba(0,0,0,.18);
  visibility:hidden;opacity:0;transform:translateY(-4px);
  transition:opacity .14s ease, transform .14s ease, visibility .14s}
.applymenu:hover > ul,.applymenu:focus-within > ul{visibility:visible;opacity:1;transform:none}
.applymenu > ul a{display:block;padding:11px 14px;border-radius:6px;white-space:nowrap;
  color:var(--ink);font-weight:560;font-size:15px;text-decoration:none}
.applymenu > ul a:hover{background:var(--sand);color:var(--red-dark);text-decoration:none}
.applymenu > ul a:focus-visible{outline:3px solid var(--red);outline-offset:-3px}
@media (prefers-reduced-motion:reduce){
  .applymenu > ul,.applymenu > button .chev{transition:none}}

/* ---------- sections ---------- */
section.band{padding:58px 0;border-top:1px solid var(--line)}
section.band.tint{background:var(--cream)}
section.band > .wrap > h2:first-child,
section.band > .wrap > .secthead:first-child{margin-top:0}
h2{font-size:clamp(22px,2.7vw,31px);line-height:1.2;margin:0 0 8px;letter-spacing:-.015em;font-weight:700}
h3{font-size:19.5px;margin:30px 0 6px;font-weight:670;line-height:1.3}
h4{font-size:16.5px;margin:22px 0 4px;font-weight:660}
p{margin:0 0 14px;color:var(--ink-2);max-width:78ch}
.secthead p{font-size:17px;max-width:70ch}
main p strong, main li strong{color:var(--ink)}
.answer{font-size:17px;color:var(--ink)}

/* ---------- cards ---------- */
.grid{display:grid;gap:22px}
.grid > *{min-width:0}
.g2{grid-template-columns:repeat(auto-fit,minmax(320px,1fr))}
.g3{grid-template-columns:repeat(auto-fit,minmax(272px,1fr))}
.g4{grid-template-columns:repeat(auto-fit,minmax(210px,1fr))}
/* The whole card is the click target. The stretched pseudo-element on the
   existing link means there is still exactly one link per card - better for
   screen readers and for how crawlers read the page than wrapping everything
   in an anchor or bolting a click handler on. */
.card{background:#fff;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;
  display:flex;flex-direction:column;position:relative;
  transition:border-color .16s ease, box-shadow .16s ease, transform .16s ease}
.card:has(.more){cursor:pointer}
.card:has(.more):hover{border-color:#c9c2b4;box-shadow:var(--shadow);transform:translateY(-2px)}
.card .more::after{content:"";position:absolute;inset:0;border-radius:var(--radius)}
.card:focus-within{outline:3px solid var(--red);outline-offset:3px}
.card .more:focus-visible{outline:none}
@media(prefers-reduced-motion:reduce){.card{transition:none}
  .card:has(.more):hover{transform:none}}
.card img{aspect-ratio:3/2;object-fit:cover;width:100%}
.card .pad{padding:20px 22px 22px;display:flex;flex-direction:column;flex:1}
.card h3{margin:0 0 4px;font-size:19px}
/* Accreditation sits directly under the course name on every card, so the one
   route without it is read in the same place as the four that have it.
   Named .cred, not .accred: that class already belongs to the accreditation
   strip, whose flex/border/background rules would box this line in. */
.card .cred{font-size:13px;font-weight:600;color:var(--ink-3);margin:0 0 10px;
  letter-spacing:.02em}
.card p{font-size:15px;margin-bottom:12px}
.card .price{font-size:23px;font-weight:720;color:var(--ink);letter-spacing:-.01em;margin:0 0 2px}
.card .price small{display:block;font-size:13px;font-weight:400;color:var(--ink-3);letter-spacing:0}
.card .more{margin-top:auto;font-weight:640;font-size:15px}
/* Stands in for .more on a card with nothing to download yet, so the row of
   cards still lines up along the bottom instead of one sitting short. */
.card .na{margin-top:auto;margin-bottom:0;font-size:13.5px;color:var(--ink-3)}

/* A download that is not there yet. It holds the slot so the table and the
   card grid keep their shape, and reads as unavailable rather than as a link
   that failed: dashed outline, muted, not-allowed cursor, no hover state. */
.soon{display:inline-block;font:inherit;font-size:13.5px;font-weight:600;color:var(--ink-3);
  border:1px dashed var(--line);border-radius:6px;padding:4px 10px;cursor:not-allowed;
  background:rgba(0,0,0,.015);white-space:nowrap}
.card .card-soon{margin-top:auto;align-self:flex-start}

/* Booking route cards. The whole card is already clickable via .card:has(.more),
   so .bookbtn only has to look like the action; .where carries the address or
   the words "Zoom"/"Telephone", which is the single fact that stops somebody
   booking a Sandton tour when they meant Gillitts. It is pushed to the bottom
   of the card so that every card in a row lines its address and its button up
   on the same baseline regardless of how long the description ran. */
.bookcard .where{margin:auto 0 12px;padding-top:12px;border-top:1px solid var(--line);
  font-size:13.5px;color:var(--ink-3)}
.bookcard .bookbtn{margin-top:0}
/* In-page campus switcher. Two schools on one fee page means a visitor who
   wants Gillitts should not have to scroll past every Johannesburg table. */
.jump{font-size:14.5px;font-weight:640;margin:0 0 18px}
.jump a{margin-right:4px}
/* ---------- photographs ----------
   Every photograph on the site is delivered through <picture>: AVIF first,
   WebP for the browsers that cannot read it. The box sets the aspect ratio and
   the image fills it, so the space is reserved before a single byte of the
   photograph has arrived and nothing on the page moves as it loads. */
.shot{display:block;overflow:hidden;border-radius:var(--radius);background:var(--sand)}
.shot img{width:100%;height:100%;object-fit:cover;display:block}
.shot.wide{aspect-ratio:16/9}
.shot.land{aspect-ratio:4/3}
.shot.tall{aspect-ratio:3/4}
.shot.sq{aspect-ratio:1/1}
.photorow{display:grid;gap:16px;margin:26px 0}
.photorow.p2{grid-template-columns:repeat(auto-fit,minmax(300px,1fr))}
.photorow.p3{grid-template-columns:repeat(auto-fit,minmax(230px,1fr))}
figure.shotfig{margin:0;display:flex;flex-direction:column;gap:9px}
figure.shotfig figcaption{font-size:14px;color:var(--ink-3);line-height:1.45}
/* One photograph beside its own paragraph, rather than a strip of thumbnails:
   it is the difference between a page that shows the school and a page that
   catalogues it. */
.feature{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:34px;align-items:center;margin:8px 0}
.feature .shot{max-height:520px;margin-inline:auto}
@media(max-width:820px){.feature{grid-template-columns:1fr;gap:22px}}
.meta{list-style:none;padding:0;margin:0 0 14px;font-size:14.5px;color:var(--ink-2)}
.meta li{padding:5px 0;border-bottom:1px solid var(--line);display:flex;justify-content:space-between;gap:14px}
.meta li:last-child{border-bottom:none}
.meta li span:last-child{text-align:right;font-weight:600;color:var(--ink)}

/* ---------- stat tiles ---------- */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:16px;margin:6px 0}
.stat{background:#fff;border:1px solid var(--line);border-radius:var(--radius);padding:18px 20px}
.stat b{display:block;font-size:31px;font-weight:730;letter-spacing:-.02em;line-height:1.1}
.stat span{display:block;font-size:13.5px;color:var(--ink-3);margin-top:4px}

/* ---------- poster ----------
   A full-page A4 artwork on a wide screen would either fill the column at
   1241px, which is a wall of poster, or be stretched. Cap it at a sensible
   reading width and centre it; the PDF is there for anyone who wants it
   full size. aspect-ratio keeps the space reserved before it loads. */
.poster{margin:22px 0 6px;text-align:center}
/* margin-inline:auto, not text-align: img is display:block here, so the
   parent's text-align centres the caption and leaves the picture hard left. */
.poster img{display:block;margin-inline:auto;width:100%;max-width:560px;height:auto;aspect-ratio:1241/1755;
  border:1px solid var(--line);border-radius:var(--radius);box-shadow:0 2px 14px rgba(0,0,0,.08)}
.poster figcaption{font-size:14px;color:var(--ink-3);margin-top:10px}
.muted{color:var(--ink-3)}

/* ---------- tables ---------- */
.tw{overflow-x:auto;border:1px solid var(--line);border-radius:var(--radius);margin:18px 0;background:#fff}
table{border-collapse:collapse;width:100%;font-size:15px}
caption{text-align:left;font-size:14px;color:var(--ink-3);padding:12px 16px 0;caption-side:top}
th[scope=row]{background:transparent;font-weight:600;font-size:15px;text-transform:none;letter-spacing:0;white-space:normal;border-bottom:1px solid var(--line);padding:11px 16px;color:var(--ink-2)}
th{text-align:left;background:var(--sand);font-weight:660;font-size:13.5px;padding:12px 16px;
  border-bottom:1px solid var(--line);white-space:nowrap}
td{padding:11px 16px;border-bottom:1px solid var(--line);color:var(--ink-2)}
tbody tr:last-child td{border-bottom:none}
td strong,th strong{color:var(--ink)}
/* .num right-aligns, which is right when money sits in its own column, as on
   the fee schedule and the payment-plan tables.
   The course comparison table is transposed - each course is a column - so
   right-aligning only the two money rows detached them from the nine text rows
   beneath. .figs keeps the tabular figures without touching alignment. */
.num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
.figs{font-variant-numeric:tabular-nums;white-space:nowrap}
tr.total td{background:var(--cream);font-weight:700;color:var(--ink)}

/* ---------- callouts ---------- */
.note{border-left:3px solid var(--red);background:var(--cream);padding:16px 20px;border-radius:0 8px 8px 0;margin:20px 0}
.note h3,.note h4{margin:0 0 4px;font-size:16.5px;font-weight:660}
.note p:last-child{margin-bottom:0}
.note.calm{border-left-color:var(--ink)}

/* ---------- timeline ----------
   A <ol> of real dates and real sentences. Deliberately not a graphic: an
   image of a timeline is invisible to a crawler, a screen reader and anyone
   who zooms, and the whole point of the About page is that the history can be
   read by a machine. The rule and the dot are drawn in CSS, so nothing here
   carries meaning that is lost when the styles are.

   Grid rather than absolute positioning: the year and the text sit in two
   columns, so a long description wraps under itself instead of under the year,
   and on a phone the year moves above its line. */
.tl{list-style:none;margin:22px 0 0;padding:0;border-left:2px solid var(--line);}
.tl li{display:grid;grid-template-columns:96px 1fr;gap:0 20px;padding:0 0 22px 24px;position:relative}
.tl li:last-child{padding-bottom:0}
.tl li::before{content:"";position:absolute;left:-7px;top:7px;width:12px;height:12px;border-radius:50%;
  background:var(--red);border:2px solid #fff;box-shadow:0 0 0 1px var(--line)}
.tl b{font-weight:700;font-size:15.5px;color:var(--ink);font-variant-numeric:tabular-nums}
.tl span{font-size:15.5px;color:var(--ink-2)}
@media(max-width:560px){
  .tl li{grid-template-columns:1fr;gap:2px}
  .tl b{font-size:14px;letter-spacing:.02em;color:var(--red)}
}

/* ---------- independent sources ----------
   Intentionally quieter than the page around it: this section exists so a
   reader or a crawler can check the history against records we do not own,
   not to send visitors away. Smaller type, no cards, no colour. */
.sources{margin-top:18px;display:grid;gap:18px;grid-template-columns:repeat(auto-fit,minmax(260px,1fr))}
.sources h3{font-size:15.5px;margin:0 0 4px}
.sources p{font-size:14.5px;color:var(--ink-3);margin:0 0 6px}
/* display:block, not inline: two links separated only by a <br> wrap into each
   other and read as one long link. Each needs its own line box and a gap. */
.sources a{display:block;font-size:14.5px;margin-top:7px}

/* ---------- staff portraits ----------
   A tighter grid than .g3/.g4: these are faces, not cards of prose, so they
   want to sit close together and be read as one group. 4:5 because that is
   how the portraits were shot and cropped - the site's usual 3:2 card image
   would take the top off everyone's head. object-fit:cover keeps that true
   even if a future photograph arrives at a different ratio. */
.staff{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:18px;margin:22px 0 30px}
.staff figure{margin:0}
.staff img{width:100%;aspect-ratio:4/5;object-fit:cover;object-position:50% 22%;
  border-radius:var(--radius);background:var(--cream);display:block}
.staff figcaption{margin-top:9px}
.staff b{display:block;font-size:15px;font-weight:660;line-height:1.25}
.staff span{display:block;font-size:13.5px;color:var(--ink-3);margin-top:1px}
@media(max-width:560px){.staff{grid-template-columns:repeat(auto-fill,minmax(132px,1fr));gap:14px}}

/* ---------- FAQ (always visible — never collapsed) ---------- */
.faq{border-top:1px solid var(--line);margin-top:26px}
.faq .q{border-bottom:1px solid var(--line);padding:22px 0}
.faq .q h3{margin:0 0 8px;font-size:18.5px}
.faq .q p{margin-bottom:10px}
.faq .q p:last-child{margin-bottom:0}

/* ---------- testimonials ---------- */
.quotes{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:20px}
.quote{background:#fff;border:1px solid var(--line);border-radius:var(--radius);padding:20px 22px}
.quote p{font-size:15.5px;color:var(--ink);margin-bottom:12px}
/* Name and role only — the portraits were stock photographs of other people.
   A red rule carries the visual weight the avatar used to. */
.quote .who{padding-left:11px;border-left:3px solid var(--red)}
.quote .who b{font-size:14.5px;display:block}
.quote .who span{font-size:12.5px;color:var(--ink-3)}

/* ---------- video testimonials ----------
   Three portrait clips in one row. auto-fit would drop to two-then-one and
   leave a widow, so the count is fixed at three and only breaks to one column
   on a phone, where side-by-side portrait video is unreadable anyway. */
.vids{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:18px}
.vid{margin:0;background:#fff;border:1px solid var(--line);border-radius:var(--radius);
  overflow:hidden;display:flex;flex-direction:column}
/* aspect-ratio holds the row even before the video metadata arrives, so the
   page does not jump as three files of different dimensions load. */
.vid video{display:block;width:100%;height:auto;aspect-ratio:4/5;object-fit:cover;
  background:#141414}
.vid figcaption{padding:13px 16px 15px;border-top:1px solid var(--line)}
.vid figcaption b{display:block;font-size:15px;color:var(--ink)}
.vid figcaption span{display:block;margin-top:2px;font-size:12.5px;color:var(--ink-3);
  line-height:1.45}
@media (max-width:900px){.vids{grid-template-columns:1fr;max-width:420px;margin-inline:auto}}

/* ---------- accreditation strip ---------- */
.accred{display:flex;align-items:center;gap:26px;flex-wrap:wrap;background:#fff;
  border:1px solid var(--line);border-radius:var(--radius);padding:22px 26px}
/* The three marks share a baseline height and sit in their own group so they
   wrap together rather than one at a time, which would strand a logo on its
   own line above the text. */
/* flex:0 1 auto, not flex:none. A non-shrinking group is sized to max-content,
   so its own flex-wrap never triggers and the last mark overflows the card -
   invisibly, because html has overflow-x:hidden. */
.accred .marks{display:flex;align-items:center;gap:22px;flex-wrap:wrap;
  flex:0 1 auto;max-width:100%}
.accred img{height:74px;width:auto;flex:none}
.accred > div:not(.marks){flex:1;min-width:260px}
@media(max-width:560px){.accred .marks{gap:16px}
  .accred img{height:56px}}
.accred p{margin:0;font-size:15px}

/* ---------- breadcrumb ---------- */
.crumb{font-size:13.5px;color:var(--ink-3);padding:14px 0 0}
.crumb a{color:var(--ink-3)}
.crumb span{margin:0 7px;opacity:.6}

/* ---------- footer ---------- */
footer.site{background:var(--ink);color:#c9c9c9;margin-top:0;padding:52px 0 26px;font-size:14.5px}
footer.site h2{color:#fff;font-size:14px;text-transform:uppercase;letter-spacing:.07em;margin:0 0 12px}
footer.site a{color:#e8e8e8}
footer.site p{color:#c9c9c9;margin-bottom:10px}
footer.site .cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(215px,1fr));gap:34px}
footer.site ul{list-style:none;padding:0;margin:0}
footer.site li{padding:3px 0}
footer.site .legal{border-top:1px solid #333;margin-top:34px;padding-top:20px;font-size:13px;color:#8f8f8f;
  display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap}
footer.site .legal a{color:#8f8f8f}

.updated{font-size:13.5px;color:var(--ink-3);margin-top:30px;padding-top:14px;border-top:1px solid var(--line)}

/* ---------- forms ---------- */
.enq{max-width:640px}
.fieldrow{margin:0 0 16px}
.enq label{display:block;font-weight:600;font-size:14.5px;margin-bottom:5px;color:var(--ink)}
.enq label span{color:var(--red)}
.enq input,.enq select,.enq textarea{width:100%;padding:11px 12px;border:1px solid var(--axis);
  border-radius:6px;font:inherit;font-size:16px;background:#fff;color:var(--ink)}
.enq input:focus,.enq select:focus,.enq textarea:focus{outline:2px solid var(--red);outline-offset:1px;border-color:var(--red)}
.enq [aria-invalid="true"]{border-color:var(--critical);background:#fff7f7}
.enq .err{color:#a3202f;font-size:13.5px;margin:5px 0 0;font-weight:600}
.enq .hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.enq .spin{font-size:14px;color:var(--ink-3);margin-left:12px}
.enq button[disabled]{opacity:.6;cursor:progress}
.formmsg{padding:13px 16px;border-radius:8px;font-size:15px;margin-top:14px;font-weight:600}
.formmsg.ok{background:#eaf6ea;border:1px solid #b7dfb7;color:#1c5c1c}
.formmsg.fail{background:#fdeeee;border:1px solid #f0c2c2;color:#8f1d29}
:focus-visible{outline:2px solid var(--red);outline-offset:2px}
/* ---------- landing page ---------- */
.landing{background:var(--sand);text-align:center;padding:56px 0 52px;border-bottom:1px solid var(--line)}
.landing .wrap{max-width:900px}
.landing img.mark{height:150px;width:auto;margin:0 auto 26px;display:block}
.landing h1{font-size:clamp(21px,2.5vw,27px);line-height:1.45;font-weight:500;color:var(--ink-2);
  margin:0 auto 26px;max-width:70ch;letter-spacing:0}
.landing h1 strong{color:var(--ink);font-weight:680}
/* The two schools differ in ages and hours, so the split panel names each
   campus rather than merging them into one claim that is true of neither. */
.split ul.campuses{list-style:none;padding:0;margin:0 0 18px;text-align:left;
  display:grid;gap:10px}
.split ul.campuses li{color:var(--ink-2);font-size:15.5px;line-height:1.55;
  padding-left:14px;border-left:2px solid var(--line)}
.split ul.campuses li b{color:var(--ink);font-weight:660}
.landing .btnrow{justify-content:center;margin:0}
.landing .btn{font-size:16.5px;padding:15px 30px}
/* On a phone the whole point of this page is that the two choices are visible
   without hunting for them, so the mark and the introduction both tighten to
   keep the buttons near the fold. 16px is still above the 15px body minimum. */
@media(max-width:640px){.landing{padding:28px 0 30px}
  .landing img.mark{height:88px;margin-bottom:16px}
  .landing h1{font-size:16.5px;line-height:1.5;margin-bottom:22px;text-align:left}
  .landing .btnrow{flex-direction:column;align-items:stretch}}

.split{display:grid;grid-template-columns:1fr 1fr;gap:0}
.split > div{padding:52px 46px;text-align:center;display:flex;flex-direction:column;
  align-items:center;min-width:0}
.split > div:first-child{border-right:1px solid var(--line)}
.split img.mark{height:118px;width:auto;margin:0 auto 22px;display:block}
.split h2{font-size:clamp(20px,2.2vw,25px);margin:0 0 12px}
.split p{font-size:16px;max-width:46ch;margin:0 auto 20px;text-align:center}
.split figure{margin:0 0 22px;width:100%;max-width:100%;min-width:0}
.split figure img{border-radius:var(--radius);box-shadow:var(--shadow);width:100%;height:auto;
  aspect-ratio:3/2;object-fit:cover}
.split .btn{margin-top:auto}
@media(max-width:860px){.split{grid-template-columns:1fr}
  .split > div{padding:40px 22px;border-right:none;border-bottom:1px solid var(--line)}
  .split img.mark{height:92px}}


/* ---------- staging banner (staging builds only) ---------- */
.stagingbar{background:#1c1c1c;color:#ffd9a0;font-size:12.5px;letter-spacing:.02em;
  text-align:center;padding:7px 16px;border-bottom:1px solid #3a3a3a}
.stagingbar b{color:#ffb027;font-weight:700}
.skip{position:absolute;left:-9999px}
.skip:focus{left:8px;top:8px;position:fixed;background:#fff;padding:10px 16px;z-index:200;border-radius:6px}

/* The accreditation marks are links to each body's own record, so they need
   to behave as flex items in their own right and show they are clickable.
   Keyboard focus is covered by the global :focus-visible rule. */
.accred .marks a{display:inline-flex;flex:none;border-radius:6px;
  transition:opacity .15s ease}
.accred .marks a:hover{opacity:.7}
@media(prefers-reduced-motion:reduce){.accred .marks a{transition:none}}
