:root {
  --body-font-family: "Noto Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --heading-font-family: "Epilogue", system-ui, -apple-system, "Segoe UI", sans-serif;
  --cursive-font-family: "Caveat", "Segoe Script", cursive;

  /* Brand accents */
  --color-primary: #6f47e4;   /* violet -- buttons, active nav, links */
  --color-accent: #f7c948;    /* gold -- badges, highlights, CTA chips */
  --color-success: #34c98a;   /* green -- stat/fact accent */

  /* Text & dark surfaces */
  --color-navy: #111a3f;      /* headings */
  --color-dark: #171e2e;      /* dark text, dark backgrounds */
  --color-darker: #0f141f;    /* darkest -- hover states, deep backgrounds */
  --color-slate: #2f394d;     /* borders on dark backgrounds */
  --color-body: #5a6080;      /* base body copy */
  --color-muted: #6f7590;     /* secondary/muted text */

  /* Light surfaces */
  --color-border: #e6e5f0;    /* light dividers/borders */
  --color-bg-soft: #f6f5fb;   /* light section background */
  --color-white: #ffffff;
  --color-black: #000000;

  /* Primary tints -- lavender-tinted surfaces (badges, section backgrounds) */
  --color-tint-bg: #f8f7fd;
  --color-tint-chip: #ece9fb;
  --color-tint-border: #e4e1f5;
}

