/* Site stylesheet. Plain CSS, no framework, no third-party CDN assets — the
 * CSP allows same-origin only. Fonts are self-hosted below (see
 * static/fonts/). Tokens first, then layout, then components.
 * No inline style="" anywhere in templates: utilities/components live here
 * instead. No inline event handlers either — behaviour is in app.js. */

@font-face {
    font-family: 'Inter';
    src: url("../fonts/inter-variable.260c81a4759b.woff2") format('woff2');
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Poppins';
    src: url("../fonts/poppins-600.72993dddf88a.woff2") format('woff2');
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Poppins';
    src: url("../fonts/poppins-700.25b0e113ca7c.woff2") format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Poppins';
    src: url("../fonts/poppins-800.af4d371a1027.woff2") format('woff2');
    font-weight: 800;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Playfair Display';
    src: url("../fonts/playfair-display-variable.ef05b30d6e5c.woff2") format('woff2');
    font-weight: 400 900;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Caveat';
    src: url("../fonts/caveat-variable.2d9de14f93a2.woff2") format('woff2');
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
}

:root {
    /* Palette matched to the stakeholder-provided homepage design
       (static/img/St. Anne's HSS - Home.png): deep navy + warm gold. */
    --navy-50:  #EEF3F8;
    --navy-100: #D7E3EE;
    --navy-600: #1E4972;
    --navy-700: #163A5C;
    --navy-800: #0E2C48;
    --navy-900: #0A2438;

    --gold-50:  #FDF6E7;
    --gold-100: #F7E7C1;
    --gold-400: #F2CE7E;
    --gold-500: #E8B84B;
    --gold-600: #C79530;

    --slate-600: #55677A;
    --off-white: #FAF8F4;
    --cream: #FBF3E7;
    --cream-deep: #F5E9D8;
    --pale-blue: #EDF3F7;

    --font-body: 'Inter', system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    --font-display: 'Playfair Display', 'Poppins', 'Inter', system-ui, serif;
    --font-script: 'Caveat', cursive;

    --radius-sm: 10px;
    --radius-md: 16px;
    --radius-lg: 24px;
    --container: 80rem;
    --container-narrow: 46rem;
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; overflow-x: hidden; }
body { margin: 0; font-family: var(--font-body); color: var(--navy-900); background: var(--off-white); -webkit-font-smoothing: antialiased; }
h1, h2, h3, h4 { font-family: var(--font-display); font-weight: 700; margin: 0; line-height: 1.2; }
p { margin: 0 0 1em; }
img, svg, video { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }

.container { width: min(100% - 2rem, var(--container)); margin-inline: auto; }
.container--narrow { max-width: var(--container-narrow); }
.section { padding-block: clamp(1rem, 2.5vw, 1.5rem); position: relative; }
.section--purpose { padding-top: clamp(1rem, 2vw, 1.25rem); overflow: hidden; position: relative; }
.section--campus { overflow: hidden; position: relative; }
.flow > * + * { margin-top: 1em; }