@font-face {
  font-family: "Noto Sans";
  src: url("../font/noto-sans-400-700-latin.woff2") format("woff2-variations");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Epilogue";
  src: url("../font/epilogue-600-800-latin.woff2") format("woff2-variations");
  font-weight: 600 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Caveat";
  src: url("../font/caveat-700-latin.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* The fluid scale lives on the root, not on body, because nearly every
   font-size in this theme is written in rem — and rem measures from <html>.
   With the clamp on body those rem sizes ignored it completely and stayed
   pinned to the browser's 16px at every width, so a card's 0.875rem read
   the same 14px on a 360px phone as on a 1440px monitor while the body copy
   around it scaled. Moving it here makes the whole type scale move together.

   13px holds from phones up to about 866px wide, then 1.5vw takes over and
   the whole scale grows with the window, reaching 17px at roughly 1133px. */
html {
  font-size: clamp(13px, 1.5vw, 17px);
}

body {
  margin: 0;
  font-family: var(--body-font-family);
  font-size: 1rem;
  line-height: 1.7;
  color: var(--color-body);
  background: var(--color-white);
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  margin: 0 0 15px;
  font-family: var(--heading-font-family);
  color: var(--color-navy);
  line-height: 1.25;
}

p {
  margin: 0 0 15px;
}

a {
  color: var(--color-dark);
  text-decoration: none;
  transition: color 0.3s ease;
}
a:hover {
  color: var(--color-darker);
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}

ul,
ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

.container {
  width: 100%;
  max-width: 1320px;
  margin-inline: auto;
  padding-inline: clamp(10px,1.3vw,15px);
}

.common-heading {
  font-size: clamp(24px, 14px + 2.2vw, 48px);
}

.heading-wrap {
  margin-bottom: 3rem;
}

.heading-wrap.center {
  text-align: center;
  max-width: 800px;
  margin-left: auto;
  margin-right: auto;
}

.heading-top-text {
  display: inline-block;
  background: var(--color-tint-chip);
  color: var(--color-primary);
  padding: 8px 22px;
  line-height: 1.2;
  margin-bottom: 8px;
  border-radius: 50px;
  font-size: 12px;
}

.text-center {
  text-align: center;
}

/* =========================================================
   BUTTONS — the only place button styling is written.
   Pill with the label on the left and a circular arrow chip
   on the right. The chip is a translucent disc, so the same
   markup works on every fill without a second icon file.

   Markup is `theme-btn` plus at most one modifier:
     theme-btn             violet, the default action
     theme-btn dark        navy, the second action on a light ground
     theme-btn alt         transparent, outlined, for dark grounds
     theme-btn alt-yellow  gold, for the one action that has to
                           beat a navy band

   Every size clamps between a phone and a wide desktop, so no
   breakpoint has to restate padding, type or the chip.
   ========================================================= */
.theme-btn {
  display: inline-flex;
  align-items: center;
  gap: clamp(9px, 5px + 0.6vw, 14px);
  /* Tight on three sides so the chip sits inside the pill, not beside it;
     the label side carries the real padding. */
  padding: clamp(5px, 3px + 0.3vw, 7px);
  padding-left: clamp(18px, 12px + 1.1vw, 26px);
  border: 1px solid transparent;
  border-radius: 50px;
  font-family: var(--body-font-family);
  font-size: clamp(13px, 12.2px + 0.2vw, 15px);
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  cursor: pointer;
  background: var(--color-primary);
  color: var(--color-white);
  box-shadow: 0 14px 28px -14px rgba(111, 71, 228, 0.9);
  transition: background 0.3s ease, color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease, transform 0.3s ease;
}

/* Violet -> navy on hover, the flip from the reference design. */
.theme-btn:hover, .theme-btn:focus-visible {
  transform: translateY(-2px);
  background: var(--color-dark);
  color: var(--color-white);
  box-shadow: 0 14px 28px -14px rgba(23, 30, 46, 0.85);
}

/* The arrow chip. One clamp sizes it everywhere — it replaces a fixed 38px
   with a 34px phone override. */
.btn-icon {
  display: grid;
  place-items: center;
  width: clamp(32px, 20px + 1.6vw, 38px);
  height: clamp(32px, 20px + 1.6vw, 38px);
  flex: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.2);
  transition: background 0.3s ease, transform 0.3s ease;
}
.btn-icon .icon {
  /* A share of the chip rather than its own size, so the glyph rides the
     clamp above instead of needing a second one. */
  width: 60%;
  height: 60%;
  filter: brightness(0) saturate(100%) invert(100%) sepia(0%) saturate(21%) hue-rotate(19deg) brightness(103%) contrast(100%);
}
.theme-btn:hover .btn-icon, .theme-btn:focus-visible .btn-icon {
  transform: translate(2px, -2px);
}

/* Two labels for one button: the full wording, and a short one for phones
   where a pair of buttons shares the row and the long version breaks over
   two lines. Only ever one of them is in the document — display:none also
   takes the other out of the accessibility tree, so nothing is read twice. */
.btn-label-short {
  display: none;
}
@media (max-width: 575.98px) {
  .btn-label-full {
    display: none;
  }
  .btn-label-short {
    display: inline;
  }
}

/* ---- dark: the same pill already sitting on navy, hovering the other way. */
.theme-btn.dark {
  background: var(--color-dark);
  box-shadow: 0 14px 28px -14px rgba(23, 30, 46, 0.85);
}
.theme-btn.dark:hover, .theme-btn.dark:focus-visible {
  background: var(--color-primary);
  box-shadow: 0 14px 28px -14px rgba(111, 71, 228, 0.9);
}

/* ---- alt: outlined, for the second action on a dark ground. */
.theme-btn.alt {
  background: rgba(255, 255, 255, 0.06);
  color: var(--color-white);
  border-color: rgba(255, 255, 255, 0.4);
  box-shadow: none;
}
.theme-btn.alt .btn-icon {
  background: rgba(255, 255, 255, 0.14);
}
.theme-btn.alt:hover, .theme-btn.alt:focus-visible {
  background: var(--color-white);
  color: var(--color-dark);
  border-color: var(--color-white);
  box-shadow: none;
}
.theme-btn.alt:hover .btn-icon, .theme-btn.alt:focus-visible .btn-icon {
  background: rgba(23, 30, 46, 0.1);
}
/* filter:none would leave the arrow at raw #000 while the label sits at the
   brand ink — two different blacks in one button. */
.theme-btn.alt:hover .btn-icon .icon, .theme-btn.alt:focus-visible .btn-icon .icon {
  filter: brightness(0) saturate(100%) invert(6%) sepia(26%) saturate(2198%) hue-rotate(192deg) brightness(97%) contrast(88%);
}

/* ---- alt-yellow: gold fill, dark ink. Loud on purpose. */
.theme-btn.alt-yellow {
  background: var(--color-accent);
  color: var(--color-navy);
  box-shadow: 0 14px 28px -14px rgba(247, 201, 72, 0.85);
}
.theme-btn.alt-yellow .btn-icon {
  background: rgba(17, 26, 63, 0.14);
}
.theme-btn.alt-yellow .btn-icon .icon {
  filter: brightness(0) saturate(100%) invert(6%) sepia(26%) saturate(2198%) hue-rotate(192deg) brightness(97%) contrast(88%);
}
.theme-btn.alt-yellow:hover, .theme-btn.alt-yellow:focus-visible {
  background: var(--color-white);
  color: var(--color-navy);
  box-shadow: 0 14px 28px -14px rgba(0, 0, 0, 0.5);
}
/* =========================================================
   HEADER
   Three tiers: topbar (ticker) / brand row / sticky nav.
   The nav is the only tier that sticks, so the sticky offset
   stays exactly $header-h.
   ========================================================= */
.header {
  position: relative;
  z-index: 100;
  font-family: var(--body-font-family);
}

/* ---------- Topbar --------------------------------------------------- */
.topbar {
  background: var(--color-darker);
  color: rgba(255, 255, 255, 0.72);
  font-size: 13px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
}

.topbar-inner {
  display: flex;
  align-items: center;
  gap: 24px;
  min-height: 34px;
}

.ticker {
  display: flex;
  align-items: center;
  gap: 14px;
  flex: 1 1 auto;
  min-width: 0;
}

.ticker-label {
  flex: none;
  background: var(--color-accent);
  color: var(--color-dark);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 2px 12px;
  border-radius: 50px;
}

.ticker-viewport {
  position: relative;
  overflow: hidden;
  min-width: 0;
  flex: 1 1 auto;
  /* Fade the text out at both ends instead of clipping it hard. */
  -webkit-mask-image: linear-gradient(90deg, transparent, var(--color-black) 40px, var(--color-black) calc(100% - 40px), transparent);
  mask-image: linear-gradient(90deg, transparent, var(--color-black) 40px, var(--color-black) calc(100% - 40px), transparent);
}

.ticker-track {
  display: flex;
  align-items: center;
  gap: 42px;
  margin: 0;
  padding: 0;
  list-style: none;
  width: -moz-max-content;
  width: max-content;
  animation: ticker-scroll 44s linear infinite;
}
.ticker-track li {
  position: relative;
  white-space: nowrap;
}
.ticker-track li::before {
  content: "";
  position: absolute;
  left: -23px;
  top: 50%;
  width: 5px;
  height: 5px;
  margin-top: -2px;
  border-radius: 50%;
  background: var(--color-accent);
}
.ticker-track a {
  color: rgba(255, 255, 255, 0.78);
  text-decoration: none;
  transition: color 0.3s ease;
}
.ticker-track a:hover, .ticker-track a:focus-visible {
  color: var(--color-white);
}

.ticker:hover .ticker-track,
.ticker:focus-within .ticker-track {
  animation-play-state: paused;
}

@keyframes ticker-scroll {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(-50%, 0, 0);
  } /* list is printed twice */
}
.topbar-links {
  display: flex;
  align-items: center;
  gap: 18px;
  margin: 0;
  padding: 0;
  list-style: none;
  flex: none;
}
.topbar-links li + li {
  position: relative;
}
.topbar-links li + li::before {
  content: "";
  position: absolute;
  left: -9px;
  top: 3px;
  bottom: 3px;
  width: 1px;
  background: rgba(255, 255, 255, 0.18);
}
.topbar-links a {
  color: rgba(255, 255, 255, 0.7);
  text-decoration: none;
  font-size: 12.5px;
  transition: color 0.3s ease;
}
.topbar-links a:hover, .topbar-links a:focus-visible {
  color: var(--color-accent);
}

/* Social marks, moved here off the brand row. Small and quiet: on a strip
   this thin they are a signpost, not a call to action. */
.topbar-social {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: none;
  margin: 0;
  padding: 0;
  list-style: none;
}
.topbar-social a {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 6px;
  transition: background 0.3s ease;
}
.topbar-social a .icon {
  width: 14px;
  height: 14px;
  /* Source files are black, and this strip is nearly so. */
  filter: brightness(0) saturate(100%) invert(100%);
  opacity: 0.7;
  transition: opacity 0.3s ease;
}
.topbar-social a:hover, .topbar-social a:focus-visible {
  background: rgba(255, 255, 255, 0.1);
}
.topbar-social a:hover .icon, .topbar-social a:focus-visible .icon {
  opacity: 1;
}

/* ---------- Brand row ------------------------------------------------ */
.header-main {
  background: var(--color-white);
  padding: 16px 0;
}

.header-main-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

.logo {
  display: flex;
  align-items: center;
  gap: 14px;
  text-decoration: none;
  flex: none;
}
.logo img {
  width: 60px;
  height: 60px;
  -o-object-fit: contain;
     object-fit: contain;
}

.logo-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.logo-name {
  font-family: var(--heading-font-family);
  font-size: clamp(18px, 13px + 0.7vw, 24px);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.015em;
  color: var(--color-navy);
}

.logo-tagline {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-muted);
}

.header-meta {
  display: flex;
  align-items: center;
  gap: 18px;
}

.meta-item {
  display: flex;
  align-items: center;
  gap: 11px;
  flex: none;
  text-decoration: none;
  padding: 6px 0;
}
.meta-item:hover .meta-icon, .meta-item:focus-visible .meta-icon {
  background: var(--color-primary);
  border-color: var(--color-primary);
}

.meta-icon {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  flex: none;
  border-radius: 50%;
  background: var(--color-dark);
  border: 1px solid var(--color-dark);
  transition: background 0.3s ease, border-color 0.3s ease;
}
.meta-icon .icon {
  filter: brightness(0) saturate(100%) invert(100%) sepia(0%) saturate(21%) hue-rotate(19deg) brightness(103%) contrast(100%);
}

.meta-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  line-height: 1.2;
}

.meta-label {
  font-size: 11px;
  white-space: nowrap;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-primary);
}

.meta-value {
  font-size: 14.5px;
  font-weight: 600;
  white-space: nowrap;
  color: var(--color-navy);
}

/* Layout hook only -- the fill, the arrow chip and the hover flip all come
   from .theme-btn / .theme-btn in _buttons.scss. */
.erp-btn {
  flex: none;
}

/* ---------- Navbar --------------------------------------------------- */
/* A body-level sibling of <header>, not a child -- see include/header.php.
   Sticky is clamped to the containing block, so nested inside the short
   <header> it had nowhere to travel and never stuck.

   z-index sits ABOVE .header's 100 so the drawer's backdrop (110, inside this
   element) dims the header too. */
.navbar {
  position: sticky;
  top: 0;
  z-index: 120;
  background: var(--color-dark);
  border-top: 1px solid var(--color-slate);
  transition: box-shadow 0.3s ease, background 0.3s ease;
}
.navbar.is-stuck {
  background: var(--color-darker);
  box-shadow: 0 12px 30px -18px rgba(15, 20, 31, 0.9);
}

.navbar-inner {
  position: relative;
  display: flex;
  align-items: center;
  gap: 16px;
  min-height: 54px;
  /* School sketch, filling the dead space right of the menu. Purely
     decorative, so it is a pseudo-element -- nothing to tab to and no alt
     text to invent. z-index -1 keeps it above the bar's own background but
     behind the links and any open dropdown.

     `contain` scales it by HEIGHT, and the bar is only $header-h tall, so the
     bar height -- not the box width -- is what caps how big it can get. */
}
.navbar-inner::after {
  content: "";
  position: absolute;
  right: 15px;
  top: 50%;
  z-index: -1;
  width: 240px;
  height: 46px;
  transform: translateY(-50%);
  background: url("../images/webp-icons/header-sketch.webp") right center/contain no-repeat;
  opacity: 0.6;
  pointer-events: none;
  transition: opacity 0.3s ease;
}

/* Apply Now claims that corner once the bar sticks, so the sketch stands down. */
.navbar.is-stuck .navbar-inner::after {
  opacity: 0;
}

/* Compact brand + CTA: both live at zero width until the bar sticks. */
.nav-brand,
.nav-cta {
  display: flex;
  align-items: center;
  flex: none;
  overflow: hidden;
  max-width: 0;
  opacity: 0;
  transform: translateY(4px);
  pointer-events: none;
  white-space: nowrap;
  text-decoration: none;
  transition: max-width 0.45s ease, opacity 0.3s ease, transform 0.3s ease, margin 0.3s ease;
}

.nav-brand {
  gap: 10px;
  color: var(--color-white);
  font-weight: 700;
  font-size: 15px;
}
.nav-brand img {
  background: var(--color-white);
  border-radius: 50%;
  padding: 3px;
  width: 34px;
  height: 34px;
  -o-object-fit: contain;
     object-fit: contain;
}

/* Both brand links used to carry a `title` repeating the name printed right
   beside them, so hovering popped a white native tooltip straight over the
   words it echoed -- the name read as "disappears on hover". The title is
   gone; the name itself is the hover cue now. Stated once for both bars:
   violet on the white header, gold on the navy sticky bar. */
.logo-name,
.nav-brand span {
  transition: color 0.25s ease;
}

.logo:hover .logo-name,
.logo:focus-visible .logo-name {
  color: var(--color-primary);
}

.nav-brand:hover span,
.nav-brand:focus-visible span {
  color: var(--color-accent);
}

.nav-cta {
  margin-left: auto;
  padding: 0;
  border-radius: 50px;
  background: var(--color-accent);
  color: var(--color-dark);
  font-size: 13.5px;
  font-weight: 700;
}
.nav-cta:hover, .nav-cta:focus-visible {
  background: var(--color-white);
}

.navbar.is-stuck .nav-brand,
.navbar.is-stuck .nav-cta {
  max-width: 320px;
  opacity: 1;
  transform: none;
  pointer-events: auto;
}
.navbar.is-stuck .nav-brand {
  margin-right: 8px;
}
.navbar.is-stuck .nav-cta {
  padding: 10px 20px;
}

.nav-wrapper {
  display: flex;
  align-items: center;
  gap: 16px;
  flex: 1 1 auto;
}