.screen-reader-text {
    position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.skip-link:focus {
    position: fixed !important; top: .5rem; left: .5rem; width: auto; height: auto; margin: 0;
    padding: .5rem 1rem; clip: auto; background: var(--navy-900); color: #fff; z-index: 1000; border-radius: 6px;
}
:focus-visible { outline: 3px solid var(--gold-500); outline-offset: 2px; }

.icon { width: 1.1em; height: 1.1em; display: inline-block; vertical-align: -0.15em; flex-shrink: 0; }
.icon--sm { width: 1em; height: 1em; }
.flip-x { transform: scaleX(-1); }

/* ---------- Buttons ---------- */
.btn {
    display: inline-flex; align-items: center; gap: .5rem; justify-content: center;
    padding: .7rem 1.5rem; border-radius: 999px; font-weight: 600; font: inherit;
    border: 2px solid transparent; cursor: pointer; white-space: nowrap;
}
.btn--gold { background: var(--gold-500); color: var(--navy-900); }
.btn--gold:hover { background: var(--gold-600); }
.btn--ghost { background: transparent; border-color: rgba(255,255,255,.5); color: #fff; }
.btn--ghost:hover { background: rgba(255,255,255,.12); }
.btn--outline { background: transparent; border-color: var(--navy-700); color: var(--navy-800); }
.btn--outline:hover { background: var(--navy-800); color: #fff; }
.btn--sm { padding: .5rem 1.1rem; font-size: .8125rem; }
.btn--pop { transition: transform .25s ease, background-color .25s ease, color .25s ease; }
.btn--pop:hover { transform: scale(1.05); }
.btn--pop:active { transform: scale(.98); }
.btn--circle { width: 2.75rem; height: 2.75rem; padding: 0; border-radius: 999px; flex-shrink: 0; }

.pill { display: inline-flex; align-items: center; font-size: .75rem; font-weight: 600; color: var(--gold-600); background: var(--gold-50); padding: .25rem .75rem; border-radius: 999px; }

/* ---------- Reveal-on-scroll ---------- */
.reveal { opacity: 0; transform: translateY(28px) scale(.98); transition: opacity .7s cubic-bezier(.21,.61,.35,1), transform .7s cubic-bezier(.21,.61,.35,1); }
.reveal.in-view { opacity: 1; transform: translateY(0) scale(1); }
@media (prefers-reduced-motion: reduce) { .reveal { opacity: 1; transform: none; transition: none; } }

.lift { transition: transform .35s ease, box-shadow .35s ease; }
.lift:hover { transform: translateY(-6px); box-shadow: 0 20px 40px -20px rgba(14,47,92,.35); }

.accent-underline { position: relative; display: inline-block; color: var(--navy-900); }
.accent-underline::after {
    content: ''; position: absolute; left: 0; bottom: -10px; width: 56px; height: 3px;
    background: var(--gold-500); border-radius: 2px; transform: scaleX(0); transform-origin: left;
    transition: transform .6s ease .2s;
}
.accent-underline.center::after { left: 50%; transform-origin: center; transform: translateX(-50%) scaleX(0); }
.reveal.in-view .accent-underline::after { transform: scaleX(1); }
.reveal.in-view .accent-underline.center::after { transform: translateX(-50%) scaleX(1); }

.orb { position: absolute; border-radius: 999px; pointer-events: none; filter: blur(60px); animation: float-slow 10s ease-in-out infinite; }
.orb[data-orb="1"] { left: -4rem; top: 0; width: 18rem; height: 18rem; background: rgba(37,100,176,.06); }
.orb[data-orb="2"] { right: 0; top: 50%; width: 20rem; height: 20rem; background: rgba(201,151,42,.1); animation-name: float-slow-centered; animation-delay: -3s; }
.orb[data-orb="3"] { left: -6rem; top: -6rem; width: 24rem; height: 24rem; background: rgba(201,151,42,.1); animation-delay: -5s; filter: none; }
.orb[data-orb="4"] { right: -6rem; bottom: -6rem; width: 24rem; height: 24rem; background: rgba(201,151,42,.05); animation-delay: -1.5s; filter: none; }
.orb[data-orb="5"] { right: -4rem; top: 2.5rem; width: 18rem; height: 18rem; background: rgba(28,74,136,.05); }
@keyframes float-slow { 0%,100% { transform: translate(0,0); } 50% { transform: translate(14px,-16px); } }
@keyframes float-slow-centered { 0%,100% { transform: translateY(-50%) translate(0,0); } 50% { transform: translateY(-50%) translate(14px,-16px); } }
@media (prefers-reduced-motion: reduce) { .orb { animation: none; } }

/* ---------- Site header (sticky) ----------
   The whole header (topbar + navbar together) sticks as one unit, not just
   the navbar row — position:sticky (not fixed) so it keeps its own space
   in normal flow: no layout shift, no compensating top-padding needed on
   the page content below it. Stays pinned in both scroll directions (sticky
   only ever un-pins if the page scrolls back above where the header
   started, i.e. to the very top — there's no scroll-direction-based
   hide/show script here). z-index:100 is comfortably above every other
   z-index in this file (nothing else in normal page content exceeds 5;
   #page-progress's 1001 and the skip-link's 1000 stay above it
   intentionally). .topbar and .navbar each already paint an opaque/near-
   opaque background across their own full width with no gap between them,
   so the header reads as one solid surface with nothing bleeding through
   while scrolling — no separate background needed on .site-header itself. */
/* will-change hints the browser to promote this to its own compositing
   layer up front, so re-stacking it against scrolled content doesn't
   force a full repaint of the header on every scroll frame — helps smooth
   out the jerky/stuttery redraw a sticky header can otherwise show on
   mobile while scrolling. */
.site-header { position: sticky; top: 0; z-index: 100; will-change: transform; }

/* ---------- Top bar ---------- */
.topbar { background: linear-gradient(180deg, #F3F9FD, #FFFFFF); color: var(--navy-700); font-size: .8125rem; }
.topbar__row { display: flex; align-items: center; justify-content: flex-end; gap: 1.5rem; padding-block: .2rem; flex-wrap: wrap; }
.topbar__links { display: flex; align-items: center; gap: 1.25rem; font-weight: 500; }
.topbar__links a:hover { color: var(--gold-600); }
.topbar__actions { display: flex; align-items: center; gap: .9rem; }
.topbar .social { display: flex; gap: .6rem; }
.topbar .social a { width: 1.6rem; height: 1.6rem; background: none; color: var(--navy-700); }
.topbar .social a:hover { background: none; color: var(--gold-600); }
.topbar__search { display: inline-flex; align-items: center; justify-content: center; background: none; border: 0; color: var(--navy-700); cursor: pointer; padding: 0; }
.topbar__search:hover { color: var(--gold-600); }
@media (max-width: 40em) { .topbar__links { display: none; } }

/* ---------- Navbar ---------- */
/* No longer position:sticky here — .site-header above now sticks the
   whole topbar+navbar unit together, so a second independent sticky
   context on just this inner row is unnecessary (and would fight the
   parent's own top:0 pinning). */
.navbar { background: rgba(255,255,255,.95); backdrop-filter: blur(6px); transition: box-shadow .3s; }
.navbar.is-scrolled { box-shadow: 0 8px 24px -12px rgba(14,47,92,.25); }
/* backdrop-filter forces the browser to recompute the blur underneath this
   (now sticky) bar on every scroll frame — a common source of stutter/jank
   while scrolling on mobile GPUs. Background is already 95% opaque, so the
   blur adds little visually; dropping it below 40em removes that repaint
   cost where it's most noticeable, without changing how the header looks
   or is positioned on desktop. */
@media (max-width: 40em) { .navbar { backdrop-filter: none; } }
.navbar__inner { display: flex; align-items: center; justify-content: space-between; height: 5rem; gap: 1rem; }
.brand { display: flex; align-items: center; gap: .75rem; }
.brand__crest { width: 78px; height: 78px; object-fit: contain; display: block; flex-shrink: 0; transition: transform .35s ease; }
.brand:hover .brand__crest { transform: scale(1.08) rotate(-3deg); }
.brand__text { display: flex; flex-direction: column; line-height: 1.25; }
.brand__text strong { font-family: var(--font-display); font-size: 1.5rem; letter-spacing: .02em; color: var(--navy-900); }
.brand__text small { font-size: .78rem; letter-spacing: .02em; color: var(--slate-600); font-weight: 500; text-transform: uppercase; }

.nav-links { display: none; align-items: center; gap: .9rem; font-size: .8125rem; font-weight: 500; color: var(--slate-600); }
.nav-link { position: relative; background: none; border: 0; padding: .5rem 0; display: inline-flex; align-items: center; gap: .25rem; font: inherit; color: inherit; cursor: pointer; }
.nav-link:hover { color: var(--gold-600); }
.nav-link.is-current { color: var(--gold-600); }
.nav-link::after {
    content: ''; position: absolute; left: 0; right: 0; bottom: -6px; height: 2px;
    background: var(--gold-500); border-radius: 2px; transform: scaleX(0); transition: transform .25s ease;
}
.nav-link:hover::after { transform: scaleX(1); }

.nav-dropdown { position: relative; }
.nav-dropdown__panel { position: absolute; left: 0; top: 100%; padding-top: .25rem; display: none; z-index: 20; min-width: 200px; }
.nav-dropdown__panel--wide { min-width: 280px; }
.nav-dropdown--right .nav-dropdown__panel { left: auto; right: 0; }
.nav-dropdown:hover .nav-dropdown__panel { display: block; }
.nav-dropdown__panel { background: #fff; border: 1px solid var(--navy-50); border-radius: 12px; box-shadow: 0 20px 40px -20px rgba(14,47,92,.35); padding: .5rem 0; }
.nav-dropdown__panel a { display: block; padding: .5rem 1rem; font-size: .875rem; color: var(--slate-600); }
.nav-dropdown__panel a:hover { background: var(--navy-50); color: var(--gold-600); }

.navbar__actions { display: flex; align-items: center; gap: .6rem; }
.navbar__cta { padding: .6rem 1.25rem; font-size: .8125rem; display: none; }
.navbar__portal { padding: .55rem 1.1rem; font-size: .8125rem; display: none; }
.nav-toggle { width: 2.5rem; height: 2.5rem; display: inline-flex; align-items: center; justify-content: center; border-radius: 10px; border: 1px solid var(--navy-100); background: none; color: var(--navy-900); cursor: pointer; }

/* max-height:0 alone doesn't fully collapse a flex container that has its
   own block padding — the padding box (and a sliver of its first child,
   e.g. "Home") still rendered at ~29px even at max-height:0. Zeroing
   padding-block in the collapsed state (and restoring it only in .is-open)
   fixes that; both are transitioned together for the same smooth open/
   close animation as before. */
.mobile-menu { max-height: 0; padding-block: 0; overflow: hidden; transition: max-height .4s ease, padding-block .4s ease; border-top: 1px solid var(--navy-50); }
.mobile-menu.is-open { max-height: 2000px; padding-block: .5rem 1.25rem; overflow-y: auto; }
.mobile-menu { display: flex; flex-direction: column; gap: .125rem; font-weight: 500; color: var(--slate-600); }
.mobile-menu__link, .mobile-menu__group summary { padding: .6rem .5rem; border-radius: 10px; display: flex; align-items: center; justify-content: space-between; cursor: pointer; list-style: none; }
.mobile-menu__link:hover, .mobile-menu__group summary:hover { background: var(--navy-50); }
.mobile-menu__group summary::-webkit-details-marker { display: none; }
.mobile-menu__group[open] summary .icon { transform: rotate(180deg); }
.mobile-menu__sub { display: flex; flex-direction: column; padding-left: 1rem; }
.mobile-menu__sub a { padding: .5rem; border-radius: 10px; font-size: .875rem; }
.mobile-menu__sub a:hover { background: var(--navy-50); }
.mobile-menu__cta { margin-top: .5rem; justify-content: center; }

@media (min-width: 80em) {
    .nav-links { display: flex; }
    .navbar__cta { display: inline-flex; }
    .navbar__portal { display: inline-flex; }
    .nav-toggle { display: none; }
}
@media (max-width: 79.99em) { .mobile-menu { display: flex; } }
@media (min-width: 80em) { .mobile-menu { display: none !important; max-height: none; } }

/* ---------- Hero ---------- */
/* Fixed min-height so the section doesn't resize as the autoplaying
   slideshow swaps in each slide's heading/lead text (different slides'
   copy wraps to different numbers of lines, which otherwise reflows the
   whole section per-slide). Values are each breakpoint's tallest slide,
   measured directly, plus a small safety margin. */
.hero { position: relative; color: #fff; overflow: hidden; background: var(--navy-900); min-height: 27.2rem; }
@media (min-width: 48em) { .hero { min-height: 25.25rem; } }
@media (min-width: 56em) { .hero { min-height: 28.5rem; } }
.hero__layers { position: absolute; inset: 0; }
.hero__layer {
    position: absolute; inset: 0; opacity: 0; transition: opacity 1s ease;
}
.hero__layer.is-active { opacity: 1; z-index: 1; }
.hero__layer .ph { position: absolute; inset: 0; border-radius: 0; }
.hero__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Smart-Class.png (2nd fallback slide) is near-square, so the very wide/
   short hero box crops most of it — the default centered crop cut off the
   teacher's face entirely. Bias the crop upward so it stays in frame. */
.hero__layer:nth-child(2) .hero__bg { object-position: 50% 13%; }
.hero__overlay {
    position: absolute; inset: 0; z-index: 1;
    background: linear-gradient(100deg, rgba(10,36,56,.94) 0%, rgba(10,36,56,.82) 32%, rgba(10,36,56,.35) 62%, rgba(10,36,56,.15) 100%);
}
.hero__corner { position: absolute; z-index: 1; right: 0; bottom: 0; width: min(46%, 34rem); height: auto; display: none; pointer-events: none; }
@media (min-width: 64em) { .hero__corner { display: block; } }
.hero__content { position: relative; z-index: 2; padding-block: clamp(1.5rem, 4vw, 2.25rem) clamp(1rem, 2.5vw, 1.5rem); }
.hero__col { transition: opacity .4s ease; }
.hero__col.is-fading { opacity: 0; }
.hero__col { max-width: 34rem; }
.hero .eyebrow { color: var(--gold-400); font-size: .75rem; }
.hero h1 { font-size: clamp(1.75rem, 1.3rem + 2vw, 2.9rem); line-height: 1.15; margin-bottom: .5rem; }
.text-gold { color: var(--gold-400); }
.hero__script { display: block; font-family: var(--font-script); font-weight: 600; color: var(--gold-400); font-size: 1.35em; line-height: 1; margin-top: .1em; }
.hero__lead { font-size: clamp(.9rem, .86rem + .25vw, 1rem); color: rgba(255,255,255,.82); max-width: 30rem; margin: 1rem 0 1.75rem; }
.hero__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; }
.hero__actions .btn { font-size: .875rem; font-weight: 700; }
.hero__facts {
    display: flex; flex-wrap: nowrap; align-items: center; gap: .6rem 1.25rem; margin-top: 1.5rem;
    font-size: .8125rem; font-weight: 500; color: rgba(255,255,255,.9); max-width: 100%;
    overflow-x: auto; -ms-overflow-style: none; scrollbar-width: none; padding-bottom: .25rem;
}
.hero__facts::-webkit-scrollbar { display: none; }
.hero__fact { display: inline-flex; align-items: center; gap: .5rem; white-space: nowrap; flex-shrink: 0; }
.hero__fact .icon { color: var(--gold-400); width: 1.4em; height: 1.4em; }
.hero__fact + .hero__fact { padding-left: 1.25rem; border-left: 1px solid rgba(255,255,255,.3); }
@media (max-width: 30em) {
    .hero__fact + .hero__fact { padding-left: .85rem; }
    /* Below this width the row can't fit without scrolling — show a thin
       scrollbar instead of hiding it, so nothing looks silently cut off. */
    .hero__facts { scrollbar-width: thin; }
    .hero__facts::-webkit-scrollbar { display: block; height: 3px; }
    .hero__facts::-webkit-scrollbar-thumb { background: rgba(255,255,255,.4); border-radius: 2px; }
    .hero__facts::-webkit-scrollbar-track { background: rgba(255,255,255,.1); }
}

.badge {
    display: inline-flex; align-items: center; gap: .5rem; background: rgba(255,255,255,.1);
    border: 1px solid rgba(255,255,255,.25); backdrop-filter: blur(4px); border-radius: 999px;
    padding: .4rem 1rem; font-size: .8125rem; font-weight: 500; margin-bottom: 1rem;
}

/* ---------- Section heading ---------- */
.section__heading { text-align: center; max-width: 42rem; margin: 0 auto 1rem; }
.eyebrow { display: flex; align-items: center; justify-content: center; gap: .375rem; color: var(--gold-600); font-weight: 600; font-size: .8125rem; letter-spacing: .08em; text-transform: uppercase; margin-bottom: .5rem; }
.eyebrow--light { color: var(--gold-400); justify-content: flex-start; }
.eyebrow--left { justify-content: flex-start; }
.section__heading h2 { font-size: clamp(1.5rem, 1.2rem + 1vw, 2.25rem); }

.divider { height: 1px; margin-block: 1.5rem; background: linear-gradient(90deg, transparent, var(--navy-100), transparent); }

/* ---------- Placeholder component (for stakeholder-supplied photos) ---------- */
.ph {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: .4rem;
    width: 100%; height: 100%; min-height: 100%;
    background: repeating-linear-gradient(135deg, var(--navy-50) 0 14px, #fff 14px 28px);
    color: var(--navy-600); text-align: center; padding: .75rem;
}
.ph .icon { width: 1.6rem; height: 1.6rem; opacity: .5; }
.ph span { font-size: .65rem; font-weight: 600; letter-spacing: .02em; opacity: .7; max-width: 12rem; line-height: 1.3; }
.ph--dark { background: repeating-linear-gradient(135deg, rgba(255,255,255,.08) 0 14px, rgba(255,255,255,.02) 14px 28px); color: rgba(255,255,255,.6); }

/* ---------- Quick Access + Our Story ---------- */
.section--story {
    background: var(--off-white); overflow: hidden;
    /* No top padding: the building photo's top edge should touch the hero
       section's bottom edge exactly. Bottom padding unchanged. */
    padding-top: 0; padding-bottom: clamp(.75rem, 1.5vw, 1rem);
}
.story-grid { display: grid; grid-template-columns: 1fr; gap: 1rem; }
@media (min-width: 56em) { .story-grid { grid-template-columns: .8fr 1.2fr; gap: 1.5rem; align-items: start; } }
.qa-card {
    background: var(--off-white); border-radius: var(--radius-lg); padding: clamp(.85rem, 1.8vw, 1.15rem);
    box-shadow: 0 24px 48px -28px rgba(14,47,92,.2); border: 1px solid var(--navy-50);
    position: relative;
    z-index: 3;
}
/* Fixed height (not stretched to the row) so the card's bottom edge lines
   up with the second line of the story-hero quote text beside it. Doesn't
   touch .story-hero or the row height, so nothing else shifts. */
@media (min-width: 56em) { .qa-card { align-self: start; height: 33.17rem; } }
.qa-title { font-size: clamp(1.4rem, 1.1rem + 1.6vw, 1.9rem); color: var(--navy-900); margin-bottom: .1rem; }
/* Matches .story-hero__panel h2 ("A Century of Excellence") at the same breakpoint. */
@media (min-width: 56em) { .qa-title { font-size: clamp(1.5rem, 1.1rem + 1.7vw, 2.25rem); } }
.qa-sub { color: var(--slate-600); font-size: .825rem; margin-bottom: .75rem; }
.qa-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: .65rem; }
@media (min-width: 30em) { .qa-grid { grid-template-columns: repeat(3, 1fr); } }
.qa-tile {
    background: #fff; border: 1px solid var(--navy-50); border-radius: var(--radius-md); padding: .85rem .9rem;
    display: flex; flex-direction: column; gap: .25rem;
    transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease;
}
.qa-tile:hover { transform: translateY(-4px); box-shadow: 0 16px 32px -20px rgba(14,47,92,.3); border-color: var(--navy-100); }
.qa-tile__icon {
    width: 1.6rem; height: 1.6rem; border-radius: 999px; background: #fff; color: var(--navy-600);
    display: inline-flex; align-items: center; justify-content: center;
}
.qa-tile__title { font-weight: 700; color: var(--navy-900); font-size: .85rem; font-family: var(--font-body); }
.qa-tile__sub { font-size: .7rem; color: var(--slate-600); display: inline-flex; align-items: center; gap: .25rem; }
.qa-tile--primary { background: var(--navy-900); border-color: var(--navy-900); }
.qa-tile--primary .qa-tile__title { color: #fff; }
.qa-tile--primary .qa-tile__sub { color: rgba(255,255,255,.75); }
.qa-tile--primary:hover { border-color: var(--gold-500); }

/* ---------- "A Century of Excellence": pixel-mapped layered composition ----------
   Reference screenshot is 705x667 for this component. Every position/size
   below is that same box expressed as a percentage, so the layered/overlap
   relationships hold at any width. Desktop (>=56em) only — see the mobile
   stacked fallback near the end of this block. */
.story-hero { position: relative; }
.story-link-block { display: none; }
@media (min-width: 56em) {
    /* Compacted from the reference's 705/667 — shorter overall, independent
       of the Quick Access card (its own grid column, untouched). */
    .story-hero { aspect-ratio: 705 / 560; }

    /* Building: anchor box per reference (left 385 top 0 w315 h520 of 705x667).
       height:75% (was 77.96%) so its bottom edge touches the student photo's
       top edge (student is top:75%) instead of overlapping it by ~3%. */
    .story-hero__building {
        position: absolute; z-index: 2; left: 54.61%; top: 0;
        /* Stretch past .story-hero's own right edge out to the page's true
           right gutter (mirrors .container's own max-width/margin math,
           same formula .story-hero__student uses below — previously had an
           extra +1rem that overshot the true page edge instead of fitting
           it), without resizing .story-hero itself — so the
           percentage-positioned panel/quote/badge siblings are unaffected. */
        right: calc(-1 * max(1rem, 50vw - 40rem)); height: 75%;
        overflow: hidden;
    }
    .story-hero__building img { width: 100%; height: 100%; object-fit: cover; object-position: top; display: block; }

    /* Students: full-bleed — same left/width as the building above it (so
       their edges line up) and no shadow/gap, so the two photos read as one
       continuous image rather than a separate floating card. */
    .story-hero__student {
        position: absolute; z-index: 1; left: 54.61%; top: 75%;
        right: calc(-1 * max(1rem, 50vw - 40rem)); height: 25%;
        overflow: hidden;
    }
    .story-hero__student img { width: 100%; height: 100%; object-fit: cover; object-position: 66% 45%; display: block; }

    /* Story panel: anchor box per reference (left 45 top 30 w355 h440). No card chrome. */
    .story-hero__panel {
        position: absolute; z-index: 3; left: 6.38%; top: 4.5%; width: 50.35%; height: 65.97%;
        padding: 0 1.25rem 0 0;
        display: flex; flex-direction: column; justify-content: center;
    }
    .story-hero__panel .eyebrow { justify-content: flex-start; margin-bottom: .5rem; }
    .story-hero__panel h2 { font-size: clamp(1.5rem, 1.1rem + 1.7vw, 2.25rem); line-height: 1.15; margin-bottom: .85rem; }
    .story-hero__panel p { color: var(--slate-600); font-size: .8rem; line-height: 1.6; margin-bottom: 1.1rem; white-space: nowrap; }
    .story-hero__panel .btn { padding: .5rem .9rem; font-size: .8rem; align-self: flex-start; }

    /* Quote panel: anchor box per reference (left 48 top 440 w~530 h215).
       z-index above the student photo so it layers in front of it; height
       extended to 100%-top so its bottom edge lines up with the student
       photo's own bottom edge (student is top:75%+height:25% = 100%). */
    .story-hero__quote {
        position: absolute; z-index: 4; left: 6.81%; top: 65.97%; width: 47.8%; height: 34.03%;
        background: var(--navy-900); color: #fff;
        clip-path: polygon(0% 8%, 60% 0%, 100% 6%, 100% 100%, 0% 100%);
        padding: 1.75rem 1.75rem 1.25rem; overflow: hidden;
    }
    .story-hero__quote::before {
        content: '\201C'; position: absolute; top: .5rem; left: 1.25rem; font-family: var(--font-display);
        font-size: 3rem; color: var(--gold-500); line-height: 1; opacity: .7;
    }
    .story-hero__quote p {
        font-family: var(--font-display); font-style: italic; font-size: 1.2rem; line-height: 1.45;
        margin: 0 0 .6rem; padding-left: 1.5rem; color: #fff; white-space: nowrap;
    }
    .story-hero__quote cite { font-size: .8rem; color: rgba(255,255,255,.65); font-style: normal; padding-left: 1.5rem; display: block; }

    /* Connector rectangle bridging .qa-card and the quote. Positioned in the
       SAME coordinate system as .story-hero__quote (percentages of this
       .story-hero box, which has no padding/border) rather than the wider
       .story-grid box, so it tracks the quote's actual edges exactly at
       every viewport width — .story-grid's row height is whichever of
       .qa-card (fixed rem height) or .story-hero (aspect-ratio height) is
       taller, and that varies by width, so percentages of .story-grid don't
       stay in sync with the quote the way percentages of .story-hero do.
       - bottom: 0 — .story-hero__quote's own top+height sums to 100%, i.e.
         its bottom edge already sits exactly on .story-hero's bottom edge,
         so anchoring our bottom there matches the quote's bottom exactly.
       - height: 30% — slightly less than the quote's 34.03%.
       - left/width use calc() mixing px and % because .qa-card sits in a
         separate, independently-scaling grid column. Measured directly
         against the live rendered boxes at two widths (1024px and 1280px
         viewports) rather than trusted from the CSS source, since
         .qa-card's actual right edge — after accounting for the browser's
         fr-track rounding, not just the nominal 1.5rem grid gap — turned
         out to sit at 24px + 0.667% of .story-hero's own width to its
         left, and .story-hero__quote's actual left edge turned out to be
         7.2875% in (not the 6.81% an older comment on .story-hero__quote
         claims — that value no longer matches this file's current rules).
         Solved from two constraints: (a) right edge (left+width) = the
         quote's measured left edge, 7.2875% (touching, not overlapping)
         and (b) .qa-card's measured bottom-right corner lands exactly 1/4
         of the way across this block's top edge. Re-derive both constants
         (via getBoundingClientRect on .qa-card/.story-hero__quote/
         .story-hero at two different viewport widths) if either box's own
         CSS changes. */
    .story-link-block {
        display: block; position: absolute; z-index: 1;
        left: calc(-32px - 3.32%); width: calc(32px + 10.61%);
        bottom: 0; height: 30%;
        background: var(--navy-900);
        /* Bottom edge narrowed (bottom-left corner pulled in) so the left
           edge reads as a tilted diagonal instead of vertical. Top-right
           and bottom-right corners stay at 100% — the right edge (touching
           the quote) and the overall bounding box (right/bottom alignment
           verified above) are unaffected; clip-path is purely visual. */
        clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 28% 100%);
    }

    /* Badge: shown plain/circular (the source art — 100C.png — is already a
       round emblem on a square canvas). Enlarged again (13.79%->16.55% /
       17.36%->20.83%, same aspect so border-radius:50% stays a true circle)
       so the "100" text baked into the artwork reads clearly. `left` kept
       fixed at 49.1% so the extra size keeps growing only to the right
       (away from the quote text it must clear), not left into it; `top`
       recomputed to keep the same vertical center (71%) as before the
       resize. */
    .story-hero__badge {
        /* z-index 5 (was 2) — above .story-hero__quote (4) and
           .story-hero__panel (3), so the badge now visibly layers over the
           story-quote section instead of being occluded by it. */
        position: absolute; z-index: 5; left: 49.1%; top: 60.59%; width: 16.55%; height: 20.83%;
    }
    .story-hero__badge__inner {
        width: 100%; height: 100%; border-radius: 50%; overflow: hidden;
    }
    .story-hero__badge img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: center; }
}

/* Mobile/tablet: rearrange into a simple stack, same visual hierarchy. */
@media (max-width: 55.99em) {
    .story-hero { display: flex; flex-direction: column; gap: 1.25rem; }
    .story-hero__panel { order: 1; }
    .story-hero__panel .eyebrow { justify-content: flex-start; margin-bottom: .5rem; }
    .story-hero__panel h2 { font-size: clamp(1.4rem, 1.1rem + 1.6vw, 1.9rem); line-height: 1.2; margin-bottom: .65rem; }
    .story-hero__panel h2 br { display: none; }
    .story-hero__panel p { color: var(--slate-600); font-size: .9rem; margin-bottom: 1rem; }
    .story-hero__panel p br { display: none; }
    .story-hero__building { order: 2; position: relative; border-radius: var(--radius-lg); overflow: hidden; aspect-ratio: 4/3; }
    .story-hero__building img { width: 100%; height: 100%; object-fit: cover; object-position: center 22%; display: block; }
    .story-hero__badge { order: 3; width: min(60%, 16rem); margin: -3rem auto 0; position: relative; z-index: 2; border-radius: var(--radius-md); overflow: hidden; box-shadow: 0 20px 40px -20px rgba(14,47,92,.35); }
    .story-hero__badge img { display: block; width: 100%; height: auto; }
    .story-hero__quote {
        order: 4; background: var(--navy-900); color: #fff; border-radius: var(--radius-lg); padding: 1.25rem 1.5rem;
        position: relative; overflow: hidden;
    }
    .story-hero__quote::before {
        content: '\201C'; position: absolute; top: -.25rem; left: 1.1rem; font-family: var(--font-display);
        font-size: 3.25rem; color: var(--gold-500); line-height: 1; opacity: .6;
    }
    .story-hero__quote p { font-family: var(--font-display); font-style: italic; font-size: 1.05rem; line-height: 1.45; margin: 0 0 .6rem; padding-left: 1.5rem; color: #fff; }
    .story-hero__quote p br { display: none; }
    .story-hero__quote cite { font-size: .78rem; color: rgba(255,255,255,.65); font-style: normal; padding-left: 1.5rem; display: block; }
    .story-hero__quote cite br { display: none; }
    .story-hero__student { order: 5; position: relative; border-radius: var(--radius-lg); overflow: hidden; aspect-ratio: 16/9; }
    .story-hero__student img { width: 100%; height: 100%; object-fit: cover; object-position: 66% 45%; display: block; }
}

/* ---------- Why St. Anne's + Legacy timeline ---------- */
.section--why {
  background: var(--off-white);
  overflow: hidden;
  position: relative;
  padding-bottom: clamp(.75rem, 1.5vw, 1.1rem);
}
.section--why .container { position: relative; z-index: 1; padding-inline: 1.5rem; }
.why-band {
  background: var(--cream);
  padding-block: clamp(.75rem, 1.5vw, 1.1rem);
}
.why-grid { display: grid; grid-template-columns: 1fr; gap: .85rem; align-items: start; }
@media (min-width: 56em) { .why-grid { grid-template-columns: .8fr 1.6fr; gap: 1.5rem; } }
.why-copy .eyebrow { justify-content: flex-start; }
/* Clears the left .section--why__leaf's actual art (reaches ~97px from the
   page edge at its 7.5rem size) — per instruction, moved instead of
   shrinking the leaf back down. Desktop only (matches why-grid's own
   min-width:56em two-column breakpoint, where .why-copy is a narrow
   column directly beside the leaf); at the single-column mobile stack
   .why-copy isn't specifically beside the leaf the same way. */
@media (min-width: 56em) { .why-copy { margin-left: 4rem; } }
.why-copy h2 { font-family: var(--font-display); font-size: clamp(1.15rem, 1rem + .9vw, 1.5rem); line-height: 1.2; color: var(--navy-900); margin-bottom: .35rem; }
.why-copy p { color: var(--slate-600); font-size: .9rem; max-width: 34ch; margin-bottom: .5rem; }
@media (min-width: 56em) {
  .why-copy p { font-size: .8rem; }
}
.why-copy__link { display: inline-flex; align-items: center; gap: .35rem; font-weight: 700; color: var(--navy-900); text-decoration: underline; text-underline-offset: 3px; }
.why-copy__link .icon { width: 1rem; height: 1rem; color: var(--navy-900); transition: transform .2s ease; }
.why-copy__link:hover { color: var(--gold-600, var(--gold-500)); }
.why-copy__link:hover .icon { transform: translateX(3px); }
.why-cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: .85rem; }
@media (min-width: 40em) { .why-cards { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 56em) { .why-cards { grid-template-columns: repeat(6, 1fr); } }
.why-card { background: #fff; border: none; border-radius: var(--radius-md); padding: .85rem .7rem; text-align: center; box-shadow: 0 10px 24px -16px rgba(14,47,92,.25); transition: transform .25s ease, box-shadow .25s ease; }
.why-card:hover { transform: translateY(-4px); box-shadow: 0 16px 32px -18px rgba(14,47,92,.3); }
.why-card .icon { width: 1.85rem; height: 1.85rem; color: var(--gold-500); margin-bottom: .4rem; stroke-width: 1.4; }
.why-card__img-icon { object-fit: contain; margin: 0 auto .4rem; }
.why-card span { display: block; font-weight: 700; font-size: .78125rem; color: var(--navy-900); line-height: 1.3; }

.legacy-row { display: grid; grid-template-columns: 1fr; gap: 1rem; align-items: center; margin-top: .85rem; }
@media (min-width: 48em) { .legacy-row { grid-template-columns: 10rem 1fr; gap: 1.5rem; } }
.legacy-row__media {
  border-radius: var(--radius-sm, .35rem); overflow: hidden; aspect-ratio: 3/2;
  filter: sepia(.35) saturate(1.1); box-shadow: 0 12px 24px -16px rgba(14,47,92,.3);
  border: 4px solid #fff; transition: transform .3s ease, box-shadow .3s ease;
}
.legacy-row__media:hover { transform: translateY(-6px) scale(1.03); box-shadow: 0 20px 32px -14px rgba(14,47,92,.4); }
.legacy-row__media img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Leaf decorations flanking the whole Why St. Anne's + Legacy section.
   Same reusable "colored mask of the transparent leaf art" technique as
   .testimonial-leaf: background-color tints the shape, so it can be any
   color without a separate pre-tinted image asset. Positioned on
   .section--why itself (which has no inline padding, so left:0/right:0 is
   already the true page edge, no vw-bleed math needed) rather than inside
   .why-band or the legacy .container, so one pair of leaves reads as
   flanking the section as a whole instead of just one sub-block.
   Color is a manually darkened step below --cream-deep (itself already
   "slightly darker than --cream") — darkened further per instruction, kept
   as a literal hex rather than a new :root token since it's only used here.
   z-index:0 — below both .container elements (z-index:1), so on the right
   this leaf renders entirely behind the why-cards/legacy-row content: an
   opaque card or photo fully occludes whatever part of the leaf is behind
   it, so the "Values-Based Education" card sitting in front of the leaf
   there is enough on its own, no size/position change needed for it. On
   the left, .why-copy's heading/paragraph have no background fill, so
   being merely behind the leaf wouldn't hide the overlap the same way —
   text would render with leaf tint visible around the letters — so
   .why-copy itself is shifted right instead (see its margin-left, desktop
   only) to clear the leaf's actual opaque art, which — per instruction —
   is restored to 7.5rem here (the source art fills 0%-80.6% of its own
   image width, so at 7.5rem the visible leaf reaches ~97px from the page
   edge; re-measure that if this width changes again). */
.section--why__leaf {
  position: absolute; top: 50%; width: 7.5rem; aspect-ratio: 784 / 1351;
  background-color: #D0C6B8; opacity: .45;
  -webkit-mask-image: url("../img/l1-white.83ae9c820ac9.png"); mask-image: url("../img/l1-white.83ae9c820ac9.png");
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-position: center; mask-position: center;
  pointer-events: none; z-index: 0;
}
.section--why__leaf--left { left: 0; transform: translateY(-50%); }
.section--why__leaf--right { right: 0; transform: translateY(-50%) scaleX(-1); }
.legacy-row__head h3 { font-family: var(--font-display); font-size: clamp(1.15rem, 1rem + .9vw, 1.5rem); line-height: 1.2; color: var(--navy-900); margin-bottom: .2rem; }
.legacy-row__head p { color: var(--slate-600); font-size: .9rem; margin-bottom: .9rem; }
@media (min-width: 56em) {
  .legacy-row__head p { font-size: .8rem; }
}
.timeline { display: grid; grid-template-columns: repeat(2, 1fr); gap: .85rem 1rem; position: relative; }
@media (min-width: 40em) { .timeline { grid-template-columns: repeat(4, 1fr); } }
.timeline::before { content: ''; position: absolute; top: 6px; left: 0; right: 0; height: 2px; background: linear-gradient(to right, var(--gold-300, var(--gold-500)) 0%, var(--gold-300, var(--gold-500)) 50%, transparent 100%); display: none; }
@media (min-width: 40em) { .timeline::before { display: block; } }
.timeline__item { position: relative; padding-top: 1.5rem; }
.timeline__item::before { content: ''; position: absolute; top: 0; left: 0; width: 14px; height: 14px; border-radius: 999px; background: var(--gold-500); border: 3px solid var(--off-white); }
.timeline__year { font-family: var(--font-display); font-weight: 700; color: var(--navy-900); display: block; }
.timeline__label { display: block; font-size: .8125rem; color: var(--slate-600); }
.timeline__item:nth-child(3) .timeline__label { max-width: 9.5rem; }
.timeline__item:nth-child(4) .timeline__label { max-width: 13.5rem; }

/* ---------- Academic Programmes ---------- */
.section--academics { background: var(--pale-blue); overflow: hidden; padding-block: clamp(.5rem, 1vw, .75rem); }
.section--academics__leaf { position: absolute; left: 0; bottom: 0; width: 5.4rem; height: auto; max-width: none; opacity: .4; pointer-events: none; z-index: 0; }
.section--academics .container { position: relative; z-index: 1; }
.academics-grid { display: grid; grid-template-columns: 1fr; gap: 1rem; align-items: center; }
@media (min-width: 64em) { .academics-grid { grid-template-columns: .7fr 1.3fr; gap: .1rem; } }
.programme-copy { position: relative; padding-left: 3rem; align-self: start; margin-top: 1.5rem; }
.programme-copy__deco { position: absolute; inset: 0; pointer-events: none; z-index: 0; overflow: visible; }
.programme-copy__triangle-sm { position: absolute; left: -2.25rem; top: 2.5rem; width: 3.5rem; height: 3.5rem; }
.programme-copy .eyebrow,
.programme-copy h2,
.programme-copy p,
.programme-copy .btn { position: relative; z-index: 1; }
.programme-copy .eyebrow { justify-content: flex-start; }
.eyebrow__navy { color: var(--navy-800); }
.programme-copy h2 { font-size: clamp(1.15rem, 1rem + .9vw, 1.5rem); line-height: 1.2; margin-bottom: .4rem; }
.programme-copy p:not(.eyebrow) { color: var(--slate-600); font-size: .9rem; margin-bottom: .75rem; max-width: 26rem; }
.programme-copy p.programme-copy__lead { max-width: 18rem; }
@media (min-width: 56em) {
  .programme-copy p:not(.eyebrow) { font-size: .8rem; }
}
.programme-showcase { position: relative; display: grid; grid-template-columns: 1fr; gap: .75rem; }
@media (min-width: 40em) { .programme-showcase { grid-template-columns: 1.3fr 1fr; } }
.programme-feature { position: relative; background: #fff; padding: .4rem; border-radius: var(--radius-lg); aspect-ratio: 4/2.7; box-shadow: 0 30px 60px -30px rgba(14,47,92,.35); transform: rotate(-1.75deg); transition: transform .3s ease, box-shadow .3s ease; }
.programme-feature__triangle-wrap { position: absolute; left: -11.2rem; bottom: 0rem; width: 15.5rem; height: 10.5rem; z-index: 0; transform-origin: top; transform: scaleY(1.1); }
.programme-feature__triangle-lg { width: 100%; height: 100%; transform: rotate(270deg); }
.programme-feature:hover { transform: rotate(0deg) translateY(-6px); box-shadow: 0 40px 70px -25px rgba(14,47,92,.5); }
.programme-feature__frame { position: relative; width: 100%; height: 100%; border-radius: calc(var(--radius-lg) - .25rem); overflow: hidden; background: var(--navy-800); }
.programme-feature .ph { position: absolute; inset: 0; }
.programme-feature__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; transform: scale(1.2); transition: transform .5s ease; }
.programme-feature:hover .programme-feature__img { transform: scale(1.3); }
.programme-feature__frame::after { content: ''; position: absolute; inset: 0; background: linear-gradient(180deg, transparent 40%, rgba(9,30,50,.92)); }
.programme-feature__body { position: absolute; left: 0; bottom: 0; right: 0; padding: .85rem; color: #fff; z-index: 1; }
.programme-feature__num { font-family: var(--font-display); font-size: 1.5rem; color: var(--gold-400); font-weight: 700; display: block; line-height: 1; }
.programme-feature__body h3 { font-size: 1.05rem; margin: .1rem 0 .35rem; color: #fff; }
.programme-feature__body ul { list-style: none; margin: 0; padding: 0; font-size: .8125rem; color: rgba(255,255,255,.8); display: flex; flex-wrap: wrap; gap: .25rem .6rem; }
.programme-list { display: flex; flex-direction: column; gap: .75rem; }
.programme-list__item { display: flex; height: 5.4rem; padding: .3rem; background: #fff; border-radius: var(--radius-md); box-shadow: 0 16px 32px -20px rgba(14,47,92,.3); transform: rotate(-1.25deg); transition: transform .25s ease, box-shadow .25s ease; }
.programme-list__item:hover { transform: rotate(0deg) translateY(-4px); box-shadow: 0 22px 40px -18px rgba(14,47,92,.45); }
.programme-list__frame { display: flex; width: 100%; height: 100%; border-radius: calc(var(--radius-md) - .2rem); overflow: hidden; background: var(--navy-800); }
.programme-list__item:nth-child(1) .programme-list__frame { background: var(--navy-800); }
.programme-list__item:nth-child(2) .programme-list__frame { background: var(--navy-600); }
.programme-list__item:nth-child(3) .programme-list__frame { background: #2f6fb0; }
.programme-list__item .ph { width: 42%; flex-shrink: 0; }
.programme-list__img { width: 42%; height: 100%; flex-shrink: 0; object-fit: cover; display: block; transition: transform .45s ease; }
.programme-list__item:hover .programme-list__img { transform: scale(1.1); }
.programme-list__body { padding: .65rem 1rem; color: #fff; flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; }
.programme-list__num { font-family: var(--font-display); font-weight: 700; color: var(--gold-400); font-size: .9rem; }
.programme-list__body h4 { font-size: 1rem; margin: .15rem 0 .35rem; color: #fff; }
.programme-list__body a { font-size: .75rem; color: rgba(255,255,255,.85); display: inline-flex; align-items: center; gap: .25rem; transition: gap .25s ease, color .25s ease; }
.programme-list__body a .icon { transition: transform .25s ease; }
.programme-list__item:hover .programme-list__body a { color: #fff; gap: .5rem; }
.programme-list__item:hover .programme-list__body a .icon { transform: translateX(3px); }

/* ---------- Facilities ---------- */
.section--facilities { background: linear-gradient(90deg, #fff 0%, var(--pale-blue) 100%); overflow: hidden; position: relative; }
.section--facilities .container { position: relative; z-index: 1; }
.section--facilities__leaf { position: absolute; top: 0; width: 6rem; height: auto; max-width: none; opacity: .4; pointer-events: none; z-index: 0; }
.section--facilities__leaf--left { left: 0; }
.section--facilities__leaf--right { right: 0; transform: scaleX(-1); }
.facilities-grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: center; }
@media (min-width: 64em) { .facilities-grid { grid-template-columns: .75fr 1.25fr; gap: 2.5rem; } }
.facilities-copy .eyebrow { justify-content: flex-start; }
.facilities-copy h2 { font-size: clamp(1.15rem, 1rem + .9vw, 1.5rem); line-height: 1.2; margin-bottom: .6rem; }
.facilities-copy p:not(.eyebrow) { color: var(--slate-600); font-size: .9rem; margin-bottom: 1.25rem; max-width: 26rem; }
@media (min-width: 56em) {
  .facilities-copy p:not(.eyebrow) { font-size: .8rem; }
}
.facility-strip { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem; }
@media (min-width: 40em) { .facility-strip { grid-template-columns: repeat(4, 1fr); } }
.facility-tile { display: flex; flex-direction: column; background: #fff; border-radius: var(--radius-md); overflow: hidden; box-shadow: 0 12px 28px -16px rgba(14,47,92,.25); transition: transform .3s ease, box-shadow .3s ease; }
.facility-tile:hover { transform: translateY(-6px); box-shadow: 0 24px 44px -18px rgba(14,47,92,.45); }
.facility-tile__photo { position: relative; aspect-ratio: 1; overflow: hidden; }
.facility-tile .ph { position: absolute; inset: 0; }
.facility-tile__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .5s ease; }
.facility-tile:hover .facility-tile__img { transform: scale(1.08); }
.facility-tile__cap {
    display: flex; align-items: center; gap: .5rem; padding: .75rem .85rem;
    font-size: .8125rem; font-weight: 700; color: var(--navy-900);
}
.facility-tile__cap .icon-wrap { width: 1.75rem; height: 1.75rem; border-radius: 999px; background: var(--gold-100); color: var(--gold-600); display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; transition: background-color .3s ease, color .3s ease; }
.facility-tile__cap .icon-wrap .icon { width: 1rem; height: 1rem; }
.facility-tile:hover .facility-tile__cap .icon-wrap { background: var(--gold-500); color: var(--navy-900); }

/* ---------- More Than the Classroom ---------- */
.section--life { background: var(--navy-900); color: #fff; overflow: hidden; }
.life-row { display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: center; }
@media (min-width: 56em) { .life-row { grid-template-columns: auto 1fr; gap: 2.5rem; } }
.life-copy h2 { font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem); margin-bottom: .4rem; color: #fff; }
.life-copy p { color: rgba(255,255,255,.65); font-size: .8125rem; margin-bottom: 1.1rem; text-transform: uppercase; letter-spacing: .08em; }
.life-strip { display: grid; grid-template-columns: repeat(3, 1fr); gap: .85rem; }
@media (min-width: 40em) { .life-strip { grid-template-columns: repeat(6, 1fr); } }
.life-tile { display: flex; flex-direction: column; background: var(--navy-900); border: 1px solid rgba(255,255,255,.12); border-radius: var(--radius-sm); overflow: hidden; box-shadow: 0 12px 24px -14px rgba(0,0,0,.4); transition: transform .3s ease, box-shadow .3s ease; }
.life-tile:hover { transform: translateY(-4px); box-shadow: 0 18px 32px -14px rgba(0,0,0,.5); }
.life-tile__photo { position: relative; aspect-ratio: 1; overflow: hidden; }
.life-tile__photo.ph { width: auto; min-height: 0; }
.life-tile__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .5s ease; }
.life-tile:hover .life-tile__img { transform: scale(1.08); }
.life-tile__label { flex: 1; display: flex; align-items: center; padding: .4rem .55rem; font-size: .7rem; font-weight: 700; color: #fff; text-align: left; background: linear-gradient(90deg, var(--navy-600), var(--navy-800)); }

/* ---------- Latest News ---------- */
.section--news { background: var(--off-white); overflow: hidden; }
.section--news__bleed { display: none; }
@media (min-width: 56em) {
  .section--news { display: grid; grid-template-columns: minmax(13rem, 18%) 1fr; align-items: stretch; }
  .section--news__bleed {
    display: block; width: 100%; height: calc(100% + 3rem); margin-top: -1.5rem; margin-bottom: -1.5rem; object-fit: cover; object-position: center 15%;
    -webkit-mask-image: linear-gradient(to right, #000 75%, transparent 100%);
    mask-image: linear-gradient(to right, #000 75%, transparent 100%);
  }
  .section--news .container { margin-inline: 0 auto; padding-left: 2rem; }
}
.news-grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; }
@media (min-width: 56em) { .news-grid { grid-template-columns: .7fr 1fr 1fr; gap: 2rem; align-items: start; } }
.news-copy { align-self: center; }
.news-copy .eyebrow { justify-content: flex-start; }
.news-copy h2 { font-size: clamp(1.15rem, 1rem + .9vw, 1.5rem); line-height: 1.2; margin-bottom: .6rem; }
.news-copy p:not(.eyebrow) { color: var(--slate-600); font-size: .9rem; margin-bottom: 1.25rem; max-width: 13.125rem; }
@media (min-width: 56em) {
  .news-copy p:not(.eyebrow) { font-size: .8rem; }
}
.news-feature { position: relative; border-radius: var(--radius-lg); overflow: hidden; aspect-ratio: 4/3; box-shadow: 0 24px 48px -24px rgba(14,47,92,.35); transition: transform .3s ease, box-shadow .3s ease; }
@media (min-width: 56em) { .news-feature { aspect-ratio: auto; align-self: stretch; } }
.news-feature:hover { transform: translateY(-6px); box-shadow: 0 32px 60px -22px rgba(14,47,92,.5); }
/* Auto-advancing crossfade between slides — same technique as .hero__layer
   (opacity-only, absolutely stacked, one .is-active at a time), so the
   outer .news-feature box itself (size/position/aspect-ratio/shadow set
   above) never changes; only what's painted inside it does. */
.news-feature__track { position: absolute; inset: 0; }
/* No z-index here (unlike .hero__layer) — .news-feature::after's darkening
   gradient and .news-feature__more's arrow button both need to keep
   painting on top of the slide images exactly as they did with the single
   static image before, and giving the active slide a z-index would jump
   it above the gradient (a plain z-index:auto element) too. Opacity alone
   is enough for the crossfade — an opacity:0 slide is invisible regardless
   of paint order. */
.news-feature__slide { position: absolute; inset: 0; opacity: 0; pointer-events: none; transition: opacity 1s ease; }
.news-feature__slide.is-active { opacity: 1; pointer-events: auto; }
.news-feature .ph { position: absolute; inset: 0; }
.news-feature__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .5s ease; }
.news-feature:hover .news-feature__img { transform: scale(1.08); }
.news-feature::after { content: ''; position: absolute; inset: 0; background: linear-gradient(180deg, transparent 35%, rgba(9,30,50,.92)); transition: background .3s ease; }
.news-feature:hover::after { background: linear-gradient(180deg, transparent 20%, rgba(9,30,50,.95)); }
.news-feature__body { position: absolute; left: 0; right: 0; bottom: 0; padding: 1.25rem; color: #fff; z-index: 1; }
.news-feature__date { font-size: .75rem; color: var(--gold-400); font-weight: 600; }
.news-feature__body h3 { font-size: 1.15rem; margin: .35rem 2.5rem .1rem 0; color: #fff; }
.news-feature__more {
    position: absolute; right: 1rem; bottom: 1rem; z-index: 2; width: 2.5rem; height: 2.5rem; border-radius: 999px;
    background: var(--gold-500); color: var(--navy-900); display: inline-flex; align-items: center; justify-content: center;
    transition: transform .3s ease, background-color .3s ease;
}
.news-feature:hover .news-feature__more { transform: scale(1.1); background: #fff; }
.news-list { display: flex; flex-direction: column; gap: .85rem; }
.news-item { display: flex; gap: .85rem; align-items: center; background: #fff; border: 1px solid var(--navy-50); border-radius: var(--radius-md); padding: .6rem; transition: box-shadow .25s ease, transform .25s ease; }
.news-item:hover { box-shadow: 0 12px 28px -18px rgba(14,47,92,.3); transform: translateY(-2px); }
.news-item__thumb { display: block; width: 5.25rem; height: 3.5rem; border-radius: var(--radius-sm); overflow: hidden; flex-shrink: 0; background: var(--navy-50); }
.news-item__img { width: 100%; height: 100%; object-fit: cover; object-position: center; display: block; }
.news-item__body { flex: 1; min-width: 0; }
.news-item__date { font-size: .7rem; color: var(--gold-600); font-weight: 600; }
.news-item__title { font-size: .775rem; font-weight: 600; color: var(--navy-900); display: flex; align-items: center; gap: .4rem; justify-content: space-between; }

/* ---------- Gallery: Moments That Matter ---------- */
.section--gallery { padding-block: 0; overflow: hidden; }
.gallery-banner { display: grid; grid-template-columns: 1fr; }
@media (min-width: 56em) { .gallery-banner { grid-template-columns: .85fr 1.05fr .7fr; } }
.gallery-banner__feature {
  position: relative; background: var(--navy-900); color: #fff;
  padding: clamp(1rem, 2vw, 1.5rem) clamp(1.5rem, 4vw, 2.5rem) clamp(1rem, 2vw, 1.5rem) clamp(2.25rem, 5vw, 4.25rem);
  display: flex; flex-direction: column; justify-content: center; overflow: hidden;
}
.gallery-banner__feature .gallery-banner__feature-leaf {
  /* Two copies share the same tight corner budget (card bottom to the
     button top), so each is sized to half of it: this card's own
     overflow:hidden/clip-path and the section's overflow:hidden (needed
     for the photo slider) all clip anything that bleeds past this box,
     so neither copy can safely be much bigger than this. */
  position: absolute; left: 0; bottom: 0; width: 3.75rem; height: auto; max-width: none;
  opacity: .35; pointer-events: none; z-index: 0;
}
.gallery-banner__feature .gallery-banner__feature-leaf--top { bottom: 6.53rem; }
@media (min-width: 56em) {
  /* Explicit grid-column/row here (matching the feather pseudo-element
     below) so both share cell (1,1) as explicitly-placed items — without
     this, the feather's own explicit placement would get locked in first
     and the auto-placement algorithm would skip that cell for this
     (otherwise auto-positioned) panel, shoving it and its siblings out of
     their normal columns. */
  .gallery-banner__feature { grid-column: 1; grid-row: 1; clip-path: polygon(0 0, 82% 0, 100% 100%, 0 100%); padding-right: clamp(2.5rem, 6vw, 4rem); margin-right: -4rem; z-index: 2; }

  /* Soft feather where the feature panel's diagonal edge meets the photo:
     a thin, 52px-wide navy-to-transparent parallelogram parallel to the
     clip-path line above (it doesn't change that clip-path at all, just
     adds a translucent bleed past it). The box is pulled in from the left
     with margin-left (82% + 0.82 * the panel's own 4rem bleed) so it
     starts exactly at the panel's diagonal corner and is only as wide as
     the feather itself — not the full bled panel width — so the gradient
     lands on the visible band instead of mostly being wasted gradient on
     the clipped-away area next to it (an earlier version spanned the
     whole panel width, which pushed the visible band into the gradient's
     already-fully-transparent tail — that's why it wasn't visible at all
     at first). Reuses the panel's own bleed technique (a grid item
     stretched to its track, pulled with margins) rather than absolute
     positioning, so it shares the exact same track/row box as the panel:
     it cannot extend below this row, and never touches the photo
     slider's own box/left edge. */
  .gallery-banner::after {
    content: "";
    display: block;
    grid-column: 1; grid-row: 1;
    margin-left: calc(82% + 52.48px);
    margin-right: -74px;
    clip-path: polygon(0 0, 20px 0, 100% 100%, calc(100% - 20px) 100%);
    background: linear-gradient(76deg, rgba(10, 36, 56, .75) 25%, rgba(10, 36, 56, 0) 75%);
    pointer-events: none;
    z-index: 2;
  }
}
.gallery-banner__feature .ph { position: absolute; inset: 0; opacity: .3; }
.gallery-banner__feature > * { position: relative; z-index: 1; }
.gallery-banner__feature h2 { font-size: clamp(1.15rem, 1rem + .9vw, 1.5rem); line-height: 1.2; margin-bottom: .4rem; color: #fff; }
.gallery-banner__feature p:not(.eyebrow) { color: rgba(255,255,255,.75); font-size: .9rem; margin-bottom: .85rem; max-width: 26rem; }
@media (min-width: 56em) {
  .gallery-banner__feature p:not(.eyebrow) { font-size: 1rem; max-width: 20.25rem; }
}
.gallery-banner__feature .btn { padding: .35rem .8rem; font-size: .7rem; gap: .3rem; align-self: flex-start; }

.gallery-banner__photo { position: relative; overflow: hidden; display: none; }
@media (min-width: 56em) {
  .gallery-banner__photo { display: block; margin-left: -8%; }
}
.gallery-banner__photo .ph { position: absolute; inset: 0; }
.gallery-banner__photo-track { position: absolute; inset: 0; display: flex; width: 100%; height: 100%; transition: transform .6s ease; }
.gallery-banner__slide { position: relative; flex: 0 0 100%; width: 100%; height: 100%; }
.gallery-banner__slide .ph { position: absolute; inset: 0; }
.gallery-banner__slide-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }

.gallery-banner__grid {
  /* Even 2x2 mosaic with only mildly uneven column/row fr sizes (no full
     row/column spans) — every tile stays landscape/near-square so the
     source photos crop naturally instead of being stretched into a tall
     portrait strip. Fixed height matches the previous 3-row total
     (3 * 6.25rem + 2 * .75rem) so this column's height is unchanged. */
  display: grid; grid-template-columns: 1.1fr .9fr; grid-template-rows: 1.05fr .95fr; gap: .75rem; height: 20.25rem;
}
@media (min-width: 56em) { .gallery-banner__grid { margin-left: .75rem; } }
.gallery-banner__grid .ph { aspect-ratio: 4/2.3; }
.gallery-banner__grid-img {
  width: 100%; height: 100%; object-fit: cover; border-radius: 0;
  border: 3px solid #fff; box-shadow: 0 8px 20px -12px rgba(14,47,92,.4);
  transition: transform .3s ease, box-shadow .3s ease; cursor: pointer;
  position: relative;
}
.gallery-banner__grid-img--tl { grid-column: 1; grid-row: 1; transform: rotate(-2deg); }
.gallery-banner__grid-img--tr { grid-column: 2; grid-row: 1; transform: rotate(2.5deg); }
.gallery-banner__grid-img--bl { grid-column: 1; grid-row: 2; transform: rotate(2deg); }
.gallery-banner__grid-img--br { grid-column: 2; grid-row: 2; transform: rotate(-2.5deg); }
.gallery-banner__grid-img--tl:hover,
.gallery-banner__grid-img--tr:hover,
.gallery-banner__grid-img--bl:hover,
.gallery-banner__grid-img--br:hover { transform: rotate(0deg) scale(1.08); box-shadow: 0 18px 32px -12px rgba(14,47,92,.55); z-index: 2; }

/* ---------- Testimonial + CTA ---------- */
.testimonial-leaf { display: none; }
@media (min-width: 56em) {
  /* Desktop (2-column) only — at the single-column mobile layout the
     testimonial card and CTA stack vertically, so "the section's bottom
     edge" no longer lines up with the testimonial card's own bottom edge
     specifically. Positioned on .section itself (not inside
     .testimonial-card, which has overflow:hidden for its slider) so it can
     reach the true page edge instead of being clipped at the card's own
     left edge; .section has no inline padding of its own, so left:0 here
     already is the page edge, no vw-bleed math needed. The bottom offset
     matches .section's own padding-block so the leaf's bottom lines up
     with the (stretch-matched) card/grid bottom edge exactly. */
  .testimonial-leaf {
    display: block; position: absolute; left: 0; bottom: clamp(1rem, 2.5vw, 1.5rem);
    width: 5rem; aspect-ratio: 784 / 1351;
    background-color: var(--navy-100);
    -webkit-mask-image: url("../img/l1-white.83ae9c820ac9.png"); mask-image: url("../img/l1-white.83ae9c820ac9.png");
    -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
    -webkit-mask-size: contain; mask-size: contain;
    -webkit-mask-position: bottom left; mask-position: bottom left;
    pointer-events: none;
  }
}
.testimonial-cta { display: grid; grid-template-columns: 1fr; gap: 1.5rem; position: relative; }
@media (min-width: 56em) {
  .testimonial-cta { grid-template-columns: 1fr 1fr; gap: 2.5rem; align-items: stretch; }
  /* Vertical divider between the testimonial and CTA columns, centered in
     the grid gap. Desktop only — at the single-column mobile stack the two
     cards are no longer side by side, so there's no gap to put a vertical
     line in. Same soft-fade-at-both-ends technique and color (--navy-100)
     as .divider's horizontal line, just rotated to vertical and spanning
     the row's own stretched height instead of a fixed margin. */
  .testimonial-cta::before {
    content: ''; position: absolute; top: 0; bottom: 0; left: 50%; transform: translateX(-50%);
    width: 2px;
    background: linear-gradient(to bottom, transparent, var(--navy-100) 15%, var(--navy-100) 85%, transparent);
    pointer-events: none;
  }
}
.testimonial-card { position: relative; height: 100%; overflow: hidden; }
.testimonial-card__track { display: flex; height: 100%; transition: transform .6s ease; }
.testimonial-card__slide {
  /* Padding lives here (not on .testimonial-card) so the slide's own edge,
     not the padding edge, is what overflow:hidden clips against — otherwise
     a sliver of the next slide bleeds into the card's own padding area. */
  flex: 0 0 100%; width: 100%; box-sizing: border-box; padding: 1.5rem;
  display: flex; flex-direction: column; gap: 1rem;
}
@media (min-width: 40em) { .testimonial-card__slide { flex-direction: row; align-items: flex-start; gap: 1.5rem; } }
.testimonial-card .eyebrow { justify-content: flex-start; }
.testimonial-card__photo { width: 8rem; height: 8rem; border-radius: 999px; overflow: hidden; flex-shrink: 0; border: 3px solid var(--gold-100); }
.testimonial-card__photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.testimonial-card__quote { font-family: var(--font-display); font-style: italic; color: var(--slate-600); line-height: 1.5; margin-bottom: .75rem; }
.testimonial-card__name { font-weight: 700; color: var(--navy-900); display: inline-flex; align-items: center; gap: .35rem; }
.testimonial-card__meta { color: var(--slate-600); font-size: .8125rem; }
.cta-card {
  position: relative; overflow: hidden; color: #fff; padding: 1.5rem;
  display: flex; flex-direction: column; justify-content: center; min-height: 12rem;
  box-shadow: 0 24px 48px -24px rgba(14,47,92,.4);
  /* Only the top edge is angled (was a notched-corner polygon that hid part
     of building.png — replaced with a full rectangle, then this subtle
     top-only slope added per the reference screenshot). Left/right edges
     stay perfectly vertical (both corners pinned to x:0%/100%) and the
     bottom edge is untouched (both bottom corners at y:100%) — only the
     top-left corner drops to 4% down while the top-right stays at 0%, a
     ~4% linear rise across the full width. That's a gentle slope, not a
     skew of the whole card (card's own box/width/height/content are
     unaffected; clip-path is purely a visual crop). */
  clip-path: polygon(0% 4%, 100% 0%, 100% 100%, 0% 100%);
}
@media (min-width: 56em) {
  .cta-card { margin-right: calc(-1 * max(1rem, (100vw - var(--container)) / 2)); }
}
.cta-card .ph { position: absolute; inset: 0; }
.cta-card .cta-card__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: right center; z-index: 0; }
.cta-card::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, var(--navy-900) 0%, rgba(10,36,56,.94) 32%, rgba(10,36,56,.55) 58%, rgba(10,36,56,0) 82%);
}
.cta-card > * { position: relative; z-index: 1; }
.cta-card .eyebrow { justify-content: flex-start; }
.cta-card h2 { font-size: clamp(1.25rem, 1.05rem + 1vw, 1.75rem); line-height: 1.2; margin-bottom: .5rem; color: #fff; }
.cta-card p { color: rgba(255,255,255,.8); margin-bottom: .85rem; max-width: 22rem; }
.cta-card .btn { align-self: flex-start; }

/* ---------- Footer ---------- */
.site-footer { background: var(--navy-900); color: rgba(255,255,255,.75); }
.footer__grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; padding-block: 1.5rem 1rem; }
@media (min-width: 40em) { .footer__grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 64em) { .footer__grid { grid-template-columns: 1.3fr repeat(5, 1fr) .85fr .65fr; gap: 1.5rem; } }
.footer__brand-col { grid-column: 1 / -1; }
@media (min-width: 40em) { .footer__brand-col { grid-column: 1 / 2; } }
@media (min-width: 64em) { .footer__brand-col { grid-column: auto; } }
.footer__brand { display: flex; align-items: center; gap: .75rem; margin-bottom: .6rem; }
.footer__crest { width: 56px; height: 56px; object-fit: contain; flex-shrink: 0; display: block; }
.footer__brand strong { font-family: var(--font-display); font-size: 1.05rem; color: #fff; display: block; letter-spacing: .02em; }
.footer__brand small { font-size: .68rem; color: rgba(255,255,255,.6); line-height: 1.3; display: block; margin-top: .1rem; }
.footer__tagline { font-family: var(--font-script); color: var(--gold-400); font-size: 1.2rem; margin: 0; }
.footer__heading { font-family: var(--font-body); font-weight: 700; font-size: .8125rem; color: #fff; margin-bottom: .85rem; }
.footer__links { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .55rem; font-size: .8125rem; color: rgba(255,255,255,.68); }
.footer__links a:hover { color: var(--gold-400); }
.footer__contact li { display: flex; align-items: flex-start; gap: .6rem; }
.footer__contact .icon { color: var(--gold-400); margin-top: .2em; }
.footer__bottom { border-top: 1px solid rgba(255,255,255,.12); }
.footer__bottom-row { display: flex; flex-direction: column; align-items: center; gap: .5rem; padding-block: 1rem; font-size: .75rem; color: rgba(255,255,255,.55); }
.footer__powered-by { display: inline-flex; align-items: center; gap: .4rem; margin: 0; }
.footer__powered-by-logo { height: 1.1rem; width: auto; display: inline-block; }
@media (min-width: 40em) { .footer__bottom-row { flex-direction: row; justify-content: space-between; } }

.social { list-style: none; display: flex; gap: .5rem; margin: 0; padding: 0; }
.social a { display: inline-flex; width: 2.1rem; height: 2.1rem; align-items: center; justify-content: center; border-radius: 999px; background: rgba(255,255,255,.1); color: #fff; }
.social a:hover { background: var(--gold-500); color: var(--navy-900); }

/* ---------- Breadcrumb ---------- */
.breadcrumb { font-size: .875rem; padding-block: .75rem; background: var(--navy-50); }
.breadcrumb ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: .4rem; }
.breadcrumb li + li::before { content: '›'; margin-right: .4rem; color: var(--slate-600); }

/* ---------- Cards (blog) ---------- */
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 18rem), 1fr)); gap: 1.5rem; }
.card { border: 1px solid var(--navy-50); border-radius: var(--radius-sm); background: #fff; }
.card__body { padding: 1.25rem; }
.card__title { font-size: 1.125rem; margin: .25rem 0 .5rem; }
.meta { color: var(--slate-600); font-size: .875rem; }

/* ---------- Forms ---------- */
.form-field { display: flex; flex-direction: column; gap: .3rem; margin-bottom: 1rem; }
.form-field label { font-weight: 600; }
.form-field input, .form-field textarea {
    font: inherit; padding: .6rem .75rem; border: 1px solid var(--navy-100); border-radius: 8px; width: 100%;
}
.form-notice { padding: .75rem 1rem; border-radius: 8px; border: 1px solid; margin-bottom: 1rem; }
.form-notice--success { color: #15803d; border-color: currentColor; background: #f0fdf4; }

/* ---------- Boosted navigation progress bar ---------- */
#page-progress { position: fixed; top: 0; left: 0; height: 3px; width: 0; background: var(--gold-500); z-index: 1001; transition: width .3s ease; }
html.is-navigating #page-progress { width: 80%; }

/* ---------- Floating scroll-to-top / scroll-to-footer control ----------
   Fixed to the viewport (not any section), so it's unaffected by and
   doesn't affect the layout/spacing of page content. z-index:90 — above
   ordinary page content (nothing outside the header goes above 5) but
   below the header (100) and #page-progress (1001), so it can never
   visually block either of those. Round (border-radius:999px) with the
   same gold fill as .btn--gold (the "Explore Our School" CTA in the CTA
   card) — color/shape matched to that button per instruction. */
.scroll-nav {
  position: fixed; right: 1.5rem; bottom: 1.5rem; z-index: 90;
  display: flex; flex-direction: column; gap: .5rem;
}
.scroll-nav__btn {
  width: 2.75rem; height: 2.75rem; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--gold-500); border: none; border-radius: 999px;
  color: var(--navy-900); box-shadow: 0 8px 20px -10px rgba(14,47,92,.35);
  cursor: pointer;
  transition: opacity .3s ease, transform .2s ease, box-shadow .2s ease, background-color .2s ease;
}
.scroll-nav__btn .icon { width: 1.1rem; height: 1.1rem; }
/* Shared "chevron" icon (used elsewhere for dropdown carets) points down by
   default — flipped for the up button instead of adding a second SVG. */
.scroll-nav__btn--up .icon { transform: rotate(180deg); }
.scroll-nav__btn:hover { background: var(--gold-600); transform: translateY(-2px); box-shadow: 0 14px 26px -10px rgba(14,47,92,.4); }
.scroll-nav__btn:active { transform: translateY(0); box-shadow: 0 6px 14px -8px rgba(14,47,92,.35); }
/* Context-aware visibility: toggled by app.js based on scroll position.
   Opacity/transform fade (not display:none) per instruction — stays a
   layout box (so the other button doesn't jump), just visually and
   interactively disabled while faded. */
.scroll-nav__btn.is-hidden { opacity: 0; transform: translateY(6px); pointer-events: none; }
@media (max-width: 40em) {
  /* Slightly smaller + tighter spacing than desktop, per instruction —
     still a comfortable tap target (42px, above the ~40px common minimum),
     just not as roomy as desktop's 44px + 1.5rem margins. */
  .scroll-nav { right: 1rem; bottom: 1rem; gap: .4rem; }
  .scroll-nav__btn { width: 2.625rem; height: 2.625rem; }
  .scroll-nav__btn .icon { width: 1rem; height: 1rem; }
}