.nav-menu {
  display: flex;
  align-items: center;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav-item {
  position: relative;
}

/* Dropdown parents are <span role="button">, not links, so the pointer and
   the no-select have to be stated -- a span gets neither for free. */
.nav-link {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  height: 54px;
  padding: 0 15px;
  cursor: pointer;
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;
  color: rgba(255, 255, 255, 0.85);
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-decoration: none;
  transition: color 0.3s ease;
  /* Active/hover marker sits on the bar's own baseline. */
}
.nav-link::before {
  content: "";
  position: absolute;
  left: 15px;
  right: 15px;
  bottom: 0;
  height: 3px;
  background: var(--color-accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s ease;
}
.nav-link:hover, .nav-link:focus-visible, .nav-link.is-active {
  color: var(--color-white);
}
.nav-link:hover::before, .nav-link:focus-visible::before, .nav-link.is-active::before {
  transform: scaleX(1);
}

.has-dropdown > .nav-link::after {
  content: "";
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform 0.3s ease;
}

.dropdown {
  position: absolute;
  top: calc(100% + 10px);
  left: 8px;
  min-width: 258px;
  margin: 0;
  padding: 8px;
  list-style: none;
  background: var(--color-darker);
  border: 1px solid var(--color-slate);
  border-top: 3px solid var(--color-accent);
  border-radius: 0 0 8px 8px;
  box-shadow: 0 24px 44px -24px rgba(0, 0, 0, 0.7);
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s ease;
}
.dropdown a {
  display: block;
  padding: 11px 14px;
  border-radius: 6px;
  color: rgba(255, 255, 255, 0.8);
  font-size: 14px;
  text-decoration: none;
  transition: background 0.3s ease, color 0.3s ease, padding-left 0.3s ease;
}
.dropdown a:hover, .dropdown a:focus-visible {
  background: var(--color-slate);
  color: var(--color-white);
  padding-left: 20px;
}

.nav-item.has-dropdown:hover > .dropdown,
.nav-item.has-dropdown:focus-within > .dropdown,
.nav-item.has-dropdown.is-open > .dropdown {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.nav-item.has-dropdown:hover > .nav-link::after,
.nav-item.has-dropdown.is-open > .nav-link::after {
  transform: rotate(-135deg);
  margin-top: 2px;
}

/* Mobile-only controls, hidden on desktop. */
.menu-toggle,
.dropdown-toggle,
.mobile-nav-head {
  display: none;
}

/* ---------- Narrow desktop ------------------------------------------- */
/* Between the nav breakpoint and 1200px the brand row has no room for the
   social icons too; they come back below $bp-lg, where .header-meta gets a
   full-width row of its own. */
@media (max-width: 1199.98px) {
  .social-links {
    display: none;
  }
  /* Menu runs wider relative to the bar here -- give the sketch less room. */
  .navbar-inner::after {
    width: 190px;
  }
}
/* ---------- Mobile --------------------------------------------------- */
@media (max-width: 991.98px) {
  /* Same call as the contact chips below: the ticker needs the whole strip
     on a phone, and the footer carries the social links. */
  .topbar-links,
  .topbar-social {
    display: none;
  }
  /* Mobile header is two rows only: topbar, then brand + burger. The contact
     chips and the CTA come off -- the number and mail id are in the footer and
     on the contact page, and the drawer carries its own Apply Now. */
  .header-meta {
    display: none;
  }
  .header-main-inner {
    flex-wrap: nowrap;
    gap: 12px;
  }
  /* The nav bar collapses here, so the compact two-row header does the
     sticking instead. Works because .header is a body-level child. */
  .header {
    position: sticky;
    top: 0;
  }
  /* Two sticky rows is a lot of a phone screen to give up on every scroll —
     it kept slicing the top off whatever was passing under it. Once the page
     moves the ticker rolls up and only the brand row goes on sticking; it
     comes back when the reader returns to the top. */
  .topbar {
    max-height: 64px;
    overflow: hidden;
    transition: max-height 0.3s ease;
  }
  .is-scrolled .topbar {
    max-height: 0;
    border-bottom-color: transparent;
  }
  .header-main {
    padding: 9px 0;
    box-shadow: 0 2px 14px -8px rgba(0, 0, 0, 0.45);
  }
  /* Nothing left for the bar to show: its only mobile job is hosting the
     drawer, which is position:fixed and escapes anyway. */
  .navbar {
    position: static;
    background: none;
    border-top: 0;
    box-shadow: none;
  }
  .navbar-inner {
    min-height: 0;
    padding: 0;
  }
  /* Bar is collapsed on mobile; nothing to decorate. */
  .navbar-inner::after {
    display: none;
  }
  .nav-brand {
    display: none;
  }
  /* .navbar is static now, so is-stuck never fires here -- but keep the
     drawer's CTA off the sticky-bar padding rule just in case. */
  .navbar.is-stuck .nav-cta {
    padding: 14px 22px;
  }
  /* A 40px fade each side eats a phone-width ticker. */
  .ticker-viewport {
    -webkit-mask-image: linear-gradient(90deg, transparent, var(--color-black) 16px, var(--color-black) calc(100% - 16px), transparent);
    mask-image: linear-gradient(90deg, transparent, var(--color-black) 16px, var(--color-black) calc(100% - 16px), transparent);
  }
  /* Lives on the white brand row now, so the bars are ink, not white. */
  .menu-toggle {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 38px;
    height: 38px;
    flex: none;
    margin-left: auto;
    padding: 0 10px;
    background: transparent;
    border: 1px solid var(--color-border);
    border-radius: 8px;
    cursor: pointer;
  }
  .menu-toggle .bar {
    display: block;
    height: 2px;
    background: var(--color-navy);
    border-radius: 2px;
    transition: transform 0.3s ease, opacity 0.3s ease;
  }
  .nav-brand {
    max-width: 260px;
    opacity: 1;
    transform: none;
    pointer-events: auto;
    margin-right: auto;
  }
  .nav-wrapper {
    position: fixed;
    inset: 0 0 0 auto;
    z-index: 120;
    width: min(340px, 86vw);
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0;
    background: var(--color-dark);
    overflow-y: auto;
    transform: translateX(100%);
    transition: transform 0.35s ease;
  }
  .nav-wrapper.is-open {
    transform: translateX(0);
  }
  .mobile-nav-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 18px;
    border-bottom: 1px solid var(--color-slate);
  }
  /* Only ~184px is left for the name after the mark and the close button, and
     the full name needs ~210px -- so it wraps. Balance the two lines rather
     than fighting it: "Chandra Badani / Public School", not a stranded
     "School" on its own row. */
  .mobile-nav-logo {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    color: var(--color-white);
    font-family: var(--heading-font-family);
    font-weight: 700;
    font-size: 14px;
    line-height: 1.2;
    letter-spacing: -0.01em;
    text-decoration: none;
  }
  .mobile-nav-logo img {
    background: var(--color-white);
    border-radius: 50%;
    padding: 3px;
    flex: none;
  }
  .mobile-nav-logo span {
    display: block;
    min-width: 0;
    text-wrap: balance;
  }
  .nav-close {
    position: relative;
    width: 40px;
    height: 40px;
    flex: none;
    background: var(--color-slate);
    border: 0;
    border-radius: 8px;
    cursor: pointer;
  }
  .nav-close::before, .nav-close::after {
    content: "";
    position: absolute;
    left: 11px;
    top: 19px;
    width: 18px;
    height: 2px;
    background: var(--color-white);
  }
  .nav-close::before {
    transform: rotate(45deg);
  }
  .nav-close::after {
    transform: rotate(-45deg);
  }
  .nav-menu {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 8px 0;
  }
  .nav-item {
    border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  }
  .nav-link {
    height: auto;
    padding: 15px 18px;
  }
  .nav-link::before {
    display: none;
  }
  .nav-link.is-active {
    color: var(--color-accent);
  }
  .has-dropdown > .nav-link::after {
    display: none;
  }
  .dropdown-toggle {
    position: absolute;
    top: 6px;
    right: 10px;
    display: block;
    width: 40px;
    height: 40px;
    background: transparent;
    border: 0;
    cursor: pointer;
  }
  .dropdown-toggle::before, .dropdown-toggle::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 50%;
    background: rgba(255, 255, 255, 0.7);
    transform: translate(-50%, -50%);
    transition: opacity 0.3s ease, transform 0.3s ease;
  }
  .dropdown-toggle::before {
    width: 12px;
    height: 2px;
  }
  .dropdown-toggle::after {
    width: 2px;
    height: 12px;
  }
  .nav-item.is-open > .dropdown-toggle::after {
    opacity: 0;
  }
  .dropdown {
    position: static;
    display: none;
    min-width: 0;
    padding: 4px 0 12px;
    background: var(--color-darker);
    border: 0;
    border-radius: 0;
    box-shadow: none;
    opacity: 1;
    visibility: visible;
    transform: none;
  }
  .dropdown a {
    padding: 11px 18px 11px 30px;
  }
  .nav-item.is-open > .dropdown {
    display: block;
  }
  /* No hover-open on touch: the toggle button drives it. */
  .nav-item.has-dropdown:hover > .dropdown {
    display: none;
  }
  .nav-item.has-dropdown.is-open:hover > .dropdown {
    display: block;
  }
  .nav-cta {
    order: 5;
    max-width: none;
    opacity: 1;
    transform: none;
    pointer-events: auto;
    justify-content: center;
    margin: 18px;
    padding: 14px 22px;
  }
}
@media (max-width: 767.98px) {
  .topbar-inner {
    min-height: 36px;
  }
  .logo {
    gap: 11px;
  }
  .logo img {
    width: 44px;
    height: 44px;
  }
  .logo-name {
    font-size: 16px;
  }
  .logo-tagline {
    font-size: 10px;
    letter-spacing: 0.1em;
  }
}
@media (max-width: 575.98px) {
  .topbar {
    font-size: 12px;
  }
  .logo img {
    width: 38px;
    height: 38px;
  }
  .logo-name {
    font-size: 14.5px;
  }
  .logo-tagline {
    font-size: 9px;
    letter-spacing: 0.08em;
  }
}
/* Backdrop behind the mobile drawer. It is a child of .navbar, so this 110
   is compared against .nav-wrapper's 120 in the same stacking context -- the
   drawer stays lit and everything else dims. Moving this element out of
   .navbar breaks that, because sticky positioning traps the drawer. */
.nav-backdrop {
  position: fixed;
  inset: 0;
  z-index: 110;
  background: rgba(15, 20, 31, 0.6);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0.3s ease;
}
.nav-backdrop.is-visible {
  opacity: 1;
  visibility: visible;
}

/* ---------- Quality floor -------------------------------------------- */
/* .navbar is a sibling of .header now, so it needs naming in both blocks. */
.header a:focus-visible,
.header button:focus-visible,
.navbar a:focus-visible,
.navbar button:focus-visible,
.navbar .nav-link:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .ticker-track {
    animation: none;
  }
  .header *,
  .header *::before,
  .header *::after,
  .navbar *,
  .navbar *::before,
  .navbar *::after {
    transition-duration: 0.01ms !important;
  }
}
/* =========================================================
   HERO
   Full-bleed photo slider. The navy scrim runs left-to-right
   so the headline always sits on brand colour and the faces
   in the photograph stay clear on the right.
   ========================================================= */
.hero {
  position: relative;
  isolation: isolate;
  min-height: clamp(520px, 76vh, 780px);
  display: flex;
  align-items: flex-end;
  padding: 120px 0 116px;
  overflow: hidden;
  background: var(--color-dark);
  color: var(--color-white);
  font-family: var(--body-font-family);
}

/* ---------- Slides --------------------------------------------------- */
.hero-slides {
  position: absolute;
  inset: 0;
  z-index: -2;
}

.hero-slide {
  position: absolute;
  inset: 0;
  background-position: center;
  background-size: cover;
  opacity: 0;
  transform: scale(1.06);
  transition: opacity 1s ease;
}
.hero-slide.is-active {
  opacity: 1;
  animation: hero-drift 9s ease-out forwards;
}

@keyframes hero-drift {
  from {
    transform: scale(1.06);
  }
  to {
    transform: scale(1);
  }
}
.hero-scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgba(15, 20, 31, 0.55) 0%, rgba(15, 20, 31, 0) 32%), linear-gradient(90deg, rgba(23, 30, 46, 0.94) 0%, rgba(23, 30, 46, 0.82) 34%, rgba(23, 30, 46, 0.36) 64%, rgba(23, 30, 46, 0.1) 100%), linear-gradient(0deg, rgba(15, 20, 31, 0.8) 0%, rgba(15, 20, 31, 0) 55%);
}

/* ---------- Content -------------------------------------------------- */
.hero-inner {
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 40px;
}

.hero-content {
  max-width: 660px;
  /* Runs once on load -- the panel no longer swaps with the background. */
  animation: hero-panel-in 0.6s ease both;
}

@keyframes hero-panel-in {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.hero-eyebrow {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 20px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.78);
}
.hero-eyebrow::before {
  content: "";
  width: 34px;
  height: 2px;
  flex: none;
  background: var(--color-accent);
}

.hero-title {
  margin: 0 0 10px;
  font-family: var(--heading-font-family);
  font-size: clamp(31px, 18px + 2.6vw, 58px);
  font-weight: 800;
  line-height: 1.06;
  letter-spacing: -0.025em;
  color: var(--color-white);
  text-wrap: balance;
}

/* The long name is set as two block lines rather than left to wrap, so it reads
   as a name and not as a sentence that ran out of room. */
.hero-title-line {
  display: block;
}

/* The motto sits between the name and the paragraph and carries the hand-drawn
   stroke the old headline used, so the accent survives the H1 change without
   underlining half of the school's own name. */
.hero-tagline {
  margin: 0 0 22px;
  font-family: var(--heading-font-family);
  font-size: clamp(18px, 13px + 0.9vw, 26px);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--color-white);
}

/* Hand-drawn accent stroke under the line that carries the promise. */
.hero-mark {
  position: relative;
  display: inline-block;
  white-space: nowrap;
}
.hero-mark svg {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.16em;
  width: 100%;
  height: 0.22em;
  overflow: visible;
  color: var(--color-accent);
}
.hero-mark path {
  fill: none;
  stroke: currentColor;
  stroke-width: 7;
  stroke-linecap: round;
  stroke-dasharray: 420;
  stroke-dashoffset: 420;
  animation: hero-stroke 0.9s 0.5s ease forwards;
}

@keyframes hero-stroke {
  to {
    stroke-dashoffset: 0;
  }
}
.hero-lead {
  margin: 0 0 32px;
  max-width: 540px;
  font-size: 1rem;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.8);
}

/* "Every child here is known by name" used to be the headline; as the opening
   sentence of the lead it still needs to read a step above the rest of it. */
.hero-lead strong {
  font-weight: 600;
  color: var(--color-white);
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-bottom: 34px;
}

/* Layout hook only -- fill, arrow chip and hover flip come from .theme-btn in
   _buttons.scss. The hero just makes the pair a touch larger. */
.hero-btn {
  padding-left: clamp(20px, 14px + 1.2vw, 30px);
}
.hero-btn .btn-icon {
  width: clamp(34px, 22px + 1.7vw, 42px);
  height: clamp(34px, 22px + 1.7vw, 42px);
}

/* Three facts as a plain rule-separated row -- no panel, no glow. The hero
   scrim is already the ground here; boxing them again only fought the photo.
   Each column carries its own hue through --fact-accent. */
.hero-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 34px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.fact {
  position: relative;
  display: flex;
  align-items: center;
  gap: 13px;
}
.fact + .fact::before {
  content: "";
  position: absolute;
  left: -17px;
  top: 5px;
  bottom: 5px;
  width: 1px;
  background: rgba(255, 255, 255, 0.2);
}
.fact {
  /* --fact-accent draws the ring; --fact-icon recolours the line art, which
     is an <img> and so needs a filter rather than a colour. */
}
.fact.is-violet {
  --fact-accent: var(--color-primary);
  /* Violet reads far dimmer than the other two against the scrim, and thin
     strokes lose that fight -- the lift puts the icon near #b778ff. */
  --fact-icon: brightness(0) saturate(100%) invert(31%) sepia(21%) saturate(7489%) hue-rotate(242deg) brightness(91%) contrast(96%) brightness(165%);
}
.fact.is-green {
  --fact-accent: var(--color-success);
  --fact-icon: brightness(0) saturate(100%) invert(66%) sepia(12%) saturate(2205%) hue-rotate(102deg) brightness(100%) contrast(82%);
}
.fact.is-amber {
  --fact-accent: var(--color-accent);
  --fact-icon: brightness(0) saturate(100%) invert(98%) sepia(31%) saturate(7478%) hue-rotate(319deg) brightness(99%) contrast(96%);
}

.fact-ring {
  display: grid;
  place-items: center;
  width: 50px;
  height: 50px;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--fact-accent);
}

/* Black line art like the SVG set, so it takes the same recolour. */
.fact-icon {
  width: 32px;
  height: 32px;
  filter: var(--fact-icon);
}

.fact-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.fact-value {
  font-family: var(--heading-font-family);
  font-size: clamp(15px, 12px + 0.55vw, 20px);
  font-weight: 700;
  line-height: 1.15;
  color: var(--color-white);
}

.fact-label {
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.35;
  color: rgba(255, 255, 255, 0.62);
}

/* ---------- Slider controls (the signature element) ------------------- */
.hero-controls {
  display: flex;
  align-items: center;
  gap: 18px;
  flex: none;
  padding-bottom: 6px;
}

.hero-count {
  /* It is a <p>, so the base 0 0 15px margin would otherwise push the
     digits half a line above the rail and the arrows. */
  margin: 0;
  font-size: 13px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.6);
}
.hero-count .is-now {
  color: var(--color-white);
}

/* Rail fills across the autoplay interval, so the bar is a real timer. */
.hero-rail {
  position: relative;
  width: 130px;
  height: 2px;
  background: rgba(255, 255, 255, 0.25);
  overflow: hidden;
}

.hero-rail-fill {
  position: absolute;
  inset: 0;
  background: var(--color-accent);
  transform: scaleX(0);
  transform-origin: left;
}

.hero-rail-fill.is-running {
  animation: hero-rail 7s linear forwards;
}

@keyframes hero-rail {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}
.hero-arrows {
  display: flex;
  gap: 8px;
}

.hero-arrow {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 50%;
  color: var(--color-white);
  cursor: pointer;
  transition: background 0.3s ease, border-color 0.3s ease, color 0.3s ease;
  /* Chevrons are real icon files, so .is-prev / .is-next differ only in the
     src -- no rotation maths. */
}
.hero-arrow .icon {
  width: 16px;
  height: 16px;
  filter: brightness(0) saturate(100%) invert(100%) sepia(0%) saturate(21%) hue-rotate(19deg) brightness(103%) contrast(100%);
}
.hero-arrow:hover, .hero-arrow:focus-visible {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: var(--color-white);
}

/* ---------- Edge tabs ------------------------------------------------- */
.hero-tabs {
  position: absolute;
  top: 50%;
  right: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 6px;
  transform: translateY(-50%);
}
.hero-tabs a {
  writing-mode: vertical-rl;
  padding: 18px 11px;
  border-radius: 8px 0 0 8px;
  background: var(--color-primary);
  color: var(--color-white);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  transition: background 0.3s ease, color 0.3s ease, padding 0.3s ease;
  /* Ground and text flip together -- gold takes dark text, maroon takes
     white, and these two tabs swap grounds on hover. */
}
.hero-tabs a:hover, .hero-tabs a:focus-visible {
  background: var(--color-darker);
  color: var(--color-white);
  padding-right: 16px;
}
.hero-tabs a.is-secondary {
  background: var(--color-darker);
  color: var(--color-white);
}
.hero-tabs a.is-secondary:hover, .hero-tabs a.is-secondary:focus-visible {
  background: var(--color-primary);
  color: var(--color-white);
}

/* ---------- Quick access strip --------------------------------------- */
.hero-quick {
  position: relative;
  z-index: 6;
  margin-top: -62px;
}

.hero-quick-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: 8px;
  box-shadow: 0 30px 60px -40px rgba(15, 20, 31, 0.6);
  overflow: hidden;
}

.quick-card {
  position: relative;
  display: flex;
  align-items: center;
  gap: 14px;
  /* One clamp instead of a phone override — it lands near 12px/16px on a
     narrow screen and back at the old 26px/24px on a wide one. */
  padding: clamp(12px, 4px + 1.5vw, 26px) clamp(16px, 8px + 1.1vw, 24px);
  text-decoration: none;
  border-right: 1px solid var(--color-border);
  transition: background 0.3s ease;
}
.quick-card:last-child {
  border-right: 0;
}
.quick-card {
  /* Accent bar grows from the top edge on hover. */
}
.quick-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: var(--color-primary);
  transform: scaleX(0);
  transition: transform 0.3s ease;
}
.quick-card:hover, .quick-card:focus-visible {
  background: var(--color-bg-soft);
}
.quick-card:hover::before, .quick-card:focus-visible::before {
  transform: scaleX(1);
}
.quick-card:hover .quick-icon, .quick-card:focus-visible .quick-icon {
  background: var(--color-primary);
  border-color: var(--color-primary);
}
.quick-card:hover .quick-arrow, .quick-card:focus-visible .quick-arrow {
  transform: translateX(4px);
}

.quick-icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  flex: none;
  border-radius: 8px;
  background: var(--color-dark);
  border: 1px solid var(--color-dark);
  transition: background 0.3s ease, border-color 0.3s ease;
}
.quick-icon .icon {
  width: 20px;
  height: 20px;
  filter: brightness(0) saturate(100%) invert(100%) sepia(0%) saturate(21%) hue-rotate(19deg) brightness(103%) contrast(100%);
}

.quick-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.quick-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--color-navy);
}

.quick-note {
  font-size: 12.5px;
  color: var(--color-body);
}

.quick-arrow {
  margin-left: auto;
  flex: none;
  color: var(--color-muted);
  font-size: 18px;
  line-height: 1;
  transition: transform 0.3s ease;
}

/* ---------- Responsive ------------------------------------------------ */
@media (max-width: 1199.98px) {
  .hero-quick-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  .quick-card:nth-child(2n) {
    border-right: 0;
  }
  .quick-card:nth-child(-n+2) {
    border-bottom: 1px solid var(--color-border);
  }
}
@media (max-width: 991.98px) {
  .hero {
    min-height: 0;
    padding: 84px 0 92px;
  }
  .hero-inner {
    flex-direction: column;
    align-items: flex-start;
    gap: 30px;
  }
  /* The photo runs the full width here instead of sitting beside the copy, so
     the scrim is the only thing carrying contrast. The old 0.3 mid-stop left
     white text at 2.2:1 over a bright sky; 0.68 puts it at 6.9:1. */
  .hero-scrim {
    background: linear-gradient(180deg, rgba(15, 20, 31, 0.78) 0%, rgba(15, 20, 31, 0.68) 45%, rgba(15, 20, 31, 0.94) 100%);
  }
  .hero-tabs {
    display: none;
  }
  /* Stacked, the controls row has the column to itself, so it takes the whole
     width: the rail stretches and the arrows land on the right edge instead
     of trailing the rail somewhere in the middle of the line. */
  .hero-controls {
    width: 100%;
  }
  .hero-rail {
    flex: 1;
    width: auto;
  }
}
@media (max-width: 767.98px) {
  /* The bottom padding used to be 76px, and the quick strip only rides 34px
     of it, so a band of empty scrim sat between the slider controls and the
     white cards. */
  .hero {
    padding: 64px 0 52px;
  }
  /* "Admissions open - Session 2026-27" needs 347px at the desktop size but a
     375px phone only offers 345, so it wrapped and stranded "27" on its own
     line. Tighter type brings it to 294px. flex-start keeps the rule beside
     the FIRST line rather than floating mid-block if it ever does wrap on a
     320px screen. */
  .hero-eyebrow {
    align-items: flex-start;
    gap: 9px;
    margin-bottom: 16px;
    font-size: 11px;
    line-height: 1.45;
    letter-spacing: 0.12em;
  }
  .hero-eyebrow::before {
    width: 24px;
    margin-top: 7px;
  }
  /* .hero-mark holds the stroke on one unbroken line, so the motto has to fit
     the narrowest phone. 16px puts "Shaping Bright Futures Together" at roughly
     258px, inside the 288px a 320px screen leaves after the container padding. */
  .hero-tagline {
    margin-bottom: 18px;
    font-size: 16px;
  }
  /* Both actions stay on one row on a phone. The pills share the width
     evenly and the label is allowed to wrap, so the longer second-slide
     copy still fits without pushing the ghost button onto its own line. */
  .hero-actions {
    flex-wrap: nowrap;
    gap: 10px;
    margin-bottom: 28px;
  }
  .hero-btn {
    flex: 1 1 0;
    min-width: 0;
    justify-content: space-between;
    gap: 8px;
    padding: 5px 5px 5px 16px;
    font-size: 13px;
    line-height: 1.25;
    white-space: normal;
    text-align: left;
  }
  .hero-btn .btn-icon {
    width: 30px;
    height: 30px;
  }
  .hero-btn .btn-icon .icon {
    width: 60%;
    height: 60%;
  }
  /* Stays three across -- stacking three stats would cost more height than
     the whole hero can spare on a phone. There is no room for the icon to sit
     beside the text at ~100px a column, so it goes back on top. */
  .hero-facts {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0;
  }
  .fact {
    flex-direction: column;
    align-items: center;
    gap: 8px;
    min-width: 0;
    padding: 0 6px;
    text-align: center;
  }
  .fact + .fact::before {
    left: 0;
    top: 2px;
    bottom: 2px;
  }
  .fact-ring {
    width: 42px;
    height: 42px;
  }
  .fact-icon {
    width: 23px;
    height: 23px;
  }
  /* Three 1fr columns leave roughly 95px for a label, and "Campus and
     grounds" runs a hair past that -- letting it wrap made the third column
     taller than the other two. One line with an ellipsis keeps the row even;
     the full string stays in the DOM, so screen readers still get it. */
  .fact-text {
    align-items: center;
    max-width: 100%;
  }
  .fact-label {
    max-width: 100%;
    font-size: 10px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /* The 6px nudge only exists to lift the row off the bottom edge in the
     desktop flex-end layout; stacked on a phone it is just dead space. */
  .hero-controls {
    gap: 12px;
    padding-bottom: 0;
  }
  .hero-arrow {
    width: 40px;
    height: 40px;
  }
  .hero-quick {
    margin-top: -34px;
  }
  .hero-quick-grid {
    grid-template-columns: 1fr;
  }
  .quick-card {
    border-right: 0;
    border-bottom: 1px solid var(--color-border);
  }
  .quick-card:last-child {
    border-bottom: 0;
  }
}
/* ---------- Quality floor -------------------------------------------- */
.hero a:focus-visible,
.hero button:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .hero-slide.is-active {
    animation: none;
  }
  .hero-mark path {
    animation: none;
    stroke-dashoffset: 0;
  }
  .hero-rail-fill.is-running {
    animation: none;
    transform: scaleX(1);
  }
  .hero *,
  .hero *::before,
  .hero *::after,
  .hero-quick * {
    transition-duration: 0.01ms !important;
  }
}
.breadcrumb-banner {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  position: relative;
  padding-block: clamp(50px, 7vw, 90px);
  background-color: var(--color-dark);
  color: var(--color-white);
  text-align: center;
}
.breadcrumb-banner::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(15, 20, 31, 0.82), rgba(23, 30, 46, 0.88));
}
.breadcrumb-banner .container {
  position: relative;
}
.breadcrumb-banner .breadcrumb-title {
  color: var(--color-white);
  font-size: clamp(24px, 14px + 2.2vw, 48px);
  margin-bottom: 12px;
}
.breadcrumb-banner .breadcrumb-trail {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 22px;
  font-size: 14.5px;
  color: rgba(255, 255, 255, 0.8);
}
.breadcrumb-banner .breadcrumb-trail li {
  position: relative;
}
.breadcrumb-banner .breadcrumb-trail li + li::before {
  content: "";
  position: absolute;
  left: -14px;
  top: 50%;
  width: 6px;
  height: 6px;
  border-right: 2px solid var(--color-accent);
  border-bottom: 2px solid var(--color-accent);
  transform: translateY(-50%) rotate(-45deg);
}
.breadcrumb-banner .breadcrumb-trail li[aria-current] {
  color: var(--color-accent);
}
.breadcrumb-banner .breadcrumb-trail a {
  color: rgba(255, 255, 255, 0.8);
}
.breadcrumb-banner .breadcrumb-trail a:hover {
  color: var(--color-accent);
}

.page-section {
  padding-block: clamp(45px, 6vw, 85px);
}
.page-section.is-tinted {
  background: var(--color-bg-soft);
}

.section-head {
  max-width: 760px;
  margin-bottom: 35px;
}
.section-head .section-sub {
  display: inline-block;
  color: var(--color-primary);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin-bottom: 10px;
}
.section-head.text-center {
  margin-inline: auto;
}

.footer {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-color: var(--color-dark);
  background-image: url("../images/webp-icons/footer-bg.webp");
  color: rgba(255, 255, 255, 0.75);
  padding-top: 60px;
}
.footer a {
  color: rgba(255, 255, 255, 0.75);
}
.footer a:hover {
  color: var(--color-accent);
}
.footer .footer-top {
  display: grid;
  grid-template-columns: 1.4fr repeat(3, 1fr);
  gap: 40px;
  padding-bottom: 45px;
}
.footer .footer-logo {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 18px;
  color: var(--color-white);
  font-family: var(--heading-font-family);
  font-size: 18px;
  font-weight: 700;
  line-height: 1.25;
}
.footer .footer-logo img {
  background: var(--color-white);
  border-radius: 50%;
  padding: 3px;
}
.footer .footer-title {
  color: var(--color-white);
  font-size: 17px;
  margin-bottom: 18px;
  position: relative;
  padding-bottom: 10px;
}
.footer .footer-title::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 38px;
  height: 3px;
  background: var(--color-accent);
  border-radius: 2px;
}
.footer .footer-links {
  display: grid;
  gap: 10px;
  font-size: 14.5px;
}
.footer .footer-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 15px;
  flex-wrap: wrap;
  padding-block: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  font-size: 14px;
}
.footer .footer-bottom p {
  margin: 0;
}
@media (max-width: 991.98px) {
  .footer .footer-top {
    grid-template-columns: repeat(2, 1fr);
    gap: 30px;
  }
}
@media (max-width: 767.98px) {
  .footer {
    padding-top: 45px;
  }
  .footer .footer-top {
    grid-template-columns: 1fr;
  }
  .footer .footer-bottom {
    justify-content: center;
    text-align: center;
  }
}/*# sourceMappingURL=style.css.map */
