/* Brightwoods public site — design tokens. Niki owns this file. Names are the contract. */
:root {
  --bws-color-brand: #005051;
  --bws-color-brand-600: #007c83;
  --bws-color-brand-400: #3aa39f;
  --bws-color-brand-100: #e3f2f0;
  --bws-color-accent: #e8a838;
  --bws-color-accent-100: #fbeed2;
  --bws-color-ink: #161f1c;
  --bws-color-ink-soft: #42524c;
  --bws-color-line: #e6e1d6;
  --bws-color-bg: #faf8f4;
  --bws-color-surface: #ffffff;
  --bws-color-success: #1e6b3a;
  --bws-color-warning: #96590a;
  --bws-color-danger: #9a2a1f;

  --bws-font-display: "Poppins", system-ui, -apple-system, "Segoe UI", sans-serif;
  --bws-font-body: "Poppins", system-ui, -apple-system, "Segoe UI", sans-serif;
  /* Hand-signature look for the directress letter's closing name, matching
     the old Brightwoods site. cursive as the fallback (not sans-serif) so a
     failed font load still reads as a signature, not a body-text mistake. */
  --bws-font-script: "Alex Brush", "Brush Script MT", cursive;

  --bws-text-xs: 0.8125rem;
  --bws-text-sm: 0.9375rem;
  --bws-text-md: 1.0625rem;
  --bws-text-lg: 1.25rem;
  --bws-text-xl: 1.5rem;
  --bws-text-2xl: clamp(1.75rem, 1.2rem + 2vw, 2.25rem);
  --bws-text-3xl: clamp(2rem, 1.4rem + 3vw, 3rem);
  --bws-text-4xl: clamp(2.5rem, 1.6rem + 4.5vw, 4rem);

  --bws-space-1: 0.25rem;  --bws-space-2: 0.5rem;   --bws-space-3: 0.75rem;
  --bws-space-4: 1rem;     --bws-space-5: 1.5rem;   --bws-space-6: 2rem;
  --bws-space-8: 3rem;     --bws-space-10: 4rem;    --bws-space-12: 6rem;

  --bws-radius-sm: 6px; --bws-radius-md: 12px; --bws-radius-lg: 20px; --bws-radius-pill: 999px;
  --bws-shadow-sm: 0 1px 2px rgba(22, 31, 28, .08);
  --bws-shadow-md: 0 8px 24px rgba(22, 31, 28, .10);

  --bws-container: 1200px;
  /* The utility rail is fixed and paints over the page, so its geometry is a
     layout constant that clearance paddings elsewhere subtract from the
     available width. Derive all of them from these three, so the rail can
     shrink on small screens without a single rule being updated by hand. */
  --bws-rail-icon: 48px;
  --bws-rail-pad: var(--bws-space-6);
  --bws-rail-gap: var(--bws-space-5);
  --bws-rail-width: 96px;
  /* The nav row's centre line has to land exactly on the rail's burger
     centre, which is the rail's top padding plus half an icon. Computed
     rather than the literal 112px it used to be, so resizing an icon or the
     rail padding can no longer silently knock the two out of alignment. */
  --bws-header-height: calc(2 * (var(--bws-rail-pad) + var(--bws-rail-icon) / 2));
  /* Safe clearance for content that would otherwise sit under the fixed
     left enrollment tab (768px and up — it hides below that). Generous
     rather than exact: the tab's own width is text set in vertical-rl, not
     a fixed value, so this errs wide. */
  --bws-tab-width: 72px;
}
/* At 96px the rail covered a quarter of a 390px phone and painted over the
   hero headings, and the header height it drives ate 112px of an 844px
   screen. Shrinking it here reflows every clearance padding with it. */
@media (max-width: 767px) {
  :root {
    /* rail-icon and rail-pad are deliberately left alone: --bws-header-height
       is derived from them, so slimming the rail through these would shrink
       the header bar and shift the logo with it. The rail is sized directly
       in its own phone rule instead; only the width moves here, since that
       feeds clearance rather than the header. */
    --bws-rail-icon: 40px;
    --bws-rail-pad: var(--bws-space-4);
    --bws-rail-gap: var(--bws-space-3);
    --bws-rail-width: 44px;
  }
}
/* Portrait tablets carry both fixed rails at once — the enrollment tab on
   the left and the utility rail on the right — so both give up some width. */
@media (min-width: 768px) and (max-width: 1023px) {
  :root {
    --bws-rail-icon: 44px;
    --bws-rail-pad: var(--bws-space-5);
    --bws-rail-gap: var(--bws-space-4);
    --bws-rail-width: 72px;
    --bws-tab-width: 56px;
  }
}
/* The one clearance formula every rail/tab-adjacent rule on the site
   should use instead of its own calc(): clear the tab/rail only by as
   much as the centred .bws-container's own margin doesn't already
   provide, collapsing to the plain gutter once the viewport is wide
   enough that the rail sits well outside the container. Undefined below
   768px on purpose — the enrollment tab is hidden there (see
   .bws-banner), so nothing needs left-side clearance, and every
   consumer's mobile rule uses the plain --bws-space-4 gutter directly. */
:root {
  /* Phones: the plain gutter on both sides. Nothing floats over the text
     there — the enrollment tab is hidden, and the rail is folded into the
     header band (see .bws-utility-rail below 768px), so the page keeps its
     full width. Reserving a column for the rail instead left the text in a
     narrow strip with a dead gap beside it, which was worse than the problem
     it solved. */
  --bws-safe-left: var(--bws-space-4);
  --bws-safe-right: var(--bws-space-4);
}
@media (min-width: 768px) {
  :root {
    --bws-safe-left: max(var(--bws-space-4), calc(var(--bws-tab-width) + var(--bws-space-4) - max(0px, (100vw - var(--bws-container)) / 2)));
    --bws-safe-right: max(var(--bws-space-4), calc(var(--bws-rail-width) + var(--bws-space-4) - max(0px, (100vw - var(--bws-container)) / 2)));
  }
}
/* Breakpoints (use in media queries): 480px, 768px, 1024px, 1280px */
/* Brightwoods public site — base styles. Mobile-first. Every colour via tokens.css. */
/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body, h1, h2, h3, h4, p, figure, blockquote, dl, dd { margin: 0; }
ul[class], ol[class] { margin: 0; padding: 0; list-style: none; }
img, picture { max-width: 100%; display: block; }
input, button, textarea, select { font: inherit; }
a { color: inherit; }
/* ---------- Typography ---------- */
body.bws {
  font-family: var(--bws-font-body);
  font-size: var(--bws-text-md);
  line-height: 1.6;
  color: var(--bws-color-ink);
  background: var(--bws-color-bg);
  /* clip, NOT hidden: overflow:hidden would turn body into a scroll
     container and break every position:sticky on the page (the header, the
     hero, the mid-page parallax all depend on it). clip contains sideways
     overflow without that side effect, and leaves overflow-y visible. */
  overflow-x: clip;
}
.bws h1, .bws h2, .bws h3, .bws h4 {
  font-family: var(--bws-font-display);
  font-weight: 600;
  line-height: 1.2;
  color: var(--bws-color-ink);
}
.bws h1 { font-size: var(--bws-text-4xl); }
.bws h2 { font-size: var(--bws-text-3xl); }
.bws h3 { font-size: var(--bws-text-2xl); }
.bws h4 { font-size: var(--bws-text-xl); }
.bws p { font-size: var(--bws-text-md); color: var(--bws-color-ink-soft); }
.bws a { text-decoration: none; }
/* Headings reset to margin:0 above — give a section's own title room from
   whatever follows it (a grid, a lede) instead of sitting flush against it. */
.bws-container > h2 { margin-bottom: var(--bws-space-6); }
/* ---------- Skip link ---------- */
.bws-skip-link {
  position: absolute;
  left: -999px;
  top: auto;
  z-index: 1000;
  background: var(--bws-color-brand);
  color: #fff;
  padding: var(--bws-space-2) var(--bws-space-4);
  border-radius: var(--bws-radius-sm);
}
.bws-skip-link:focus {
  left: var(--bws-space-4);
  top: var(--bws-space-4);
}
/* ---------- Layout helpers ---------- */
.bws-container {
  max-width: var(--bws-container);
  margin-inline: auto;
  padding-inline: var(--bws-space-4);
}
.bws-container--narrow { max-width: 760px; }
/* Explicit opaque background, not just inherited from body: the hero is
   position:sticky and stays in place behind the whole rest of the page, so
   every section needs its own solid fill or it shows through. */
.bws-section { position: relative; z-index: 1; background: var(--bws-color-bg); padding-block: var(--bws-space-8); }
.bws-grid {
  display: grid;
  gap: var(--bws-space-5);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.bws-grid--2 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
@media (min-width: 768px) {
  /* minmax(0, 1fr), not bare 1fr: a bare 1fr is minmax(auto, 1fr), which
     can't shrink a track below its content's intrinsic width (a <select>,
     a date input). Once the container itself got narrower than two such
     tracks side by side — the admissions inquiry form once its aside
     card took part of the row — the grid overflowed its own column
     instead of the tracks shrinking to fit. */
  .bws-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  /* Same minmax(0, …) reasoning as .bws-grid--2 above: these three tracks
     now sit inside a container that clears both fixed rails, so they have
     ~180px less room than before and a bare 1fr's intrinsic-width floor is
     that much closer to biting. */
  .bws-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* ---------- Buttons ---------- */
.bws-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--bws-space-2);
  padding: var(--bws-space-3) var(--bws-space-5);
  border-radius: var(--bws-radius-pill);
  font-weight: 600;
  font-size: var(--bws-text-sm);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.bws-btn--primary {
  background: var(--bws-color-brand);
  color: #fff;
}
.bws-btn--primary:hover { background: var(--bws-color-brand-600); }
.bws-btn--secondary {
  background: var(--bws-color-accent);
  color: var(--bws-color-ink);
}
.bws-btn--secondary:hover { background: var(--bws-color-accent-100); }
.bws-btn--ghost {
  background: transparent;
  color: var(--bws-color-brand);
  border-color: var(--bws-color-brand);
}
.bws-btn--ghost:hover {
  background: var(--bws-color-brand-100);
}
.bws-btn__spinner {
  display: none;
  width: 14px;
  height: 14px;
  border: 2px solid rgba(255, 255, 255, .4);
  border-top-color: currentColor;
  border-radius: 50%;
}
.bws-btn.is-loading { cursor: default; }
.bws-btn.is-loading .bws-btn__spinner {
  display: inline-block;
  -webkit-animation: bws-spin .6s linear infinite;
          animation: bws-spin .6s linear infinite;
}
@-webkit-keyframes bws-spin {
  to { -webkit-transform: rotate(360deg); transform: rotate(360deg); }
}
@keyframes bws-spin {
  to { -webkit-transform: rotate(360deg); transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .bws-btn.is-loading .bws-btn__spinner { -webkit-animation: none; animation: none; }
}
/* ---------- Card ---------- */
.bws-card {
  background: var(--bws-color-surface);
  border: 1px solid var(--bws-color-line);
  border-radius: var(--bws-radius-md);
  padding: var(--bws-space-5);
  box-shadow: var(--bws-shadow-sm);
}
/* ---------- Tag ---------- */
.bws-tag {
  display: inline-flex;
  align-items: center;
  padding: var(--bws-space-1) var(--bws-space-3);
  border-radius: var(--bws-radius-pill);
  background: var(--bws-color-brand-100);
  color: var(--bws-color-brand);
  font-size: var(--bws-text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
}
/* ---------- Header / nav ---------- */
.bws-header {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  z-index: 250;
  /* .bws-header has no content of its own — .bws-header__inner is what
     normally gives it height. Without this, hiding that child while the
     drawer is open (below) collapses .bws-header to ~0px and the whole
     page snaps upward to fill the gap. Fixing the height here keeps the
     header's box constant regardless of what's shown inside it. */
  min-height: var(--bws-header-height);
  background: var(--bws-color-surface);
  /* The divider is an inset shadow, not a border: a border adds 1px to the
     header's height, which the hero's negative margin (header height
     exactly) didn't cover, leaving a hairline of page background showing
     under the transparent header. */
  box-shadow: inset 0 -1px 0 var(--bws-color-line);
  transition: background-color .25s ease, box-shadow .25s ease;
}
/* Over a hero the header carries NO background of its own — the darkening
   lives on the hero photo itself (.bws-hero__scrim), so there is no
   header-shaped rectangle that can read as a grey bar over a bright photo.
   This is set in CSS rather than by a JS-added class so the transparent
   state is the default paint and cannot fail open to a white bar; home.js
   only adds --solid once the hero has scrolled out from under it. */
body:has(.bws-hero) .bws-header {
  background: transparent;
  box-shadow: none;
}
body:has(.bws-hero) .bws-header .bws-logo,
body:has(.bws-hero) .bws-header .bws-logo span,
body:has(.bws-hero) .bws-header .bws-nav a { color: #fff; }
/* Scrolled at all — back to the plain white bar. */
body:has(.bws-hero) .bws-header.bws-header--solid {
  background: var(--bws-color-surface);
  box-shadow: inset 0 -1px 0 var(--bws-color-line);
}
body:has(.bws-hero) .bws-header--solid .bws-logo,
body:has(.bws-hero) .bws-header--solid .bws-logo span { color: var(--bws-color-ink); }
body:has(.bws-hero) .bws-header--solid .bws-nav a { color: var(--bws-color-ink-soft); }
.bws-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: var(--bws-header-height);
  gap: var(--bws-space-6);
  padding-inline: var(--bws-space-8);
  /* Rail width plus a gutter — flush against the rail's edge left the last
     nav link visually colliding with it. */
  padding-right: calc(var(--bws-rail-width) + var(--bws-space-5));
  position: relative;
}
/* 48px is a desktop-width gutter. Narrower screens can't spare it on the
   logo's side — the rail already claims the other one — so the wordmark
   moves back toward the edge. padding-left only: the right side's rail
   clearance above still applies. */
@media (max-width: 1023px) {
  .bws-header__inner { padding-left: var(--bws-space-5); }
}
@media (max-width: 767px) {
  .bws-header__inner { padding-left: var(--bws-space-4); }
}
.bws-logo {
  display: flex;
  align-items: center;
  gap: var(--bws-space-3);
  font-family: var(--bws-font-display);
  font-weight: 700;
  font-size: var(--bws-text-lg);
  color: var(--bws-color-ink);
}
/* Subtle settle-in on first load, in the spirit of Repton's bolder version —
   a small overshoot then rest, not a full bounce. */
@-webkit-keyframes bws-bob-in {
  0%   { -webkit-transform: translateY(-10px); transform: translateY(-10px); opacity: 0; }
  55%  { -webkit-transform: translateY(3px); transform: translateY(3px); opacity: 1; }
  100% { -webkit-transform: translateY(0); transform: translateY(0); }
}
@keyframes bws-bob-in {
  0%   { -webkit-transform: translateY(-10px); transform: translateY(-10px); opacity: 0; }
  55%  { -webkit-transform: translateY(3px); transform: translateY(3px); opacity: 1; }
  100% { -webkit-transform: translateY(0); transform: translateY(0); }
}
.bws-logo {
  -webkit-animation: bws-bob-in .6s cubic-bezier(.34, 1.2, .64, 1) both;
          animation: bws-bob-in .6s cubic-bezier(.34, 1.2, .64, 1) both;
}
@media (prefers-reduced-motion: reduce) {
  .bws-logo { -webkit-animation: none; animation: none; }
}
.bws-logo img { width: auto; height: 56px; }
/* Two wordmarks: coloured by default (any solid header), white-lettered only
   while the header floats transparent over a hero, swapping back the moment
   home.js turns the bar solid on scroll. */
.bws-logo .bws-logo__img--light { display: none; }
body:has(.bws-hero) .bws-header:not(.bws-header--solid) .bws-logo__img--color { display: none; }
body:has(.bws-hero) .bws-header:not(.bws-header--solid) .bws-logo__img--light { display: block; }
@media (max-width: 480px) {
  .bws-logo img { height: 44px; }
}
.bws-nav-toggle { position: absolute; opacity: 0; pointer-events: none; }
/* Primary links — hidden on narrow screens (the drawer carries them there),
   inline and generously spaced on wider ones. */
.bws-nav { display: none; }
@media (min-width: 768px) {
  .bws-nav {
    display: flex;
    align-items: center;
    gap: var(--bws-space-8);
    margin-left: auto;
  }
  .bws-nav a {
    font-size: var(--bws-text-md);
    font-weight: 600;
    color: var(--bws-color-ink-soft);
  }
}
/* ---------- Right-side drawer (nav on narrow screens, always: account) ---------- */
/* ---------- Full-screen menu (Repton-style 3-column takeover) ---------- */
.bws-drawer {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  grid-template-columns: 1fr;
  opacity: 0;
  visibility: hidden;
  -webkit-clip-path: inset(0 0 100% 0);
          clip-path: inset(0 0 100% 0);
  transition: opacity .3s ease, visibility 0s linear .5s, -webkit-clip-path .55s cubic-bezier(.65, 0, .35, 1);
  transition: opacity .3s ease, visibility 0s linear .5s, clip-path .55s cubic-bezier(.65, 0, .35, 1);
  transition: opacity .3s ease, visibility 0s linear .5s, clip-path .55s cubic-bezier(.65, 0, .35, 1), -webkit-clip-path .55s cubic-bezier(.65, 0, .35, 1);
}
@media (min-width: 900px) {
  .bws-drawer { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) minmax(0, 1.1fr); }
}
.bws-nav-toggle:checked ~ .bws-drawer {
  opacity: 1;
  visibility: visible;
  -webkit-clip-path: inset(0 0 0% 0);
          clip-path: inset(0 0 0% 0);
  transition: opacity .3s ease, visibility 0s linear, -webkit-clip-path .55s cubic-bezier(.65, 0, .35, 1);
  transition: opacity .3s ease, visibility 0s linear, clip-path .55s cubic-bezier(.65, 0, .35, 1);
  transition: opacity .3s ease, visibility 0s linear, clip-path .55s cubic-bezier(.65, 0, .35, 1), -webkit-clip-path .55s cubic-bezier(.65, 0, .35, 1);
}
/* The header carries no burger of its own any more (it lives in the utility
   rail instead) — with the drawer open there's nothing left for it to show,
   so the whole bar collapses out of the way rather than sitting there empty. */
.bws-nav-toggle:checked ~ .bws-header__inner { display: none; }
/* .bws-utility-rail is a page-level sibling of .bws-header, not of the
   checkbox nested inside it, so the sibling combinator can't reach it —
   :has() is needed to drive its burger→× animation from drawer state. */
body:has(.bws-nav-toggle:checked) .bws-utility-rail__burger span { background: transparent; }
body:has(.bws-nav-toggle:checked) .bws-utility-rail__burger span::before { -webkit-transform: rotate(45deg) translate(5px, 5px); transform: rotate(45deg) translate(5px, 5px); }
body:has(.bws-nav-toggle:checked) .bws-utility-rail__burger span::after { -webkit-transform: rotate(-45deg) translate(5px, -5px); transform: rotate(-45deg) translate(5px, -5px); }
/* With the drawer open the rail is only a close button. It sits at z-300
   against the drawer's z-200, so its other icons would paint straight over
   the menu beneath them — and every one of them (portal, contact, search)
   has an equivalent inside the drawer itself, so nothing is lost by folding
   them away while it's open.
   Stated as "every child that isn't the burger" rather than a list of three.
   The list silently missed .bws-contact-menu when the contact pop-out was
   added: its summary was hidden, but the <details> box itself still laid out
   and still drew a flex gap, which stretched the rail to 56px around a 32px
   button and left a block of dead teal under the ×. A list has to be updated
   every time a child is added; this doesn't. */
body:has(.bws-nav-toggle:checked) .bws-utility-rail > *:not(.bws-utility-rail__burger) {
  display: none;
}
/* The collapsed rail still occupies the top-right corner, so a column's
   first row keeps out from under it. margin, not padding: the rail overlaps
   the element's box, so the box itself has to end before the rail starts —
   padding would shift the text but leave the box running underneath. */
.bws-drawer__col > .bws-drawer__eyebrow {
  margin-right: var(--bws-rail-width);
}
/* Columns enter on their own beat once the panel starts wiping open: the
   nav/featured columns slide in from the sides first, then the photo column
   drops in a moment later for a staggered, more dramatic reveal. */
.bws-drawer__col--nav,
.bws-drawer__col--featured {
  opacity: 0;
  transition: opacity .35s ease, -webkit-transform .35s ease;
  transition: opacity .35s ease, transform .35s ease;
  transition: opacity .35s ease, transform .35s ease, -webkit-transform .35s ease;
}
.bws-drawer__col--nav { -webkit-transform: translateX(-40px); transform: translateX(-40px); }
.bws-drawer__col--featured { -webkit-transform: translateX(40px); transform: translateX(40px); }
.bws-drawer__col--image {
  opacity: 0;
  -webkit-transform: translateY(-100%);
          transform: translateY(-100%);
  transition: opacity .3s ease, -webkit-transform .3s ease;
  transition: opacity .3s ease, transform .3s ease;
  transition: opacity .3s ease, transform .3s ease, -webkit-transform .3s ease;
}
.bws-nav-toggle:checked ~ .bws-drawer .bws-drawer__col--nav,
.bws-nav-toggle:checked ~ .bws-drawer .bws-drawer__col--featured {
  opacity: 1;
  -webkit-transform: translateX(0);
          transform: translateX(0);
  transition: opacity .5s ease .2s, -webkit-transform .6s cubic-bezier(.34, 1.2, .64, 1) .2s;
  transition: opacity .5s ease .2s, transform .6s cubic-bezier(.34, 1.2, .64, 1) .2s;
  transition: opacity .5s ease .2s, transform .6s cubic-bezier(.34, 1.2, .64, 1) .2s, -webkit-transform .6s cubic-bezier(.34, 1.2, .64, 1) .2s;
}
.bws-nav-toggle:checked ~ .bws-drawer .bws-drawer__col--image {
  opacity: 1;
  -webkit-transform: translateY(0);
          transform: translateY(0);
  transition: opacity .6s ease .4s, -webkit-transform .65s cubic-bezier(.16, 1, .3, 1) .4s;
  transition: opacity .6s ease .4s, transform .65s cubic-bezier(.16, 1, .3, 1) .4s;
  transition: opacity .6s ease .4s, transform .65s cubic-bezier(.16, 1, .3, 1) .4s, -webkit-transform .65s cubic-bezier(.16, 1, .3, 1) .4s;
}
@media (prefers-reduced-motion: reduce) {
  .bws-drawer {
    -webkit-clip-path: none !important;
            clip-path: none !important;
    transition: opacity .3s ease, visibility 0s linear .3s;
  }
  .bws-nav-toggle:checked ~ .bws-drawer {
    transition: opacity .3s ease, visibility 0s linear;
  }
  .bws-drawer__col--nav,
  .bws-drawer__col--featured,
  .bws-drawer__col--image {
    -webkit-transform: none !important;
            transform: none !important;
    transition: opacity .3s ease !important;
  }
}
.bws-drawer__col {
  padding: var(--bws-space-8) var(--bws-space-6);
  overflow-y: auto;
}
.bws-drawer__col--nav {
  background: var(--bws-color-surface);
  display: flex;
  flex-direction: column;
}
.bws-drawer__col--image {
  display: none;
  background-size: cover;
  background-position: center;
  position: relative;
}
@media (min-width: 900px) {
  .bws-drawer__col--image { display: block; }
}
.bws-drawer__col--featured {
  background: var(--bws-color-bg);
  display: none;
  flex-direction: column;
}
@media (min-width: 900px) {
  .bws-drawer__col--featured { display: flex; }
}
/* Below the 3-column breakpoint the featured column stacks under the links
   rather than vanishing: it carries the BEACON portal wordmark, the social
   links and the Explore More cards, and none of those appear anywhere else
   in the drawer — on a phone they were simply unreachable. The drawer itself
   becomes the scroller so the two stacked columns read as one list instead
   of two nested scroll areas. */
@media (max-width: 899px) {
  .bws-drawer { align-content: start; overflow-y: auto; }
  .bws-drawer__col { overflow-y: visible; }
  .bws-drawer__col--featured { display: flex; }
}
/* A grid track's automatic minimum is its widest unbreakable content, so
   on some phones (font metrics wider than the desktop test browser) the
   Connect/Portal row or a long link stretched a column past the screen
   and the whole drawer scrolled sideways — the third nav level under
   "Our Work" (Educational Technology's six subsections) turned out long
   enough to trigger the same thing at the 3-column desktop width too.
   overflow-x/min-width/overflow-wrap apply at every width for that
   reason, not just narrow ones (the min-width:900px grid-template-columns
   fix above handles the desktop track-sizing half of the same bug). */
.bws-drawer { overflow-x: hidden; }
.bws-drawer__col { min-width: 0; }
.bws-drawer__link,
.bws-drawer__group summary,
.bws-drawer__sublinks a,
.bws-drawer__subgroup summary,
.bws-drawer__subsublinks a,
.bws-drawer__footer-links a,
.bws-drawer__feature-text {
  min-width: 0;
  overflow-wrap: anywhere;
}
@media (max-width: 899px) {
  .bws-drawer { grid-template-columns: minmax(0, 1fr); }
  .bws-drawer__footer-links {
    flex-wrap: wrap;
    row-gap: var(--bws-space-5);
  }
  .bws-drawer__col--nav,
  .bws-drawer__col--featured { -webkit-transform: translateY(16px); transform: translateY(16px); }
  .bws-nav-toggle:checked ~ .bws-drawer .bws-drawer__col--nav,
  .bws-nav-toggle:checked ~ .bws-drawer .bws-drawer__col--featured { -webkit-transform: none; transform: none; }
}
.bws-drawer__eyebrow {
  font-family: var(--bws-font-display);
  font-weight: 700;
  font-size: var(--bws-text-sm);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--bws-color-ink-soft);
  margin: 0 0 var(--bws-space-5);
}
.bws-drawer__nav {
  display: flex;
  flex-direction: column;
  gap: var(--bws-space-1);
}
/* Direct links (News, Contact) sit at the same visual weight as a closed
   accordion group, so the whole list reads as one consistent hierarchy. */
.bws-drawer__link,
.bws-drawer__group summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--bws-space-4) 0;
  font-family: var(--bws-font-display);
  font-weight: 600;
  font-size: var(--bws-text-lg);
  color: var(--bws-color-ink);
  border-bottom: 1px solid var(--bws-color-line);
  cursor: pointer;
}
/* Repton-style expandable category — native <details>/<summary>, no JS. */
.bws-drawer__group summary { list-style: none; }
.bws-drawer__group summary::-webkit-details-marker { display: none; }
.bws-drawer__group summary::after {
  content: "";
  width: 8px;
  height: 8px;
  flex-shrink: 0;
  border-right: 2px solid var(--bws-color-ink-soft);
  border-top: 2px solid var(--bws-color-ink-soft);
  -webkit-transform: rotate(135deg);
          transform: rotate(135deg);
  transition: -webkit-transform .2s ease;
  transition: transform .2s ease;
  transition: transform .2s ease, -webkit-transform .2s ease;
  margin-left: var(--bws-space-3);
}
/* Child combinator: only the group's own arrow turns; a nested subgroup's
   arrow follows its own open state. */
.bws-drawer__group[open] > summary::after { -webkit-transform: rotate(225deg); transform: rotate(225deg); }
.bws-drawer__sublinks {
  display: flex;
  flex-direction: column;
  padding: var(--bws-space-2) 0 var(--bws-space-3) var(--bws-space-4);
}
.bws-drawer__sublinks a {
  padding: var(--bws-space-2) 0;
  font-size: var(--bws-text-sm);
  font-weight: 500;
  color: var(--bws-color-ink-soft);
}
/* A third nav level, one step further than .bws-drawer__group: same
   disclosure-triangle idea, sized down and without a border so it reads as
   nested rather than another peer category. */
.bws-drawer__subgroup summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--bws-space-2) 0;
  font-size: var(--bws-text-sm);
  font-weight: 500;
  color: var(--bws-color-ink-soft);
  cursor: pointer;
  list-style: none;
}
.bws-drawer__subgroup summary::-webkit-details-marker { display: none; }
.bws-drawer__subgroup summary::after {
  content: "";
  width: 6px;
  height: 6px;
  flex-shrink: 0;
  border-right: 2px solid var(--bws-color-ink-soft);
  border-top: 2px solid var(--bws-color-ink-soft);
  -webkit-transform: rotate(135deg);
          transform: rotate(135deg);
  transition: -webkit-transform .2s ease;
  transition: transform .2s ease;
  transition: transform .2s ease, -webkit-transform .2s ease;
  margin-left: var(--bws-space-3);
}
.bws-drawer__subgroup[open] summary::after { -webkit-transform: rotate(225deg); transform: rotate(225deg); }
.bws-drawer__subsublinks {
  display: flex;
  flex-direction: column;
  padding: var(--bws-space-1) 0 var(--bws-space-2) var(--bws-space-4);
}
.bws-drawer__subsublinks a {
  padding: var(--bws-space-1) 0;
  font-size: var(--bws-text-xs);
  color: var(--bws-color-ink-soft);
  opacity: .85;
}
.bws-drawer__search {
  display: flex;
  gap: var(--bws-space-2);
  margin-top: auto;
  padding-top: var(--bws-space-6);
}
.bws-drawer__search input[type="search"] {
  flex-grow: 1;
  min-width: 0;
  padding: var(--bws-space-3) var(--bws-space-4);
  border: 1px solid var(--bws-color-line);
  border-radius: var(--bws-radius-sm);
}
.bws-drawer__search button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  flex-shrink: 0;
  border: none;
  border-radius: var(--bws-radius-sm);
  background: var(--bws-color-brand);
  color: #fff;
  cursor: pointer;
}
/* Featured column: thumbnail + title + subtitle, like Repton's group list. */
.bws-drawer__feature {
  display: flex;
  align-items: center;
  gap: var(--bws-space-4);
  padding-block: var(--bws-space-4);
  border-bottom: 1px solid var(--bws-color-line);
}
.bws-drawer__feature-thumb {
  width: 72px;
  height: 60px;
  flex-shrink: 0;
  border-radius: var(--bws-radius-sm);
  background-size: cover;
  background-position: center;
  background-color: var(--bws-color-brand-100);
}
.bws-drawer__feature-text { display: flex; flex-direction: column; gap: 2px; }
.bws-drawer__feature-text strong {
  font-family: var(--bws-font-display);
  font-size: var(--bws-text-md);
  color: var(--bws-color-ink);
}
.bws-drawer__feature-text small { color: var(--bws-color-ink-soft); }
.bws-drawer__feature:hover .bws-drawer__feature-text strong { color: var(--bws-color-brand); }
.bws-drawer__footer-links {
  display: flex;
  gap: var(--bws-space-8);
  margin-top: var(--bws-space-6);
}
.bws-drawer__footer-links a {
  display: block;
  padding-block: var(--bws-space-1);
  font-size: var(--bws-text-sm);
  color: var(--bws-color-ink-soft);
}
/* BEACON wordmark in place of the "Portal" label. Its letters sit low in the
   image (the lighthouse fills the top), so it is aligned by the letters'
   baseline, not its box: 24px tall, lifted 4px so "beacon" rests on the same
   line as the neighbouring "Connect" label, and the 31px gap brings the box
   back to where the Connect links start, keeping both columns' rows level. */
.bws-drawer__beacon-logo {
  display: block;
  width: auto;
  height: 24px;
  margin-top: -4px;
  /* Same left-edge correction as the rail's pop-out: 8.2% of the rendered
     width (24px tall × 439/116 ≈ 91px) is empty before the lighthouse, which
     otherwise leaves the mark indented against the portal links below. */
  margin-left: -7px;
  margin-bottom: 31px;
}
/* The drawer's twin of .bws-portal-menu__badge, in the footer's smaller,
   quieter type rather than the pop-out's. */
.bws-drawer__badge {
  display: inline-block;
  margin-left: var(--bws-space-2);
  padding: 1px 7px;
  font-size: var(--bws-text-xs);
  font-weight: 600;
  color: var(--bws-color-brand);
  background: var(--bws-color-brand-100);
  border-radius: var(--bws-radius-pill);
  vertical-align: middle;
}
/* ---------- Enrollment tab (fixed left edge, repton.org style) ---------- */
/* Vertical tab pinned to the left edge rather than a strip across the top,
   so it stays put through the whole scroll. It's fixed and out of flow, so
   it reserves no height — nothing below needs to offset around it. */
.bws-banner {
  position: fixed;
  left: 0;
  top: 50%;
  -webkit-transform: translateY(-50%);
          transform: translateY(-50%);
  z-index: 260;
  display: flex;
  flex-direction: column;
  transition: opacity .2s ease, -webkit-transform .3s ease;
  transition: transform .3s ease, opacity .2s ease;
  transition: transform .3s ease, opacity .2s ease, -webkit-transform .3s ease;
  font-weight: 500;
  font-size: var(--bws-text-sm);
  /* One pill, not two: the background and rounding live on the container so
     the label and CTA read as a single button rather than two separate
     rounded blocks stacked with a gap between them. Written as LEFT-side
     rounding on purpose — rotate(180deg) on the children below flips the
     box, so these corners land on the right, the edge facing into the page
     rather than the viewport edge the tab is anchored to. */
  border-radius: var(--bws-radius-sm) 0 0 var(--bws-radius-sm);
  overflow: hidden;
  background: var(--bws-banner-bg);
  color: var(--bws-banner-fg);
  --bws-banner-bg: var(--bws-color-ink);
  --bws-banner-fg: #fff;
}
.bws-banner--open { --bws-banner-bg: var(--bws-color-success); }
.bws-banner--reservation { --bws-banner-bg: var(--bws-color-accent); --bws-banner-fg: var(--bws-color-ink); }
.bws-banner--closed { --bws-banner-bg: var(--bws-color-ink); }
.bws-banner__label,
.bws-banner__cta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--bws-space-2);
  /* Reads bottom-to-top up the left edge. */
  -webkit-writing-mode: vertical-rl;
      -ms-writing-mode: tb-rl;
          writing-mode: vertical-rl;
  -webkit-transform: rotate(180deg);
          transform: rotate(180deg);
  /* Narrow on the physical horizontal axis — the tab overlays the page's own
     left gutter, so every extra pixel of width crowds the body text. */
  padding: var(--bws-space-5) var(--bws-space-2);
  font-size: var(--bws-text-xs);
}
/* A hairline instead of a gap, so the CTA still reads as its own row within
   the one pill rather than the whole tab looking like a single flat block.
   Set as border-TOP on the label (not border-bottom on the CTA): both boxes
   carry rotate(180deg), which swaps each box's own top/bottom edge when it
   paints, so a border-top here is what lands, visually, on the seam between
   the two rows rather than on the pill's outer top edge. */
.bws-banner__label { border-top: 1px solid rgba(255, 255, 255, .25); }
.bws-banner--reservation .bws-banner__label { border-top-color: rgba(22, 31, 28, .18); }
/* Icons are replaced elements, so writing-mode leaves them alone but the
   parent's rotate(180deg) still flips them — undo just the rotation. */
.bws-banner__label svg,
.bws-banner__cta svg {
  -webkit-transform: rotate(180deg);
          transform: rotate(180deg);
  /* The SVGs carry width/height attributes that would otherwise set the
     tab's physical width — override so the padding decides it. */
  width: 14px;
  height: 14px;
}
.bws-banner__cta {
  font-weight: 600;
  text-decoration: none;
  letter-spacing: .04em;
  text-transform: uppercase;
  font-size: var(--bws-text-xs);
}
/* The whole tab is one link now, so it lights up as a unit rather than only
   the Inquire half responding to the pointer. */
.bws-banner:hover { -webkit-filter: brightness(1.15); filter: brightness(1.15); }
.bws-banner:focus-visible {
  outline: 2px solid var(--bws-color-accent);
  outline-offset: 3px;
}
/* Slide it off the left edge while the drawer is open. */
body:has(.bws-nav-toggle:checked) .bws-banner {
  -webkit-transform: translateY(-50%) translateX(-100%);
          transform: translateY(-50%) translateX(-100%);
  opacity: 0;
  pointer-events: none;
}
@media (max-width: 767px) {
  /* A vertical left-edge tab overlays body text at phone widths (there's no
     40px gutter to reserve for it) — so on phones this becomes a horizontal
     pill floating above the bottom-left corner instead, generously padded
     since Inquire is the single most important tap on the whole site. */
  .bws-banner {
    top: auto;
    bottom: var(--bws-space-4);
    left: var(--bws-space-4);
    -webkit-transform: none;
            transform: none;
    flex-direction: row;
    border-radius: var(--bws-radius-pill, 999px);
  }
  /* The full status ("Enrollment is open for SY 2026-2027") doesn't fit next
     to the CTA at this width. Dropped visually, not from the experience —
     the anchor's own aria-label still carries the full text to assistive
     tech, and the pill's colour still signals open / reservation / closed. */
  .bws-banner__label { display: none; }
  .bws-banner__cta {
    -webkit-writing-mode: horizontal-tb;
        -ms-writing-mode: lr-tb;
            writing-mode: horizontal-tb;
    -webkit-transform: none;
            transform: none;
    padding: var(--bws-space-4) var(--bws-space-5);
    font-size: var(--bws-text-sm);
  }
  .bws-banner__cta svg {
    -webkit-transform: none;
            transform: none;
    width: 18px;
    height: 18px;
  }
  /* Drops out of view downward instead of sideways, matching its new
     bottom-anchored position. */
  body:has(.bws-nav-toggle:checked) .bws-banner {
    -webkit-transform: translateY(150%);
            transform: translateY(150%);
  }
  /* Both are bottom-left, phone-only fixed elements. Rather than guessing an
     offset to lift the pill above consent — its height varies with copy
     length and screen width (170-270px across common phone sizes) — hide
     the pill outright while consent is up. It reappears the instant the
     visitor answers either consent button; admissions stays one tap away
     in the drawer meanwhile. */
  body:has(#bws-consent:not([hidden])) .bws-banner {
    display: none;
  }
}
/* ---------- Forms ---------- */
.bws-field {
  display: flex;
  flex-direction: column;
  gap: var(--bws-space-1);
  margin-bottom: var(--bws-space-4);
}
.bws-field label {
  font-weight: 600;
  font-size: var(--bws-text-sm);
  color: var(--bws-color-ink);
}
.bws-input {
  /* A text input sizes itself to about 20 characters unless told otherwise,
     and min-width:auto lets it refuse to shrink below that. At the default
     font it happens to fit the column, so this looked fine for months — but
     turn on Android's text scaling and those 20 characters outgrow the card,
     the input pushes past its edge and the page clips it. The <select> never
     did this because its wrapper already floors it at min-width:0.
     Stated explicitly so the controls follow their column at any font size. */
  width: 100%;
  max-width: 100%;
  min-width: 0;
  padding: var(--bws-space-2);
  border: 1px solid var(--bws-color-line);
  border-radius: var(--bws-radius-sm);
  background: var(--bws-color-surface);
  color: var(--bws-color-ink);
  font-size: var(--bws-text-md);
  transition: box-shadow .15s ease;
}
/* Same reasoning for the label that wraps each control: a flex item defaults
   to min-width:auto, so a stubborn child can hold the whole field open. */
.bws-field { min-width: 0; }
.bws-input:focus {
  outline: 2px solid var(--bws-color-brand-400);
  outline-offset: 1px;
  box-shadow: 0 0 0 3px var(--bws-color-brand-100);
}
/* ---------- Custom select (admissions: Grade level, Campus) ---------- */
/* Pointer-fine devices only (see initCustomSelects in home.js) — the
   native <select> stays in the DOM and keeps .bws-input's look until and
   unless JS successfully enhances it (.is-enhanced), so touch devices and
   a JS failure both simply get the plain native control, unchanged. */
.bws-select { position: relative; }
.bws-select.is-enhanced .bws-select__native {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
}
.bws-select__button {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bws-space-2);
  padding: var(--bws-space-2);
  border: 1px solid var(--bws-color-line);
  border-radius: var(--bws-radius-sm);
  background: var(--bws-color-surface);
  color: var(--bws-color-ink);
  font-family: inherit;
  font-size: var(--bws-text-md);
  text-align: left;
  cursor: pointer;
  transition: box-shadow .15s ease;
}
.bws-select__button:focus-visible {
  outline: 2px solid var(--bws-color-brand-400);
  outline-offset: 1px;
  box-shadow: 0 0 0 3px var(--bws-color-brand-100);
}
.bws-select__chevron {
  flex-shrink: 0;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--bws-color-ink-soft);
  border-top: 2px solid var(--bws-color-ink-soft);
  -webkit-transform: rotate(135deg);
          transform: rotate(135deg);
  transition: -webkit-transform .2s ease;
  transition: transform .2s ease;
  transition: transform .2s ease, -webkit-transform .2s ease;
}
.bws-select.is-open .bws-select__chevron { -webkit-transform: rotate(225deg); transform: rotate(225deg); }
.bws-select__panel {
  position: absolute;
  top: calc(100% + var(--bws-space-1));
  left: 0;
  right: 0;
  z-index: 20;
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .25s cubic-bezier(.16, 1, .3, 1);
  transition: grid-template-rows .25s cubic-bezier(.16, 1, .3, 1), -ms-grid-rows .25s cubic-bezier(.16, 1, .3, 1);
}
.bws-select.is-open .bws-select__panel { grid-template-rows: 1fr; }
.bws-select__listbox {
  list-style: none;
  overflow-y: auto;
  min-height: 0;
  max-height: 240px;
  margin: 0;
  padding: var(--bws-space-2) 0;
  background: var(--bws-color-surface);
  border: 1px solid var(--bws-color-line);
  border-radius: var(--bws-radius-sm);
  box-shadow: var(--bws-shadow-md);
}
.bws-select__option {
  padding: var(--bws-space-2) var(--bws-space-3);
  font-size: var(--bws-text-md);
  color: var(--bws-color-ink);
  cursor: pointer;
}
.bws-select__option:hover,
.bws-select__option.is-active {
  background: var(--bws-color-brand-100);
}
@media (prefers-reduced-motion: reduce) {
  .bws-select__panel { transition: none; }
  .bws-input,
  .bws-select__button,
  .bws-select__chevron { transition: none; }
}
.bws-error {
  color: var(--bws-color-danger);
  font-size: var(--bws-text-xs);
  -webkit-animation: bws-error-in .15s ease-out both;
          animation: bws-error-in .15s ease-out both;
}
@-webkit-keyframes bws-error-in {
  from { opacity: 0; -webkit-transform: translateY(-2px); transform: translateY(-2px); }
  to { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); }
}
@keyframes bws-error-in {
  from { opacity: 0; -webkit-transform: translateY(-2px); transform: translateY(-2px); }
  to { opacity: 1; -webkit-transform: translateY(0); transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .bws-error { -webkit-animation: none; animation: none; }
}
/* Same margin-bottom .bws-field already carries: without it these sat flush
   against each other and against whatever followed (the submit button, on
   the admissions inquiry form). */
.bws-check {
  display: flex;
  align-items: flex-start;
  gap: var(--bws-space-2);
  font-size: var(--bws-text-sm);
  color: var(--bws-color-ink-soft);
  margin-bottom: var(--bws-space-4);
}
/* Honeypot — visually hidden, still readable to screen readers is NOT desired here. */
.bws-hp {
  position: absolute !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  left: -9999px;
}
/* ---------- Alerts ---------- */
.bws-alert {
  padding: var(--bws-space-3) var(--bws-space-4);
  border-radius: var(--bws-radius-sm);
  font-size: var(--bws-text-sm);
  border: 1px solid var(--bws-color-line);
  background: var(--bws-color-surface);
}
.bws-alert--danger {
  background: #fbe9e6;
  border-color: var(--bws-color-danger);
  color: var(--bws-color-danger);
}
/* ---------- Consent banner ---------- */
.bws-consent {
  position: fixed;
  left: var(--bws-space-4);
  right: var(--bws-space-4);
  bottom: var(--bws-space-4);
  z-index: 200;
  background: var(--bws-color-surface);
  border: 1px solid var(--bws-color-line);
  border-radius: var(--bws-radius-md);
  padding: var(--bws-space-4);
  box-shadow: var(--bws-shadow-md);
}
.bws-consent__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bws-space-3);
  margin-top: var(--bws-space-3);
}
/* ---------- Eyebrow label ---------- */
.bws-eyebrow {
  font-family: var(--bws-font-display);
  font-weight: 700;
  font-size: var(--bws-text-xs);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--bws-color-brand-600);
  margin: 0 0 var(--bws-space-2);
}
/* ---------- Screen-reader-only utility ---------- */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
/* ---------- Utility rail: fixed, hugs its own icons (ismanila.org-style) ---------- */
/* Sitewide (not confined to the hero), pinned to the top-right corner, flush
   with the header. Height comes purely from its content — it never spans the
   viewport — and it sits above everything else (banner 260, header 250,
   drawer 200) since it now carries the drawer's only open/close control and
   must stay reachable regardless of what else is on screen. */
.bws-utility-rail {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 300;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--bws-rail-gap);
  width: var(--bws-rail-width);
  padding: var(--bws-rail-pad) 0;
  background: var(--bws-color-brand);
  border-radius: 0 0 0 var(--bws-radius-md);
}
.bws-utility-rail__rule {
  width: 32px;
  height: 2px;
  background: rgba(255, 255, 255, .3);
  border-radius: var(--bws-radius-pill);
}
.bws-utility-rail__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--bws-rail-icon);
  height: var(--bws-rail-icon);
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .3);
  background: rgba(255, 255, 255, .12);
  color: #fff;
  cursor: pointer;
}
.bws-utility-rail__icon:hover { background: rgba(255, 255, 255, .22); }
/* The BEACON mark is a white PNG rather than an inline SVG, so it needs its
   own sizing — the img reset sets max-width but not a height. */
.bws-utility-rail__icon img {
  width: 26px;
  height: 26px;
  -o-object-fit: contain;
     object-fit: contain;
  /* Optical, not geometric, centring. The mark's ink sits low and right
     inside its square canvas: its alpha-weighted centre of mass is about
     12% down and right of the canvas centre, so centring the box leaves it
     looking low and right. Nudging by roughly half that correction lands it
     where the eye expects without overshooting. */
  -webkit-transform: translate(-6%, -6%);
          transform: translate(-6%, -6%);
}
.bws-utility-rail__burger span,
.bws-utility-rail__burger span::before,
.bws-utility-rail__burger span::after {
  content: "";
  display: block;
  width: 22px;
  height: 2px;
  background: #fff;
  position: relative;
  transition: opacity .15s ease, -webkit-transform .15s ease;
  transition: transform .15s ease, opacity .15s ease;
  transition: transform .15s ease, opacity .15s ease, -webkit-transform .15s ease;
}
.bws-utility-rail__burger span::before { top: -7px; }
.bws-utility-rail__burger span::after { top: 5px; }
/* ---------- Site search (toggled from the utility rail) ---------- */
.bws-site-search {
  position: fixed;
  top: var(--bws-header-height);
  right: var(--bws-rail-width);
  z-index: 301;
  display: flex;
  flex-direction: column;
  gap: var(--bws-space-3);
  max-width: 360px;
  background: var(--bws-color-surface);
  border: 1px solid var(--bws-color-line);
  border-radius: var(--bws-radius-md);
  padding: var(--bws-space-3);
  box-shadow: var(--bws-shadow-md);
}
.bws-site-search[hidden] { display: none; }
.bws-site-search__form {
  display: flex;
  gap: var(--bws-space-2);
}
.bws-site-search input[type="search"] {
  /* Fills whatever the button doesn't need, rather than a fixed min-width
     fighting the button for space inside the popover's own max-width and
     forcing the button's box past the popover's rounded corner. */
  flex: 1;
  min-width: 0;
  padding: var(--bws-space-2) var(--bws-space-3);
  border: 1px solid var(--bws-color-line);
  border-radius: var(--bws-radius-sm);
}
.bws-site-search button {
  flex-shrink: 0;
  padding: var(--bws-space-2) var(--bws-space-4);
  border: none;
  border-radius: var(--bws-radius-sm);
  background: var(--bws-color-brand);
  color: #fff;
  font-weight: 600;
  cursor: pointer;
}
@media (max-width: 767px) {
  .bws-site-search {
    left: var(--bws-space-3);
    right: calc(var(--bws-rail-width) + var(--bws-space-2));
    max-width: none;
  }
}
/* ---------- Search suggestion chips (rail popover, drawer, results page) ---------- */
.bws-search-suggestions__label {
  margin: 0 0 var(--bws-space-2);
  font-size: var(--bws-text-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--bws-color-ink-soft);
}
.bws-search-suggestions__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bws-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.bws-search-suggestions__list a {
  display: inline-block;
  padding: var(--bws-space-1) var(--bws-space-3);
  border: 1px solid var(--bws-color-line);
  border-radius: var(--bws-radius-pill, 999px);
  font-size: var(--bws-text-sm);
  color: var(--bws-color-ink);
  text-decoration: none;
  background: var(--bws-color-surface-sunk, var(--bws-color-brand-100));
  transition: background .15s ease, border-color .15s ease;
}
.bws-search-suggestions__list a:hover,
.bws-search-suggestions__list a:focus-visible {
  border-color: var(--bws-color-brand);
  background: var(--bws-color-brand-100);
}
/* Results page: not a floating popover, just a block under the note text. */
.bws-search .bws-search-suggestions { margin-top: var(--bws-space-5); }
/* ---------- Parallax (hero + mid-page image) ---------- */
.bws-parallax {
  position: relative;
  overflow: hidden;
  min-height: 100vh;
  display: flex;
  align-items: center;
}
.bws-parallax__bg {
  position: absolute;
  inset: -20% 0;
  z-index: 0;
  background-size: cover;
  background-position: center;
  background-color: var(--bws-color-brand-100);
  will-change: transform;
}
/* Pinned in place while the intro section (opaque, higher z-index, right
   after it in the page) scrolls up from below and covers it — no image on
   the intro itself, just this section staying put underneath. */
/* Pulled up by the banner+header's combined height so it fills the page
   from the very top — banner and header (both higher z-index) then overlay
   its top edge instead of sitting above it, which is what makes a
   transparent header actually reveal the hero photo behind it. */
.bws-hero {
  position: -webkit-sticky;
  position: sticky;
  /* Pinned to the very top of the viewport, not below the header: with
     the negative margin pulling it up under the header, a sticky offset of
     the header's height would win at scroll 0 and push the hero back down,
     leaving a blank bar behind the transparent header. */
  top: 0;
  margin-top: calc(-1 * var(--bws-header-height));
  z-index: 0;
}
/* Same pinned-underneath technique as the hero above, but mid-page: this
   parallax photo stays put (no negative margin needed — it isn't trying to
   reach the very top of the page) while the next section (Our Core Values,
   opaque, higher z-index) scrolls up from below and covers it. */
.bws-parallax--image {
  position: -webkit-sticky;
  position: sticky;
  top: var(--bws-header-height);
  z-index: 0;
}
/* Full-photo dark wash (ismanila.org reference) so white logo/nav/caption
   text stays legible everywhere over the hero, not just near the top edge.
   A real element (not a ::before), placed right after .bws-parallax__bg in
   the DOM, so it paints above the photo by plain DOM order alone — the
   explicit z-index is a second, redundant guarantee, not the only thing
   holding this up. Slightly darker at the very top/bottom for the header
   and play-button rows specifically. */
.bws-hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 5;
  /* Legibility bands only, ismanila.org style: a dark fade at the top for
     the white logo and nav while the header is transparent, and one at the
     bottom for the play and pause buttons. The middle stays clear so the
     hero video shows in full colour. */
  background: linear-gradient(
    180deg,
    rgba(0, 0, 0, .62) 0%,
    rgba(0, 0, 0, 0) 28%,
    rgba(0, 0, 0, 0) 74%,
    rgba(0, 0, 0, .5) 100%
  );
  pointer-events: none;
}
.bws-hero__play-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .92);
  color: var(--bws-color-brand);
}
/* Background montage: sits between the parallax photo (z 0) and the scrim
   (z 5), so the same dark wash keeps header and buttons legible over the
   moving picture. Starts transparent and fades in once it is actually
   playing, so a slow download shows the photo rather than a black box. */
.bws-hero__video {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  -o-object-fit: cover;
     object-fit: cover;
  opacity: 0;
  transition: opacity .6s ease;
  pointer-events: none;
}
.bws-hero__video.is-playing { opacity: 1; }
.bws-hero__pause {
  position: absolute;
  /* Bottom-right, not bottom-left: the Inquire tab/pill lives at the left
     edge at every breakpoint (the desktop vertical tab, and the phone pill
     introduced alongside it), and directly overlapped this button there on
     phones. */
  right: var(--bws-space-6);
  bottom: var(--bws-space-6);
  z-index: 6;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .7);
  background: rgba(0, 0, 0, .35);
  color: #fff;
  cursor: pointer;
}
.bws-hero__pause:hover { background: rgba(0, 0, 0, .55); }
.bws-hero__pause .bws-hero__pause-icon--play { display: none; }
.bws-hero__pause.is-paused .bws-hero__pause-icon--play { display: inline; }
.bws-hero__pause.is-paused .bws-hero__pause-icon--pause { display: none; }
@media (prefers-reduced-motion: reduce) {
  .bws-hero__video, .bws-hero__pause { display: none; }
}
.bws-parallax__caption {
  position: relative;
  z-index: 1;
  color: #fff;
}
@media (prefers-reduced-motion: reduce) {
  .bws-parallax__bg { -webkit-transform: none !important; transform: none !important; }
}
@media (prefers-reduced-motion: reduce) {
  .bws-level-tile,
  .bws-level-tile__photo,
  .bws-level-tile__name,
  .bws-level-tile__name::after {
    transition: none !important;
  }
  .bws-level-tile:hover,
  .bws-level-tile:focus-visible,
  .bws-level-tile:hover .bws-level-tile__photo,
  .bws-level-tile:focus-visible .bws-level-tile__photo,
  .bws-level-tile:hover .bws-level-tile__name,
  .bws-level-tile:focus-visible .bws-level-tile__name {
    -webkit-transform: none !important;
            transform: none !important;
  }
}
/* ---------- Video modal ---------- */
.bws-video-modal {
  border: none;
  border-radius: var(--bws-radius-md);
  padding: 0;
  max-width: min(90vw, 960px);
  width: 100%;
  background: #000;
}
.bws-video-modal::-webkit-backdrop { background: rgba(22, 31, 28, .75); }
.bws-video-modal::backdrop { background: rgba(22, 31, 28, .75); }
.bws-video-modal__frame { position: relative; aspect-ratio: 16 / 9; }
.bws-video-modal__frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.bws-video-modal__close {
  position: absolute;
  top: -40px;
  right: 0;
  background: transparent;
  color: #fff;
  border: none;
  font-size: 28px;
  line-height: 1;
  cursor: pointer;
}
/* ---------- Intro block ---------- */
/* Same brand-teal band treatment as Core Values / Learning Spaces. The
   bottom border is dropped — it was teal-on-cream for definition against the
   page background, and would be invisible against this same teal fill. */
.bws-intro {
  position: relative;
  z-index: 1;
  /* The splash screen's texture, once, centred on the band (no tiling). The
     glow and vignette match the splash too. */
  background:
    radial-gradient(ellipse at 50% 45%, rgba(58, 163, 159, .3) 0%, rgba(0, 80, 81, 0) 60%),
    radial-gradient(ellipse at 50% 50%, rgba(0, 0, 0, 0) 60%, rgba(0, 30, 31, .35) 100%),
    var(--bws-color-brand) url("/assets/images/splash-texture.jpg") center / cover no-repeat;
}
.bws-intro__inner { text-align: center; }
/* Two classes needed on each: the global `.bws h2` / `.bws p` / `.bws-eyebrow`
   rules are class+element (or a single class competing on source order) and
   would otherwise win, painting this text in dark ink/teal on a teal fill. */
.bws-intro .bws-eyebrow { color: #fff; opacity: .8; }
/* #intro (id) rather than .bws-intro (class) for the heading specifically:
   the global `.bws h1`/`.bws h2` rules are also class+element, a
   same-specificity tie that would otherwise depend on source order — the id
   wins outright, no ambiguity. Targets both levels: the home page's intro
   has no page-hero block above it, so block.blade.php promotes this
   heading to an <h1> there, while an inner-page "intro" block (if any)
   would keep it as an <h2>. */
/* Scoped to the home band's class too, so an inner-page section that
   happens to be keyed "intro" keeps its normal heading colour. */
#intro.bws-intro h1, #intro.bws-intro h2 { font-size: 2.5rem; color: #fff; }
.bws-intro .bws-intro__lede { font-size: var(--bws-text-lg); color: #fff; margin-top: var(--bws-space-5); }
/* ---------- Split: photo + text, alternating sides ---------- */
/* Explicit z-index + opaque background: the hero above is position:sticky
   and stays physically in place behind everything else on the page, so
   every section after it needs its own solid fill or the hero shows
   through wherever a child is left transparent. */
.bws-split { position: relative; z-index: 1; background: var(--bws-color-bg); padding: 0; }
/* overflow-x:clip so the reveal transforms below can never reach the page
   box. They translate full-bleed panels sideways, which made the document
   64px wider than the viewport until each section revealed — and a mobile
   browser answers that by zooming out, which drags every fixed element (the
   rail, the drawer, the consent bar) off-position along with it. Clipping
   here contains the motion without making the track a scroll container. */
.bws-split__track { position: relative; overflow-x: clip; }
/* :not([hidden]) rather than a bare display:flex — otherwise this rule's
   specificity ties with the browser's [hidden]{display:none} and (being an
   author rule) wins the tie, so a "hidden" slide would render anyway.
   78vh, not the full viewport: at 100vh, short text (a few lines under an
   eyebrow) left large empty margins above/below in the centred text column,
   and the image panel — sized off this same slide height — was reported as
   too large as a result. Shrinking the slide brings both down together. */
.bws-split__slide:not([hidden]) { display: flex; flex-wrap: wrap; align-items: stretch; min-height: 78vh; }
/* Sits on the block that follows a paired split section, marking the exact
   cross where that section's own top edge meets the shared vertical divider
   — a Repton-style seal at the intersection. Fixed in place (no scroll
   tracking) and shown at its own natural shape, no circular crop. */
.bws-split__crest {
  position: absolute;
  top: 0;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
          transform: translate(-50%, -50%);
  z-index: 3;
  width: auto;
  height: 72px;
  -webkit-filter: drop-shadow(0 4px 10px rgba(22, 31, 28, .35));
          filter: drop-shadow(0 4px 10px rgba(22, 31, 28, .35));
}
.bws-split--image-right .bws-split__slide { flex-direction: row-reverse; }
.bws-split__image {
  flex: 1 1 480px;
  min-height: 420px;
  background-size: cover;
  background-position: center top;
  background-color: var(--bws-color-brand-100);
}
.bws-split__text {
  flex: 1 1 480px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: stretch;
  background: var(--bws-color-bg);
  padding: var(--bws-space-10) var(--bws-space-8);
  border-left: 1.5px solid var(--bws-color-brand-600);
}
/* Both fixed rails sit ON TOP of the page rather than reserving layout
   space, so a split's text column can end up flush against one of them
   depending on which edge it lands on: image_side "left" puts the text on
   the right (under the utility rail), "right" + row-reverse below puts it
   on the left (under the enrollment tab) — either way the last line or the
   CTA button was sitting right against the rail with no gutter. */
.bws-split--image-left .bws-split__text {
  padding-right: calc(var(--bws-rail-width) + var(--bws-space-6));
}
@media (min-width: 768px) {
  /* The enrollment tab only exists at this width and up (hidden on phones,
     see .bws-banner above) — no need to reserve space for it below that. */
  .bws-split--image-right .bws-split__text {
    padding-left: calc(var(--bws-tab-width) + var(--bws-space-6));
  }
}
.bws-split--image-right .bws-split__text { border-left: none; border-right: 1.5px solid var(--bws-color-brand-600); }
/* Each half slides in from the screen edge it actually sits on, meeting in
   the middle — set up in JS (home.js: initScrollReveal), which only ever adds
   the "bws-reveal-ready" class when IntersectionObserver exists and motion
   isn't reduced. Without it these rules never apply, so content is visible
   by default with no JS required. */
.bws-reveal-ready .bws-split__image,
.bws-reveal-ready .bws-split__text {
  opacity: 0;
  transition: opacity .7s ease, -webkit-transform .7s cubic-bezier(.16, 1, .3, 1);
  transition: opacity .7s ease, transform .7s cubic-bezier(.16, 1, .3, 1);
  transition: opacity .7s ease, transform .7s cubic-bezier(.16, 1, .3, 1), -webkit-transform .7s cubic-bezier(.16, 1, .3, 1);
}
/* Stacked below 900px, so the halves no longer sit against the edges they
   would slide in from — they rise into place instead. This is also the
   safe direction: a vertical offset can't widen the document. */
.bws-reveal-ready .bws-split__image,
.bws-reveal-ready .bws-split__text { -webkit-transform: translateY(32px); transform: translateY(32px); }
@media (min-width: 900px) {
  .bws-reveal-ready .bws-split--image-left .bws-split__image { -webkit-transform: translateX(-64px); transform: translateX(-64px); }
  .bws-reveal-ready .bws-split--image-left .bws-split__text { -webkit-transform: translateX(64px); transform: translateX(64px); }
  .bws-reveal-ready .bws-split--image-right .bws-split__image { -webkit-transform: translateX(64px); transform: translateX(64px); }
  .bws-reveal-ready .bws-split--image-right .bws-split__text { -webkit-transform: translateX(-64px); transform: translateX(-64px); }
}
.bws-split.is-visible .bws-split__image,
.bws-split.is-visible .bws-split__text {
  opacity: 1;
  /* none, not translateX(0): the resting state has to clear an offset on
     either axis now. */
  -webkit-transform: none;
          transform: none;
}
.bws-split__text h2 { font-size: 2.25rem; margin-bottom: var(--bws-space-2); }
/* The base reset zeroes p margins site-wide, and the looser reading rhythm
   below only ever existed for inner pages (.bws-page .bws-richtext p) — on
   the home page these paragraphs (the directress letter, Quality Education)
   ran together as one dense block with no line or paragraph breathing room. */
.bws-split__text .bws-richtext p { margin-bottom: var(--bws-space-4); line-height: 1.75; }
.bws-split__text .bws-richtext p:last-child { margin-bottom: 0; }
/* Shared-image layout: several text blocks share one photo, so they need
   space between them that a single-item slide doesn't. */
.bws-split__slide--shared .bws-split__text { gap: var(--bws-space-10); }
.bws-split__block { display: flex; flex-direction: column; }
.bws-split__signature { margin-top: var(--bws-space-5); }
/* align-self overrides the text column's align-items: stretch, which would
   otherwise blow the pill button out to the full column width. */
.bws-split__cta {
  margin-top: var(--bws-space-6);
  align-self: flex-start;
}
.bws-split__signature p { margin: 0; }
.bws-split__controls {
  position: absolute;
  bottom: var(--bws-space-8);
  left: var(--bws-space-8);
  z-index: 2;
  margin-top: 0;
}
.bws-split--image-left .bws-split__controls { left: auto; right: var(--bws-space-8); }
/* Specificity note: `.bws-split__signature p { margin: 0; }` above (class +
   element) beats a bare `.bws-split__signature-script` (class alone) — the
   margin-top below needs the parent class prefixed to win. */
.bws-split__signature .bws-split__signature-script {
  font-family: var(--bws-font-script);
  font-style: normal;
  font-size: 3rem;
  font-weight: 400;
  color: var(--bws-color-brand-600);
  line-height: 1;
  /* Script fonts run visually smaller than their font-size for a given
     weight — matches the old site's proportion against the body copy above
     it rather than the display font's own metrics. */
  margin-top: var(--bws-space-2);
}
/* ---------- Carousel ---------- */
.bws-carousel { position: relative; }
.bws-carousel__controls {
  display: flex;
  gap: var(--bws-space-3);
  margin-top: var(--bws-space-5);
}
.bws-carousel__nav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--bws-color-line);
  background: var(--bws-color-surface);
  color: var(--bws-color-brand);
  cursor: pointer;
}
.bws-carousel__nav:hover { background: var(--bws-color-brand-100); }
.bws-carousel__nav:disabled { opacity: .35; cursor: default; }
.bws-carousel__nav:disabled:hover { background: var(--bws-color-surface); }
/* ---------- Cards: campuses (dashed) ---------- */
.bws-grid--dashed .bws-card--dashed,
.bws-card--dashed {
  background: transparent;
  border: 2px dashed var(--bws-color-brand-400);
  box-shadow: none;
}
.bws-card--centered { text-align: center; }
.bws-card--flush-top { padding: 0; overflow: hidden; }
.bws-card--flush-top h3, .bws-card--flush-top p { margin-inline: var(--bws-space-5); }
.bws-card--flush-top h3 { margin-top: var(--bws-space-4); }
.bws-card--flush-top p { margin-bottom: var(--bws-space-5); }
.bws-card__image {
  height: 180px;
  background: var(--bws-color-brand-100);
  background-size: cover;
  background-position: center;
}
.bws-card--centered h3 { font-size: 2.5rem; }
/* ---------- Accolade band (Apple Distinguished School) ---------- */
/* Deliberately the opposite of the rest of the page: the site is card-heavy
   — borders, shadows, rounded tiles — and this band has none of that. One
   centred column, a lot of air, large light type and hairline rules, which
   is how Apple presents this programme. That contrast is the point. */
.bws-section.bws-accolade {
  background: #f5f5f7;
  padding-block: var(--bws-space-12);
  text-align: center;
}
/* No blanket flex gap: a single gap value can't tell a tightly-related pair
   (eyebrow sitting right above its heading) from a real section break (lede
   to the points row) — each element gets its own margin instead, so the
   rhythm can loosen where it needs to and stay close where it should. */
.bws-accolade__inner {
  max-width: 860px;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.bws-accolade__crest { width: 92px; height: auto; margin-bottom: var(--bws-space-6); }
.bws-accolade__badge { width: min(300px, 70vw); height: auto; margin-bottom: var(--bws-space-2); }
/* Two classes throughout: the global `.bws p` / `.bws h2` rules are
   class+element and would otherwise win on specificity. */
.bws-accolade .bws-accolade__eyebrow {
  font-size: var(--bws-text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--bws-color-brand-600);
  margin-bottom: var(--bws-space-3);
}
.bws-accolade .bws-accolade__heading {
  /* Lighter weight and tighter tracking than our usual headings — the
     large-type treatment Apple uses, rather than our display bold. */
  font-size: clamp(2rem, 1.2rem + 3.2vw, 3.25rem);
  font-weight: 500;
  letter-spacing: -.02em;
  line-height: 1.08;
  color: var(--bws-color-ink);
  margin-bottom: var(--bws-space-6);
}
.bws-accolade .bws-accolade__lede {
  max-width: 62ch;
  font-size: var(--bws-text-lg);
  line-height: 1.6;
  color: var(--bws-color-ink-soft);
}
.bws-accolade__photo {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1280 / 620;
  -o-object-fit: cover;
     object-fit: cover;
  border-radius: 18px;
  margin-top: var(--bws-space-6);
}
/* Scoped under .bws-accolade (two classes, specificity 0,2,0): the global
   reset `ul[class] { margin: 0; ... }` is an element + attribute selector
   (0,1,1), which outranks a bare `.bws-accolade__points` (0,1,0) and was
   silently zeroing this margin-top regardless of the value set here — the
   actual cause of the missing gap above this row, not a caching issue. */
.bws-accolade .bws-accolade__points {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--bws-space-8);
  width: 100%;
  margin-top: var(--bws-space-12);
  text-align: center;
}
@media (min-width: 900px) {
  /* Matches the base rule's .bws-accolade .bws-accolade__points specificity
     (0,2,0) — a bare .bws-accolade__points (0,1,0) here loses to that base
     rule regardless of this media query being active, which is exactly what
     was collapsing the grid back to a single column at any width. */
  .bws-accolade .bws-accolade__points { grid-template-columns: repeat(4, 1fr); gap: 0; }
  /* Hairline dividers instead of cards. */
  .bws-accolade__points li + li { border-left: 1px solid var(--bws-color-line); }
  .bws-accolade__points li { padding-inline: var(--bws-space-6); }
}
.bws-accolade__points strong {
  display: block;
  font-family: var(--bws-font-display);
  font-weight: 600;
  font-size: var(--bws-text-md);
  color: var(--bws-color-ink);
}
.bws-accolade__points span {
  display: block;
  margin-top: var(--bws-space-2);
  font-size: var(--bws-text-sm);
  line-height: 1.55;
  color: var(--bws-color-ink-soft);
}
.bws-accolade__cta { margin-top: var(--bws-space-6); }
/* One even rhythm down the band. Two classes on each so nothing generic can
   zero them: the list reset was flattening the points row's top margin,
   which left the photo sitting flush on the points. */
.bws-accolade .bws-accolade__badge { margin-bottom: var(--bws-space-5); }
.bws-accolade .bws-accolade__photo { margin-top: var(--bws-space-8); }
.bws-accolade .bws-accolade__points { margin-top: var(--bws-space-8); }
.bws-section.bws-accolade .bws-accolade__note { margin-top: var(--bws-space-8); }
.bws-accolade .bws-accolade__cta { margin-top: var(--bws-space-5); }
.bws-accolade .bws-accolade__note {
  margin-top: var(--bws-space-10);
  max-width: 60ch;
  font-size: var(--bws-text-xs);
  color: var(--bws-color-ink-soft);
}
/* ---------- Level tiles: photo card with bottom scrim + overlaid name ---------- */
.bws-grid--levels { grid-template-columns: repeat(2, 1fr); }
@media (min-width: 768px) {
  .bws-grid--levels { grid-template-columns: repeat(4, 1fr); }
}
.bws-level-tile {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  aspect-ratio: 3 / 4;
  border-radius: var(--bws-radius-md);
  overflow: hidden;
  padding: var(--bws-space-4);
  color: #fff;
  box-shadow: var(--bws-shadow-sm);
  transition: box-shadow .35s ease, -webkit-transform .35s ease;
  transition: box-shadow .35s ease, transform .35s ease;
  transition: box-shadow .35s ease, transform .35s ease, -webkit-transform .35s ease;
}
/* Photo lives on its own layer (not the tile's own background) so it can
   zoom on hover while the tile's own box — and its overflow:hidden clip —
   stays put. */
.bws-level-tile__photo {
  position: absolute;
  inset: 0;
  background: linear-gradient(155deg, var(--bws-color-brand-400), var(--bws-color-brand));
  background-size: cover;
  background-position: center;
  -webkit-transform: scale(1);
          transform: scale(1);
  transition: -webkit-transform .6s cubic-bezier(.25, .8, .25, 1);
  transition: transform .6s cubic-bezier(.25, .8, .25, 1);
  transition: transform .6s cubic-bezier(.25, .8, .25, 1), -webkit-transform .6s cubic-bezier(.25, .8, .25, 1);
}
.bws-level-tile__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,.6) 100%);
  transition: background .35s ease;
}
.bws-level-tile__name {
  position: relative;
  z-index: 1;
  font-family: var(--bws-font-display);
  font-weight: 600;
  font-size: 1.75rem;
  text-align: center;
  transition: -webkit-transform .35s ease;
  transition: transform .35s ease;
  transition: transform .35s ease, -webkit-transform .35s ease;
}
/* Two tiles to a row on phones leaves ~150px per tile, so 1.75rem ran
   "Kindergarten" off both edges. Scale with the screen and let a long name
   (Center for Special Education) wrap rather than overflow. */
@media (max-width: 767px) {
  .bws-level-tile { padding: var(--bws-space-3); }
  .bws-level-tile__name {
    font-size: clamp(1rem, 4.6vw, 1.25rem);
    line-height: 1.2;
    overflow-wrap: anywhere;
    text-wrap: balance;
  }
}
.bws-level-tile__name::after {
  content: "";
  display: block;
  width: 28px;
  height: 2px;
  margin: var(--bws-space-2) auto 0;
  background: var(--bws-color-accent);
  -webkit-transform: scaleX(0);
          transform: scaleX(0);
  -webkit-transform-origin: center;
          transform-origin: center;
  transition: -webkit-transform .35s ease;
  transition: transform .35s ease;
  transition: transform .35s ease, -webkit-transform .35s ease;
}
.bws-level-tile:hover,
.bws-level-tile:focus-visible {
  -webkit-transform: translateY(-6px);
          transform: translateY(-6px);
  box-shadow: var(--bws-shadow-md);
}
.bws-level-tile:hover .bws-level-tile__photo,
.bws-level-tile:focus-visible .bws-level-tile__photo {
  -webkit-transform: scale(1.08);
          transform: scale(1.08);
}
.bws-level-tile:hover .bws-level-tile__scrim,
.bws-level-tile:focus-visible .bws-level-tile__scrim {
  background: linear-gradient(180deg, rgba(0,0,0,.12) 0%, rgba(0,0,0,.74) 100%);
}
.bws-level-tile:hover .bws-level-tile__name,
.bws-level-tile:focus-visible .bws-level-tile__name {
  -webkit-transform: translateY(-4px);
          transform: translateY(-4px);
}
.bws-level-tile:hover .bws-level-tile__name::after,
.bws-level-tile:focus-visible .bws-level-tile__name::after {
  -webkit-transform: scaleX(1);
          transform: scaleX(1);
}
.bws-level-tile:focus-visible {
  outline: 2px solid var(--bws-color-accent);
  outline-offset: 3px;
}
.bws-card__icon--round {
  display: inline-block;
  width: 90px;
  height: 90px;
  border-radius: 50%;
  /* Gold disc with the white line icon centred on it, as on the old site's
     values strip; the icon itself arrives as an inline background-image. */
  background-color: var(--bws-color-accent);
  background-repeat: no-repeat;
  background-position: center;
  background-size: 50%;
  margin-bottom: var(--bws-space-3);
}
/* Our Core Values: brand-teal fill (closest thing to "blue" in this
   palette) behind the still-white cards, so the section reads as a
   distinct band on the page. #values beats the global .bws h2 color rule
   on specificity alone (id beats class+element), same fix as the footer
   heading/muted-text bugs earlier. */
/* Learning Spaces and the closing "Our passion. Their future." band get the
   same treatment. Lighter brand teal rather than the #005051 of the side rail
   and tabs, so the rail no longer melts into these bands: a soft light behind
   the cards, a slightly deeper teal toward the bottom, and a muted linen
   texture (fine film grain over faint crossed hairlines) across the band. */
#values.bws-section,
#spaces.bws-section,
.bws-section.bws-cta-band,
.bws-search__banner {
  isolation: isolate;
  background:
    radial-gradient(ellipse 70% 65% at 50% 38%, rgba(255, 255, 255, .12) 0%, rgba(255, 255, 255, 0) 70%),
    linear-gradient(180deg, var(--bws-color-brand-600) 0%, #00666c 100%);
}
#values.bws-section::before,
#spaces.bws-section::before,
.bws-section.bws-cta-band::before,
.bws-search__banner::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"),
    repeating-linear-gradient(45deg, rgba(255, 255, 255, .035) 0 1px, transparent 1px 7px),
    repeating-linear-gradient(-45deg, rgba(0, 0, 0, .04) 0 1px, transparent 1px 7px);
  background-size: 220px 220px, auto, auto;
  opacity: .55;
  mix-blend-mode: soft-light;
}
#values h2 { color: #fff; }
#spaces h2 { color: #fff; }
/* ---------- Admissions: same treatment for Requirements, Inquire, Intro ---------- */
/* These three landed in .bws-page's alternating-tint rotation (a flat,
   pastel var(--bws-color-brand-100)) by sort-order coincidence, which read
   flatter and more saturated than the rest of the site's teal moments.
   Reuses the #values/#spaces gradient+texture treatment instead — the ID
   selector's specificity beats the alternating rule with no !important. */
.bws-page--admissions #intro,
.bws-page--admissions #requirements,
.bws-page--admissions #inquire {
  isolation: isolate;
  background:
    radial-gradient(ellipse 70% 65% at 50% 38%, rgba(255, 255, 255, .12) 0%, rgba(255, 255, 255, 0) 70%),
    linear-gradient(180deg, var(--bws-color-brand-600) 0%, #00666c 100%);
}
.bws-page--admissions #intro::before,
.bws-page--admissions #requirements::before,
.bws-page--admissions #inquire::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"),
    repeating-linear-gradient(45deg, rgba(255, 255, 255, .035) 0 1px, transparent 1px 7px),
    repeating-linear-gradient(-45deg, rgba(0, 0, 0, .04) 0 1px, transparent 1px 7px);
  background-size: 220px 220px, auto, auto;
  opacity: .55;
  mix-blend-mode: soft-light;
}
/* Text that assumed the old light tint flips to white on the darker fill.
   The inquiry form's inputs and the sticky aside card keep their own white
   backgrounds either way, so only the labels/legends/checklist around them
   need to change. */
.bws-page--admissions #intro .bws-richtext p,
.bws-page--admissions #requirements h2,
.bws-page--admissions #requirements .bws-richtext p,
.bws-page--admissions #requirements .bws-checklist li,
.bws-page--admissions #inquire h2,
.bws-page--admissions #inquire .bws-field,
.bws-page--admissions #inquire .bws-check {
  color: #fff;
}
.bws-page--admissions #inquire .bws-fieldset legend { color: #fff; opacity: .85; }
.bws-page--admissions #inquire .bws-check a { color: #fff; }
.bws-page--admissions #inquire .bws-inquire__note { color: rgba(255, 255, 255, .85); }
.bws-page--admissions #inquire .bws-inquire__note a { color: #fff; }
/* The talk-to-someone card keeps its own light tint regardless of the dark
   section fill above, so its note reverts to normal ink instead of white. */
.bws-page--admissions #inquire .bws-inquire__talk .bws-inquire__note { color: var(--bws-color-ink-soft); }
.bws-page--admissions #inquire .bws-inquire__talk .bws-inquire__note a { color: var(--bws-color-brand-600); }
/* ---------- Testimonial ---------- */
/* Heading on the left; on the right the current quote sits in a raised white
   panel with a gold top bar, a big faint quote mark in its corner, the
   speaker's initials badge, and a 01 / 11 pager with solid arrows. Light
   mint with the same muted linen texture as the teal bands, so it stands apart from the teal Learning
   Spaces band above and the off-white news below. The id selector outranks
   the base .bws-section background. */
#testimonials.bws-testimonial {
  isolation: isolate;
  background:
    radial-gradient(ellipse 60% 70% at 70% 45%, rgba(255, 255, 255, .7) 0%, rgba(255, 255, 255, 0) 70%),
    var(--bws-color-brand-100);
  padding-block: var(--bws-space-12);
  color: var(--bws-color-ink);
}
#testimonials.bws-testimonial::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 .31 0 0 0 0 .32 0 0 0 .5 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"),
    repeating-linear-gradient(45deg, rgba(0, 80, 81, .025) 0 1px, transparent 1px 7px),
    repeating-linear-gradient(-45deg, rgba(0, 80, 81, .025) 0 1px, transparent 1px 7px);
  background-size: 220px 220px, auto, auto;
  /* Lighter than on the teal bands: grain shows far more on a pale ground. */
  opacity: .22;
}
.bws-testimonial__inner {
  display: grid;
  gap: var(--bws-space-8);
  align-items: center;
}
@media (min-width: 1024px) {
  .bws-testimonial__inner {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: var(--bws-space-10);
  }
}
#testimonials h2 {
  color: var(--bws-color-brand);
  font-size: var(--bws-text-2xl);
  line-height: 1.2;
  text-wrap: balance;
  margin: 0;
}
#testimonials h2::after {
  content: "";
  display: block;
  width: 56px;
  height: 4px;
  margin-top: var(--bws-space-5);
  border-radius: var(--bws-radius-pill);
  background: var(--bws-color-accent);
}
.bws .bws-testimonial__lede {
  color: var(--bws-color-ink-soft);
  font-size: var(--bws-text-md);
  line-height: 1.7;
  max-width: 26rem;
  margin: var(--bws-space-5) 0 0;
}
.bws-carousel--quote {
  position: relative;
  overflow: hidden;
  background: var(--bws-color-surface);
  border-radius: var(--bws-radius-lg);
  padding: var(--bws-space-10) var(--bws-space-10) var(--bws-space-6);
  box-shadow: 0 2px 6px rgba(0, 64, 65, .06), 0 30px 60px -24px rgba(0, 64, 65, .38);
}
/* Gold bar across the top of the panel. */
.bws-carousel--quote::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 6px;
  background: linear-gradient(90deg, var(--bws-color-accent), #f2c46b);
}
/* Oversized, very faint quote mark tucked into the top-right corner, clear
   of the pager row. */
.bws-carousel--quote::after {
  content: "";
  position: absolute;
  top: 28px;
  right: 32px;
  width: 150px;
  height: 114px;
  pointer-events: none;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 58 44'%3E%3Cpath fill='%23005051' d='M0 44V27.5C0 11.9 7.6 3 22.7 0l2.4 5.6C16.9 7.9 12.9 12.6 12.4 20H24v24H0zm32 0V27.5C32 11.9 39.6 3 54.7 0l2.4 5.6C48.9 7.9 44.9 12.6 44.4 20H56v24H32z'/%3E%3C/svg%3E") no-repeat center / contain;
  opacity: .05;
}
@media (max-width: 768px) {
  .bws-carousel--quote { padding: var(--bws-space-8) var(--bws-space-5) var(--bws-space-5); }
  .bws-carousel--quote::after { top: 20px; right: 16px; width: 96px; height: 73px; }
}
.bws-testimonial__mark {
  position: relative;
  display: block;
  color: var(--bws-color-accent);
  margin-bottom: var(--bws-space-5);
}
.bws-testimonial__slide { position: relative; margin: 0; }
.bws-testimonial__quote { margin: 0; }
.bws .bws-testimonial__quote p {
  font-family: var(--bws-font-display);
  font-size: clamp(1.125rem, .85rem + .8vw, 1.5rem);
  font-weight: 500;
  line-height: 1.55;
  color: var(--bws-color-brand);
  margin: 0;
  text-wrap: pretty;
}
.bws-testimonial__cite {
  display: flex;
  align-items: center;
  gap: var(--bws-space-3);
  margin-top: var(--bws-space-6);
}
.bws-testimonial__avatar {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--bws-color-brand);
  box-shadow: 0 0 0 3px var(--bws-color-surface), 0 0 0 5px var(--bws-color-accent);
  color: #fff;
  font-size: var(--bws-text-sm);
  font-weight: 700;
  letter-spacing: .04em;
}
.bws-testimonial__who {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.bws-testimonial__name {
  font-size: var(--bws-text-md);
  font-weight: 700;
  color: var(--bws-color-ink);
}
.bws-testimonial__title {
  font-size: var(--bws-text-sm);
  color: var(--bws-color-ink-soft);
}
.bws-testimonial__controls {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bws-space-4);
  margin-top: var(--bws-space-6);
  padding-top: var(--bws-space-5);
  border-top: 1px solid var(--bws-color-line);
}
.bws .bws-testimonial__count {
  margin: 0;
  font-size: var(--bws-text-sm);
  letter-spacing: .08em;
  color: var(--bws-color-ink-soft);
  font-variant-numeric: tabular-nums;
}
.bws-testimonial__count [data-counter] { color: var(--bws-color-brand); font-weight: 700; }
.bws-testimonial__arrows { display: flex; gap: var(--bws-space-3); }
.bws-testimonial .bws-carousel__nav {
  width: 44px;
  height: 44px;
  border: 0;
  background: var(--bws-color-brand);
  color: #fff;
  transition: background .2s ease, color .2s ease;
}
.bws-testimonial .bws-carousel__nav:hover {
  background: var(--bws-color-accent);
  color: var(--bws-color-brand);
}
.bws-testimonial .bws-carousel__nav:focus-visible { outline: 2px solid var(--bws-color-accent); outline-offset: 3px; }
/* Autoplay: a gold line fills along the pager rule over each quote's 7s, and
   an outlined pause/play button sits before the arrows. */
.bws-testimonial__progress {
  position: absolute;
  top: -1px;
  left: 0;
  right: 0;
  height: 2px;
  overflow: hidden;
  pointer-events: none;
}
.bws-testimonial__progress span {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--bws-color-accent);
  -webkit-transform: scaleX(0);
          transform: scaleX(0);
  -webkit-transform-origin: left center;
          transform-origin: left center;
}
.bws-testimonial__progress span.is-running { -webkit-animation: bws-testimonial-progress linear forwards; animation: bws-testimonial-progress linear forwards; }
@-webkit-keyframes bws-testimonial-progress {
  from { -webkit-transform: scaleX(0); transform: scaleX(0); }
  to { -webkit-transform: scaleX(1); transform: scaleX(1); }
}
@keyframes bws-testimonial-progress {
  from { -webkit-transform: scaleX(0); transform: scaleX(0); }
  to { -webkit-transform: scaleX(1); transform: scaleX(1); }
}
.bws-testimonial .bws-carousel__nav.bws-testimonial__pause {
  background: transparent;
  border: 1px solid rgba(0, 80, 81, .35);
  color: var(--bws-color-brand);
}
.bws-testimonial .bws-carousel__nav.bws-testimonial__pause:hover { background: var(--bws-color-brand-100); color: var(--bws-color-brand); }
/* .bws-carousel__nav is inline-flex, which would otherwise override [hidden]. */
.bws-testimonial .bws-testimonial__pause[hidden] { display: none; }
.bws-testimonial__play-icon { display: none; }
.bws-testimonial__pause.is-paused .bws-testimonial__pause-icon { display: none; }
.bws-testimonial__pause.is-paused .bws-testimonial__play-icon { display: block; }
/* Gold is too pale for small text on mint; the eyebrow takes the darker teal. */
.bws .bws-testimonial .bws-eyebrow--light { color: var(--bws-color-brand-600); }
/* Every slide occupies the same grid cell, so the track is always as tall as
   the LONGEST quote and the controls stop jumping as you page through them.
   The inactive slides keep their space but are made invisible rather than
   display:none — visibility:hidden also drops them from the a11y tree, so
   screen readers still only get the current quote. The [hidden] override
   needs the extra class to outrank the browser's own [hidden]{display:none}. */
.bws-carousel--quote .bws-carousel__track { display: grid; }
.bws-carousel--quote .bws-testimonial__slide {
  grid-area: 1 / 1;
  transition: opacity .35s ease, -webkit-transform .35s ease;
  transition: opacity .35s ease, transform .35s ease;
  transition: opacity .35s ease, transform .35s ease, -webkit-transform .35s ease;
}
.bws-carousel--quote .bws-testimonial__slide[hidden] {
  display: block;
  visibility: hidden;
  opacity: 0;
  -webkit-transform: translateY(8px);
          transform: translateY(8px);
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .bws-carousel--quote .bws-testimonial__slide { transition: none; }
}
/* On phones the longest quote is twice the height of the shortest, so a
   fixed-height track leaves a tall empty gap; let the band follow each quote. */
@media (max-width: 768px) {
  .bws-carousel--quote .bws-testimonial__slide[hidden] { display: none; }
}
/* ---------- News grid ---------- */
/* A scrollable row, not a CSS grid: with a fixed 3 items this used to just
   lay out 3 equal columns, which is why there was nothing for arrows to
   page through. Fixed-width cards + scroll-snap means it looks like the old
   3-up layout whenever everything fits, and becomes an actual carousel once
   more posts exist than fit on screen. */
.bws-news-grid {
  /* No top margin: the section heading is a sibling above the carousel and
     already carries its own spacing via .bws-container > h2. */
  display: flex;
  gap: var(--bws-space-5);
  overflow-x: auto;
  -ms-scroll-snap-type: x mandatory;
      scroll-snap-type: x mandatory;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.bws-news-grid::-webkit-scrollbar { display: none; }
/* Three columns — arrow, track, arrow — so each button occupies its own
   space beside the cards. Overlaying them on the row (however it was
   positioned) always clipped the first and last card; a grid track can't. */
.bws-carousel--news {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--bws-space-4);
}
.bws-carousel--news .bws-carousel__nav { flex: none; }
@media (max-width: 767px) {
  /* Arrows would eat most of a phone's width next to a near-full-width
     card; the row still swipes. */
  .bws-carousel--news { grid-template-columns: minmax(0, 1fr); }
  .bws-carousel--news .bws-carousel__nav { display: none; }
}
.bws-news-card {
  padding: 0;
  overflow: hidden;
  scroll-snap-align: start;
  flex: 0 0 min(320px, 85vw);
  /* Anything absolutely positioned inside a card is contained by the card.
     Without this its containing block is the page itself, so it escapes this
     track's horizontal clipping, lands at the card's real x-offset far off
     screen, and stretches the document sideways — which is exactly how a
     visually-hidden span turned the phone home page into a blank sideways
     scroll. */
  position: relative;
}
@media (min-width: 640px) {
  .bws-news-card { flex-basis: min(360px, calc((100% - 2 * var(--bws-space-5)) / 3)); }
}
.bws-news-card__image {
  height: 260px;
  background: var(--bws-color-brand-100);
  background-size: cover;
  background-position: center;
}
/* The base reset zeroes h3/p margins site-wide, so without an explicit gap
   here the title, body text and date sit flush against each other — flex +
   gap replaces the margins that reset removed, rather than patching each
   child individually. */
.bws-news-card__body {
  padding: var(--bws-space-5);
  display: flex;
  flex-direction: column;
  gap: var(--bws-space-3);
}
.bws-news-card__body h3 { font-size: 1.15rem; }
/* Pinned to the bottom of the flex column so the date and CTA line up across
   a row of cards even when one card's description is shorter than another's. */
.bws-news-card__meta {
  margin-top: auto;
  display: flex;
  flex-direction: column;
}
.bws-news-card__date {
  font-size: 0.625rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--bws-color-brand-600);
}
/* ---------- Photo-card hover (Learning Spaces + News) ---------- */
/* Same language as the level tiles: the card lifts, its photo zooms inside
   the card's own overflow:hidden frame. Both card types already clip their
   content, so the zoom stays inside the rounded corners. */
.bws-card--flush-top,
.bws-news-card {
  transition: box-shadow .35s ease, border-color .35s ease, -webkit-transform .35s ease;
  transition: box-shadow .35s ease, transform .35s ease, border-color .35s ease;
  transition: box-shadow .35s ease, transform .35s ease, border-color .35s ease, -webkit-transform .35s ease;
}
.bws-card--flush-top .bws-card__image,
.bws-news-card .bws-news-card__image {
  transition: -webkit-transform .6s cubic-bezier(.25, .8, .25, 1);
  transition: transform .6s cubic-bezier(.25, .8, .25, 1);
  transition: transform .6s cubic-bezier(.25, .8, .25, 1), -webkit-transform .6s cubic-bezier(.25, .8, .25, 1);
}
.bws-card--flush-top:hover,
.bws-news-card:hover,
.bws-card--flush-top:focus-within,
.bws-news-card:focus-within {
  -webkit-transform: translateY(-6px);
          transform: translateY(-6px);
  box-shadow: var(--bws-shadow-md);
  border-color: var(--bws-color-brand-400);
}
.bws-card--flush-top:hover .bws-card__image,
.bws-news-card:hover .bws-news-card__image,
.bws-card--flush-top:focus-within .bws-card__image,
.bws-news-card:focus-within .bws-news-card__image {
  -webkit-transform: scale(1.08);
          transform: scale(1.08);
}
@media (prefers-reduced-motion: reduce) {
  .bws-card--flush-top,
  .bws-news-card,
  .bws-card--flush-top .bws-card__image,
  .bws-news-card .bws-news-card__image {
    transition: none;
  }
  .bws-card--flush-top:hover,
  .bws-news-card:hover,
  .bws-card--flush-top:hover .bws-card__image,
  .bws-news-card:hover .bws-news-card__image {
    -webkit-transform: none;
            transform: none;
  }
}
/* ---------- Social row ---------- */
.bws-social__inner { text-align: center; }
.bws-social__row {
  display: flex;
  justify-content: center;
  gap: var(--bws-space-3);
  margin-top: var(--bws-space-4);
}
.bws-social__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--bws-color-ink);
  color: #fff;
}
.bws-social__icon:hover { background: var(--bws-color-brand); }
/* #social beats the base .bws-section background on specificity (id beats
   class). Dark ink heading/icons already contrast well against this gold,
   no color changes needed there. */
#social.bws-section { background: var(--bws-color-accent); }
/* ---------- CTA band (footer close) ---------- */
.bws-cta-band {
  background: var(--bws-color-brand);
  color: #fff;
  text-align: center;
  /* Roomier than the default section padding — a closing CTA band reads as
     an afterthought otherwise. */
  padding-block: var(--bws-space-10);
}
.bws-cta-band h2, .bws-cta-band p { color: #fff; }
/* Base-level fix, not band-only: the reset zeroes every <p>'s margin, and
   this bare cta paragraph carried no class of its own to restore any —
   so on a plain (non-band) cta the lede sat flush against the button
   below it. Every cta block gets the gap now, band or not. */
.bws-cta__body { margin-bottom: var(--bws-space-5); }
.bws-cta-band .bws-cta__body { margin-bottom: var(--bws-space-6); }
/* Also base-level: .bws-actions had no layout of its own outside .bws-cta-band,
   so a plain cta with two buttons had no gap between them beyond the browser's
   default inline whitespace. */
.bws-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bws-space-4);
}
.bws-cta-band .bws-actions { justify-content: center; }
/* A calmer alternative to .bws-cta-band: centres the same way (heading, lede,
   actions) but keeps the section's own background instead of switching to
   the teal band treatment — for a cta that should read as a centred closing
   statement without becoming a full-bleed colour band. */
.bws-cta-center { text-align: center; }
.bws-cta-center .bws-actions { justify-content: center; }
.bws-cta-band .bws-btn--secondary { background: var(--bws-color-accent); color: var(--bws-color-ink); }
/* ---------- Text-link hover ---------- */
/* Text links keep their colour and grow an accent underline instead of
   recolouring: a colour swap alone is easy to miss and reads inconsistently
   across the header (white over the hero, ink when solid), drawer and
   footer. One treatment covers all three, and :focus-visible matches so
   keyboard users get the same signal.

   Drawn as a background gradient rather than text-decoration because
   text-decoration cannot be transitioned — this wipes in from the left.
   The social icons are excluded: they are circular buttons whose own
   background shorthand would fight this one. */
.bws-nav a,
.bws-drawer__link,
.bws-drawer__group summary,
.bws-drawer__sublinks a,
.bws-drawer__footer-links a,
.bws-footer__contact a,
.bws-footer__nav a,
.bws-footer__bottom a {
  background-image: linear-gradient(var(--bws-color-accent), var(--bws-color-accent));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 2px;
  padding-bottom: 3px;
  transition: background-size .28s cubic-bezier(.25, .8, .25, 1);
}
.bws-nav a:hover,
.bws-nav a:focus-visible,
.bws-drawer__link:hover,
.bws-drawer__link:focus-visible,
.bws-drawer__group summary:hover,
.bws-drawer__group summary:focus-visible,
.bws-drawer__sublinks a:hover,
.bws-drawer__sublinks a:focus-visible,
.bws-drawer__footer-links a:hover,
.bws-drawer__footer-links a:focus-visible,
.bws-footer__contact a:hover,
.bws-footer__contact a:focus-visible,
.bws-footer__nav a:hover,
.bws-footer__nav a:focus-visible,
.bws-footer__bottom a:hover,
.bws-footer__bottom a:focus-visible {
  background-size: 100% 2px;
}
@media (prefers-reduced-motion: reduce) {
  .bws-nav a,
  .bws-drawer__link,
  .bws-drawer__group summary,
  .bws-drawer__sublinks a,
  .bws-drawer__footer-links a,
  .bws-footer__contact a,
  .bws-footer__nav a,
  .bws-footer__bottom a { transition: none; }
}
/* ---------- Footer ---------- */
/* Crest + motto lead as a centred masthead, then three labelled columns.
   Deliberately not the brand-left / contact-mid / gold-rail-right shape:
   same warmth and the same gold-on-ink palette, different structure. */
.bws-footer {
  /* Pulls the footer up a hair to close a subpixel rounding seam that can
     otherwise leave a hairline sliver of the page background showing
     between the previous section and this border — position: relative
     keeps it painting above that section rather than under it. */
  position: relative;
  margin-top: -2px;
  background: var(--bws-color-ink);
  color: #b9c2bd;
  padding-block: var(--bws-space-10) var(--bws-space-6);
  font-size: var(--bws-text-sm);
  border-top: 3px solid var(--bws-color-accent);
}
.bws-footer a { color: #d8ded9; text-decoration: none; }
.bws-footer__masthead {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--bws-space-4);
}
/* The crest is a 926x561 oval, not a circle — forcing it into a square with
   border-radius:50% (as this used to) squashes it and clips the ring text
   top and bottom. Sized by width, height auto, no circular crop, same
   approach as .bws-split__crest. */
.bws-footer__crest { width: 140px; height: auto; }
/* Every rule below that targets a <p> or <h2> needs two classes: the global
   `.bws p` / `.bws h2` rules are class+element and would otherwise win,
   painting footer text in near-black ink on this near-black background. */
/* Display face, not the script one: at this size the script was handsome but
   genuinely hard to read, and a motto is the last thing that should make a
   reader work. Size and gold carry the weight instead. */
.bws-footer .bws-footer__motto {
  font-family: var(--bws-font-display);
  font-size: clamp(1.75rem, 1.1rem + 2.6vw, 3rem);
  font-weight: 500;
  letter-spacing: .01em;
  color: var(--bws-color-accent);
  line-height: 1.2;
}
.bws-footer .bws-footer__blurb {
  max-width: 60ch;
  color: #b9c2bd;
  font-size: var(--bws-text-sm);
  line-height: 1.7;
}
/* Hairline rule between masthead and columns, gold and centred. */
.bws-footer__cols {
  display: grid;
  gap: var(--bws-space-8);
  grid-template-columns: 1fr;
  margin-top: var(--bws-space-10);
  padding-top: var(--bws-space-8);
  border-top: 1px solid rgba(232, 168, 56, .25);
}
@media (min-width: 768px) {
  .bws-footer__cols { grid-template-columns: repeat(3, 1fr); }
}
.bws-footer__col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--bws-space-3);
}
.bws-footer .bws-footer__label {
  color: var(--bws-color-accent);
  font-family: var(--bws-font-display);
  font-size: var(--bws-text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .12em;
  margin-bottom: var(--bws-space-2);
}
/* A second label further down the same column (Work With Us under Connect):
   the same gold heading, with room to read as its own group. */
.bws-footer .bws-footer__label--spaced { margin-top: var(--bws-space-8); }
.bws-footer .bws-footer__address {
  font-style: normal;
  color: #fff;
  line-height: 1.6;
}
.bws-footer .bws-footer__strong-link {
  font-weight: 700;
  color: #fff;
  text-transform: uppercase;
  letter-spacing: .06em;
  font-size: var(--bws-text-xs);
}
.bws-footer .bws-footer__muted { color: #8b968f; line-height: 1.6; }
.bws-footer__nav,
.bws-footer__contact {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--bws-space-3);
}
.bws-footer__social {
  display: flex;
  gap: var(--bws-space-3);
  margin-top: var(--bws-space-4);
}
.bws-footer__social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .25);
  color: #fff;
  transition: background-color .2s ease, border-color .2s ease;
}
.bws-footer__social a:hover {
  background-color: rgba(232, 168, 56, .18);
  border-color: var(--bws-color-accent);
}
.bws-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--bws-space-5);
  margin-top: var(--bws-space-8);
  padding-top: var(--bws-space-5);
  border-top: 1px solid rgba(255, 255, 255, .12);
  font-size: var(--bws-text-xs);
  color: #8b968f;
  text-align: center;
}
/* ---------- Inner pages ---------- */
/* Shorter banner than the home hero, with the page title over the photo. */
.bws-hero--page {
  min-height: clamp(380px, 58vh, 640px);
  display: flex;
  align-items: flex-end;
}
.bws-hero__scrim--page {
  background: linear-gradient(180deg, rgba(0, 0, 0, .55) 0%, rgba(0, 0, 0, .05) 35%, rgba(0, 0, 0, .1) 60%, rgba(0, 0, 0, .78) 100%);
}
.bws-hero__caption {
  position: relative;
  z-index: 6;
  width: 100%;
  padding-bottom: var(--bws-space-8);
  /* Keep the title clear of both fixed rails: the utility rail over the
     top-right corner at every width, and the enrollment tab on the left.
     The tab only exists from 768px up (see .bws-banner), so below that the
     left inset drops back to the ordinary gutter — a 390px phone cannot
     spare 56px for something that isn't on screen. */
  padding-left: var(--bws-space-4);
  padding-right: var(--bws-space-4);
  color: #fff;
  text-align: center;
}
/* At every width now, not just from 768px: the rail sits over the top-right
   corner on a phone too, and the banner's eyebrow, title and lede were running
   underneath it. The caption is centred, so both insets apply and the title
   stays on axis within what is left. */
.bws-hero__caption {
  padding-left: var(--bws-safe-left);
  padding-right: var(--bws-safe-right);
}
.bws-hero__caption h1 {
  color: #fff;
  margin-bottom: var(--bws-space-3);
  margin-inline: auto;
  text-wrap: balance;
  text-shadow: 0 2px 12px rgba(0, 0, 0, .45);
}
.bws .bws-hero__lede {
  color: rgba(255, 255, 255, .92);
  font-size: var(--bws-text-lg);
  max-width: 40rem;
  margin-inline: auto;
  margin-bottom: var(--bws-space-5);
  text-shadow: 0 1px 8px rgba(0, 0, 0, .4);
}
.bws .bws-eyebrow--light {
  color: var(--bws-color-accent);
  text-shadow: 0 1px 8px rgba(0, 0, 0, .4);
}
/* Sibling-page strip under the banner: sticks below the header on wide
   screens, scrolls sideways on phones. */
.bws-subnav {
  position: -webkit-sticky;
  position: sticky;
  top: var(--bws-header-height);
  z-index: 240;
  background: var(--bws-color-surface);
  box-shadow: inset 0 -1px 0 var(--bws-color-line);
}
.bws-subnav__inner {
  display: flex;
  /* "safe" falls back to start-alignment once the tabs overflow, so a long
     list (Educational Technology's six items) stays fully reachable by
     scroll instead of centering into content clipped off the start edge —
     a documented flexbox gotcha with plain `center` + overflow-x:auto. */
  justify-content: safe center;
  gap: var(--bws-space-6);
  overflow-x: auto;
  white-space: nowrap;
  padding-block: var(--bws-space-3);
  scrollbar-width: none;
}
.bws-subnav__inner::-webkit-scrollbar { display: none; }
/* Same gold underline as the header menu: a 2px accent line that wipes in
   from the left on hover, and stays drawn under the current page. */
.bws-subnav a {
  font-weight: 600;
  font-size: var(--bws-text-sm);
  color: var(--bws-color-ink-soft);
  padding-block: var(--bws-space-1) 3px;
  background-image: linear-gradient(var(--bws-color-accent), var(--bws-color-accent));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 2px;
  transition: background-size .28s cubic-bezier(.25, .8, .25, 1), color .2s ease;
}
.bws-subnav a[aria-current="page"],
.bws-subnav a:hover,
.bws-subnav a:focus-visible {
  color: var(--bws-color-brand);
  background-size: 100% 2px;
}
@media (prefers-reduced-motion: reduce) {
  .bws-subnav a { transition: none; }
}
/* Long-form pages, Repton-style: uppercase letter-spaced headings above a
   measured column of text, sections told apart by generous space and a
   gentle tonal shift rather than rules, and a lead paragraph set larger. */
.bws-page .bws-section { padding-block: var(--bws-space-8, 3rem); }
/* Never the closing band: its white text needs its own teal fill. */
.bws-page .bws-section:nth-of-type(even):not(.bws-cta-band) { background: var(--bws-color-surface-sunk, var(--bws-color-brand-100)); }
/* ---------- Admissions: alternating sections in a saturated teal tint ---------- */
/* Everywhere else the alternation above is --bws-color-brand-100, a tint so
   pale it reads as generic light blue rather than on-brand. Admissions uses
   a more saturated tint of the same brand teal instead — clearly teal, but
   still light enough that the page's normal dark ink text, links, and form
   styling all keep working unchanged (no white-text overrides needed, the
   way a full-strength fill like #values/#spaces on the home page requires). */
.bws-page--admissions { --bws-color-surface-sunk: #a8dcd6; }
/* The photo+text split keeps its own light card look rather than the
   alternating tint — untouched by the swap above either way, since this
   sets its own explicit background regardless of --bws-color-surface-sunk. */
.bws-page--admissions .bws-split.bws-section:nth-of-type(even) {
  background: var(--bws-color-bg);
}
.bws-page .bws-section > .bws-container > h2 {
  max-width: 44rem;
  margin-inline: auto;
  margin-bottom: var(--bws-space-6);
  font-size: var(--bws-text-xl);
  font-weight: 600;
  letter-spacing: .05em;
  line-height: 1.25;
  text-transform: uppercase;
  color: var(--bws-color-brand);
}
.bws-page .bws-section > .bws-container > .bws-richtext { max-width: 44rem; margin-inline: auto; }
.bws-page .bws-richtext p { margin-bottom: var(--bws-space-4); font-size: var(--bws-text-md); line-height: 1.6; }
.bws-page .bws-richtext h3 { margin: var(--bws-space-6) 0 var(--bws-space-3); font-size: var(--bws-text-lg); letter-spacing: .04em; }
.bws-page .bws-richtext ul { padding-left: 1.2rem; margin-bottom: var(--bws-space-5); }
.bws-page .bws-richtext li { margin-bottom: var(--bws-space-2); }
/* The first text block after the banner is the lead: bigger, brand ink. */
.bws-page .bws-hero + .bws-section .bws-richtext p:first-child {
  font-size: var(--bws-text-lg);
  line-height: 1.5;
  color: var(--bws-color-ink);
}
.bws-quote__block { position: relative; margin: 0; padding-left: var(--bws-space-8); }
.bws-quote__mark {
  position: absolute;
  left: 0;
  top: -.35em;
  font-family: var(--bws-font-display);
  font-size: 5rem;
  line-height: 1;
  color: var(--bws-color-accent);
}
.bws .bws-quote__text {
  font-family: var(--bws-font-display);
  font-size: var(--bws-text-2xl);
  font-weight: 500;
  line-height: 1.35;
  color: var(--bws-color-brand);
  margin-bottom: var(--bws-space-3);
}
.bws .bws-quote__cite {
  display: block;
  font-style: normal;
  font-size: var(--bws-text-sm);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--bws-color-ink-faint, var(--bws-color-ink-soft));
}
/* Closing band, Repton-style: centred uppercase heading, the link set as
   underlined text rather than a pill. */
.bws-page .bws-cta-band { text-align: center; }
/* The long-form h2 rule above (uppercase, letter-spaced, teal) outranks
   .bws-cta-band h2, which turned the closing heading teal on its teal band.
   Restore the home page's look for it. */
.bws-page .bws-section.bws-cta-band > .bws-container > h2 {
  max-width: none;
  font-size: var(--bws-text-3xl);
  letter-spacing: normal;
  text-transform: none;
  color: #fff;
}
.bws-page .bws-cta-band p { max-width: 40rem; margin-inline: auto; }
.bws-page .bws-cta-band .bws-actions { justify-content: center; }
.bws-hero--page .bws-parallax__bg { inset: 0; -webkit-transform: none !important; transform: none !important; }
/* Compact reading rhythm for split text on inner pages (the home page keeps
   its own looser rhythm). */
.bws-page .bws-split__text .bws-richtext p { margin-bottom: var(--bws-space-3); line-height: 1.6; }
.bws-page .bws-split__text h2 { font-size: var(--bws-text-2xl); }
/* Split sections run edge to edge, so on inner pages their text would slide
   under the fixed enrollment/Inquire tab on the left and the utility rail on
   the right. Pad whichever side the text sits against. */
@media (min-width: 768px) {
  .bws-page .bws-split--image-right .bws-split__text { padding-left: calc(var(--bws-tab-width) + var(--bws-space-8)); }
  .bws-page .bws-split--image-left .bws-split__text { padding-right: calc(var(--bws-rail-width) + var(--bws-space-8)); }
}
/* Every section's container clears both rails now, not just on inner
   pages: the home page has no .bws-page wrapper, so its own bands (Core
   Values, Learning Spaces, Testimonials, News) had no rail clearance at
   all under the old .bws-page-scoped rule and ran under both rails on
   desktop widths. Collapsing safe-area tokens rather than a flat
   calc(rail + gutter), so wide screens don't over-pad once the centred
   container's own margin already clears the rail — this also means
   already-correct inner pages now sit slightly closer to the edges
   above ~1400px than before, which is the intended fix, not a
   regression: .bws-subnav__inner has worked this way for a while. */
.bws-section > .bws-container {
  padding-left: var(--bws-safe-left);
  padding-right: var(--bws-safe-right);
}
/* Banner "logo" mode: no photo, one big crest centred on the splash
   screen's teal texture with the page title beneath it. */
.bws-hero--logo {
  align-items: center;
  min-height: clamp(420px, 64vh, 680px);
  background:
    radial-gradient(ellipse at 50% 45%, rgba(58, 163, 159, .35) 0%, rgba(0, 80, 81, 0) 60%),
    radial-gradient(ellipse at 50% 50%, rgba(0, 0, 0, 0) 55%, rgba(0, 30, 31, .45) 100%),
    var(--bws-color-brand) url("/assets/images/splash-texture.jpg") center / cover no-repeat;
}
.bws-hero--logo .bws-parallax__bg,
.bws-hero--logo .bws-hero__scrim { display: none; }
.bws-hero--logo .bws-hero__caption {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding-top: calc(var(--bws-header-height) + var(--bws-space-4));
  padding-bottom: var(--bws-space-8);
  padding-left: var(--bws-space-4);
  padding-right: var(--bws-space-4);
}
.bws-hero--logo .bws-hero__caption {
  padding-left: var(--bws-safe-left);
  padding-right: var(--bws-safe-right);
}
.bws-hero__logo {
  display: block;
  width: auto;
  height: clamp(160px, 34vh, 340px);
  max-width: 100%;
  -o-object-fit: contain;
     object-fit: contain;
  margin-bottom: var(--bws-space-5);
  -webkit-filter: drop-shadow(0 0 28px rgba(255, 255, 255, .22)) drop-shadow(0 12px 30px rgba(0, 0, 0, .35));
          filter: drop-shadow(0 0 28px rgba(255, 255, 255, .22)) drop-shadow(0 12px 30px rgba(0, 0, 0, .35));
}
.bws-hero--logo .bws-hero__caption h1 { font-size: var(--bws-text-3xl); margin-bottom: 0; }
@media (max-width: 767px) {
  .bws-hero__logo { height: auto; width: min(80vw, 340px); }
}
/* Inner pages: the photo + text split is contained and centred like every
   other inner-page section, instead of running edge to edge as on the home
   page, where the photo touched the screen edge. The photo keeps its own
   rounded panel beside the text; no divider rule is needed once there is
   space between them. Same selectors as the edge-padding rules above so
   these later ones win. */
@media (min-width: 768px) {
  .bws-page .bws-split {
    padding-block: var(--bws-space-10);
    padding-inline: calc(var(--bws-rail-width) + var(--bws-space-4));
  }
  .bws-page .bws-split__track { max-width: 72rem; margin-inline: auto; }
  /* Tablets: photo stacked above the text, both inside the page gutter. */
  .bws-page .bws-split__slide:not([hidden]) {
    min-height: 0;
    gap: var(--bws-space-6);
    align-items: stretch;
  }
  .bws-page .bws-split__image:not(.bws-split__image--natural) {
    flex: 1 1 100%;
    min-height: 360px;
    border-radius: var(--bws-radius-md);
    box-shadow: var(--bws-shadow-md);
  }
  .bws-page .bws-split__text,
  .bws-page .bws-split--image-right .bws-split__text,
  .bws-page .bws-split--image-left .bws-split__text {
    flex: 1 1 100%;
    min-width: 0;
    padding: var(--bws-space-4) 0;
    border: none;
    background: transparent;
  }
}
/* Wide enough for photo and text side by side. */
@media (min-width: 1024px) {
  .bws-page .bws-split__slide:not([hidden]) { flex-wrap: nowrap; gap: var(--bws-space-10); }
  .bws-page .bws-split__image:not(.bws-split__image--natural) { flex: 0 0 44%; min-height: 420px; }
  .bws-page .bws-split__text,
  .bws-page .bws-split--image-right .bws-split__text,
  .bws-page .bws-split--image-left .bws-split__text { flex: 1 1 0; }
}
/* data.background "surface": a white section instead of the page's
   alternating tint, so a mint label pill still reads against it. */
.bws-page .bws-section.bws-split.bws-split--surface:nth-of-type(n),
.bws-page .bws-split--surface .bws-split__text { background: var(--bws-color-surface); }
/* Inner pages: a whole (uncropped) image takes its full column instead of
   the home page's 480px cap, so artwork like the logos reads at size. */
.bws-page .bws-split__image--natural { max-width: none; padding: 0; }
.bws-page .bws-split__image--natural img { width: 100%; }
@media (max-width: 1023px) {
  .bws-page .bws-split__image--natural { flex: 1 1 100%; padding: var(--bws-space-5) var(--bws-space-4) 0; }
}
@media (min-width: 1024px) {
  .bws-page .bws-split__image--natural { flex: 0 0 44%; }
}
/* Hymn lyrics in two columns on wider screens, verses kept whole. */
@media (min-width: 768px) {
  .bws-page #hymn-lyrics.bws-section > .bws-container > .bws-richtext,
  .bws-page #hymn-lyrics.bws-section > .bws-container > h2 { max-width: 52rem; }
  .bws-page #hymn-lyrics .bws-richtext { -webkit-columns: 2; columns: 2; -webkit-column-gap: var(--bws-space-10); column-gap: var(--bws-space-10); }
  .bws-page #hymn-lyrics .bws-richtext p { -webkit-column-break-inside: avoid; break-inside: avoid; }
  .bws-page #hymn-lyrics .bws-richtext p:has(> strong:only-child) { -webkit-column-break-after: avoid; break-after: avoid; }
}
/* Core Values cards on inner pages keep the home page's title size rather
   than the larger inner-page heading scale. */
.bws-page #values .bws-card h3 { font-size: var(--bws-text-xl); margin-bottom: var(--bws-space-2); }
/* Inner-page split label as a small mint pill (Our Small Beginnings). */
.bws .bws-page .bws-split__text .bws-eyebrow {
  align-self: flex-start;
  margin-bottom: var(--bws-space-4);
  padding: var(--bws-space-1) var(--bws-space-3);
  border-radius: var(--bws-radius-pill);
  background: var(--bws-color-brand-100);
  color: var(--bws-color-brand);
}
/* Level intro starts on the same left edge as the level menu above it
   ("Preschool"): the same container and side padding as .bws-subnav__inner,
   instead of the wider rail clearance other inner-page sections use, with
   the lede and fact boxes kept to a readable width. */
/* padding-inline here would reset the right side back to the plain gutter and
   outrank the shared rule above (it is far more specific), which is exactly
   how the level pages kept their title and programme list under the rail. */
.bws-page .bws-section.bws-level-intro > .bws-container {
  padding-left: var(--bws-space-4);
  padding-right: var(--bws-safe-right);
}
/* From tablets up the fixed enrollment tab covers the left edge (and the rail
   the right) until the page is wide enough for the centred container's own
   margin to clear them, so the level menu and the intro take the same extra
   clearance, only for as long as they need it, and stay aligned. */
.bws-subnav__inner,
.bws-page .bws-section.bws-level-intro > .bws-container {
  padding-left: var(--bws-safe-left);
}
.bws-subnav__inner {
  padding-right: var(--bws-safe-right);
}
.bws-page .bws-section.bws-level-intro .bws-level-intro__inner > * {
  max-width: 44rem;
  margin-inline: 0;
}
.bws-page .bws-section.bws-level-intro .bws-level-intro__fact + .bws-level-intro__fact { margin-top: var(--bws-space-3); }
/* A small source photo beside its text: one row, the photo at its own
   width, text taking the rest, both centred on each other. */
.bws-split__image--natural {
  flex: 0 0 auto;
  min-height: 0;
  max-width: min(46%, 480px);
  background: none;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--bws-space-6);
}
.bws-split__image--natural img { max-width: 100%; height: auto; border-radius: var(--bws-radius-md); box-shadow: var(--bws-shadow-md); }
.bws-split__slide:has(.bws-split__image--natural) { min-height: 0; align-items: center; }
.bws-split__slide:has(.bws-split__image--natural) .bws-split__text { flex: 1 1 0; padding-block: var(--bws-space-8); }
/* Two or more full-width photos stacked in the image column, each shown
   whole rather than cropped to a shared box — for a pair of photos that
   belong together (e.g. an older photo kept alongside a new one) where
   paging through one at a time (the carousel above) would hide one of them
   by default. Column width/min-height stay whatever the page-scoped
   .bws-split__image rules above already set (they apply to this too, since
   it isn't --natural); only the single-photo border-radius/shadow — wrong
   here since this wraps two separate photos, not one — get cancelled, at
   matching specificity so the cascade actually picks this up. */
.bws-split__image--stack {
  background: none;
  display: flex;
  flex-direction: column;
  gap: var(--bws-space-4);
}
.bws-split__image--stack img { display: block; width: 100%; border-radius: var(--bws-radius-md); }
.bws-page .bws-split__image.bws-split__image--stack { border-radius: 0; box-shadow: none; }
/* Photo floated into a text block. */
.bws-richtext__eyebrow { max-width: 44rem; margin-inline: auto; margin-bottom: var(--bws-space-3); }
.bws-richtext__photo {
  width: min(46%, 420px);
  height: auto;
  border-radius: var(--bws-radius-md);
  box-shadow: var(--bws-shadow-md);
  margin: .3rem 0 var(--bws-space-4);
}
.bws-richtext__photo--right { float: right; margin-left: var(--bws-space-6); }
.bws-richtext__photo--left { float: left; margin-right: var(--bws-space-6); }
.bws-richtext::after { content: ""; display: block; clear: both; }
@media (max-width: 640px) {
  .bws-richtext__photo, .bws-richtext__photo--right, .bws-richtext__photo--left { float: none; width: 100%; margin-inline: 0; }
}
/* ---------- Drawer: Apple Distinguished School link with the Apple mark ---------- */
.bws-drawer__link--apple {
  /* The shared drawer-link rule spreads its children to opposite ends;
     keep the words right beside the Apple mark instead. */
  justify-content: flex-start;
  gap: .45em;
}
.bws-drawer__link--apple svg {
  width: auto;
  height: .95em;
  fill: currentColor;
  -webkit-transform: translateY(-.08em);
          transform: translateY(-.08em);
  flex: none;
}
/* ---------- Video block: a film played in the page ---------- */
.bws-video-block .bws-container { max-width: 1040px; text-align: center; }
.bws .bws-video-block__lede {
  max-width: 60ch;
  margin-inline: auto;
  color: var(--bws-color-ink-soft);
}
.bws-video-block__player {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  margin-top: var(--bws-space-6);
  border-radius: 18px;
  background: #000;
}
/* YouTube film shown as its poster with a play button until pressed. */
.bws-video-block__facade {
  position: relative;
  overflow: hidden;
  color: #fff;
}
.bws-video-block__facade img {
  display: block;
  width: 100%;
  height: 100%;
  -o-object-fit: cover;
     object-fit: cover;
  transition: opacity .3s ease, -webkit-transform .5s ease;
  transition: transform .5s ease, opacity .3s ease;
  transition: transform .5s ease, opacity .3s ease, -webkit-transform .5s ease;
}
.bws-video-block__facade::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0) 45%, rgba(0, 0, 0, .35) 100%);
}
.bws-video-block__play {
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 50%;
  display: grid;
  place-items: center;
  width: 84px;
  height: 84px;
  border-radius: 50%;
  background: var(--bws-color-accent);
  color: var(--bws-color-brand);
  box-shadow: 0 10px 30px rgba(0, 0, 0, .3);
  -webkit-transform: translate(-50%, -50%);
          transform: translate(-50%, -50%);
  transition: background .25s ease, -webkit-transform .25s ease;
  transition: transform .25s ease, background .25s ease;
  transition: transform .25s ease, background .25s ease, -webkit-transform .25s ease;
}
.bws-video-block__play svg { margin-left: 4px; }
.bws-video-block__facade:hover img { -webkit-transform: scale(1.03); transform: scale(1.03); }
.bws-video-block__facade:hover .bws-video-block__play,
.bws-video-block__facade:focus-visible .bws-video-block__play { -webkit-transform: translate(-50%, -50%) scale(1.08); transform: translate(-50%, -50%) scale(1.08); background: #fff; }
.bws-video-block__facade:focus-visible { outline: 3px solid var(--bws-color-accent); outline-offset: 4px; }
iframe.bws-video-block__player { border: 0; }
/* ---------- Timeline block: milestones down a centre line ---------- */
/* Cards alternate either side of a centre line with the date opposite, like
   the old site's milestones. The line's teal fill and each point's lit state
   are driven by home.js as the page scrolls; until it marks the track
   .is-ready they show as fully reached, so nothing depends on script. */
.bws-page .bws-section.bws-timeline:nth-of-type(n) { background: var(--bws-color-surface); }
.bws .bws-timeline__heading {
  margin: 0 auto var(--bws-space-8);
  max-width: 44rem;
  text-align: center;
  font-size: var(--bws-text-lg);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--bws-color-brand);
}
.bws-timeline__track { position: relative; max-width: 64rem; margin-inline: auto; }
.bws-timeline__line {
  position: absolute;
  top: 20px;
  bottom: 20px;
  left: 20px;
  width: 2px;
  background: var(--bws-color-line);
  -webkit-transform: translateX(-50%);
          transform: translateX(-50%);
}
.bws-timeline__progress {
  width: 100%;
  height: 100%;
  background: var(--bws-color-brand-600);
  -webkit-transform-origin: top center;
          transform-origin: top center;
}
.bws-timeline__track.is-ready .bws-timeline__progress { -webkit-transform: scaleY(var(--bws-timeline-progress, 0)); transform: scaleY(var(--bws-timeline-progress, 0)); }
.bws-timeline__list,
.bws-timeline__list > li { list-style: none; margin: 0; padding: 0; }
.bws-timeline__item {
  position: relative;
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  -webkit-column-gap: var(--bws-space-4);
          column-gap: var(--bws-space-4);
  align-items: start;
}
.bws-timeline__item + .bws-timeline__item { margin-top: var(--bws-space-6); }
.bws-timeline__point {
  grid-column: 1;
  grid-row: 1 / span 2;
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--bws-color-brand);
  color: #fff;
  box-shadow: 0 0 0 4px var(--bws-color-surface);
  transition: background .3s ease, color .3s ease;
}
.bws .bws-timeline__date {
  grid-column: 2;
  grid-row: 1;
  margin: 8px 0 var(--bws-space-2);
  font-family: var(--bws-font-display);
  font-weight: 600;
  font-size: var(--bws-text-md);
  color: var(--bws-color-brand-600);
  transition: color .3s ease;
}
.bws-timeline__card {
  grid-column: 2;
  grid-row: 2;
  position: relative;
  padding: var(--bws-space-5) var(--bws-space-6);
  background: var(--bws-color-surface);
  border-radius: var(--bws-radius-md);
  box-shadow: 0 10px 30px rgba(22, 31, 28, .08), 0 1px 2px rgba(22, 31, 28, .06);
}
.bws .bws-timeline__card h3 {
  margin: 0 0 var(--bws-space-2);
  font-size: var(--bws-text-lg);
  letter-spacing: .02em;
  color: var(--bws-color-brand);
}
.bws .bws-timeline__card p { margin: 0; color: var(--bws-color-ink); line-height: 1.6; }
.bws-timeline__card ul { margin: 0; padding-left: 1.2rem; list-style: disc; color: var(--bws-color-ink); line-height: 1.6; }
.bws-timeline__card li + li { margin-top: 2px; }
/* Not yet reached (only once script is running the scroll effect). */
.bws-timeline__track.is-ready .bws-timeline__item:not(.is-active) .bws-timeline__point { background: var(--bws-color-brand-100); color: var(--bws-color-brand-400); }
.bws-timeline__track.is-ready .bws-timeline__item:not(.is-active) .bws-timeline__date { color: var(--bws-color-ink-soft); }
/* Cards glide in from their own side as they scroll into view. */
.bws-timeline__track.is-animated .bws-timeline__card {
  opacity: 0;
  -webkit-transform: translateY(24px);
          transform: translateY(24px);
  transition: opacity .6s ease, -webkit-transform .6s cubic-bezier(.16, 1, .3, 1);
  transition: opacity .6s ease, transform .6s cubic-bezier(.16, 1, .3, 1);
  transition: opacity .6s ease, transform .6s cubic-bezier(.16, 1, .3, 1), -webkit-transform .6s cubic-bezier(.16, 1, .3, 1);
}
.bws-timeline__track.is-animated .bws-timeline__item.is-visible .bws-timeline__card { opacity: 1; -webkit-transform: none; transform: none; }
@media (min-width: 900px) {
  .bws-timeline__line { left: 50%; }
  .bws-timeline__item {
    grid-template-columns: minmax(0, 1fr) 40px minmax(0, 1fr);
    -webkit-column-gap: var(--bws-space-8);
            column-gap: var(--bws-space-8);
    align-items: center;
  }
  /* No overlap between neighbouring cards: with multi-line milestones a
     staggered pull-up let a tall card run into the next one and its date. */
  .bws-timeline__item + .bws-timeline__item { margin-top: var(--bws-space-5); }
  .bws-timeline__point { grid-column: 2; grid-row: 1; }
  .bws .bws-timeline__date { grid-row: 1; margin: 0; }
  .bws-timeline__card { grid-row: 1; }
  .bws-timeline__item--left .bws-timeline__card { grid-column: 1; }
  .bws-timeline__item--left .bws-timeline__date { grid-column: 3; text-align: left; }
  .bws-timeline__item--right .bws-timeline__card { grid-column: 3; }
  .bws-timeline__item--right .bws-timeline__date { grid-column: 1; text-align: right; }
  /* Notch on the card pointing at its point on the line. */
  .bws-timeline__card::before {
    content: "";
    position: absolute;
    top: 50%;
    width: 14px;
    height: 14px;
    background: var(--bws-color-surface);
    -webkit-transform: translateY(-50%) rotate(45deg);
            transform: translateY(-50%) rotate(45deg);
  }
  .bws-timeline__item--left .bws-timeline__card::before { right: -7px; box-shadow: 3px -3px 6px rgba(22, 31, 28, .04); }
  .bws-timeline__item--right .bws-timeline__card::before { left: -7px; box-shadow: -3px 3px 6px rgba(22, 31, 28, .04); }
  .bws-timeline__track.is-animated .bws-timeline__item--left .bws-timeline__card { -webkit-transform: translateX(-40px); transform: translateX(-40px); }
  .bws-timeline__track.is-animated .bws-timeline__item--right .bws-timeline__card { -webkit-transform: translateX(40px); transform: translateX(40px); }
  .bws-timeline__track.is-animated .bws-timeline__item.is-visible .bws-timeline__card { -webkit-transform: none; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .bws-timeline__point, .bws .bws-timeline__date { transition: none; }
}
/* ---------- People block: portrait cards ---------- */
/* Heading and lede centred over the portrait grid: the grid is wider than
   the 44rem reading column, so left-aligned text started to the right of
   the first portrait and the section read as misaligned. */
.bws-page .bws-section.bws-people > .bws-container > h2,
.bws-page .bws-section.bws-people > .bws-container > .bws-people__lede { max-width: 48rem; margin-inline: auto; text-align: center; }
.bws-people__grid.bws-people__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--bws-space-6) var(--bws-space-5);
  max-width: 64rem;
  margin: var(--bws-space-8) auto 0;
  padding: 0;
  list-style: none;
}
@media (min-width: 900px) {
  .bws-people__grid.bws-people__grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.bws-people__card { text-align: center; }
.bws-people__photo {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 5 / 7;
  -o-object-fit: cover;
     object-fit: cover;
  border-radius: var(--bws-radius-md);
  box-shadow: var(--bws-shadow-md);
  margin-bottom: var(--bws-space-4);
}
.bws .bws-people__name {
  margin: 0 0 var(--bws-space-1);
  font-size: var(--bws-text-md);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: 0;
  text-transform: none;
  color: var(--bws-color-brand);
}
.bws .bws-people__role { margin: 0; font-size: var(--bws-text-sm); line-height: 1.45; color: var(--bws-color-ink-soft); }
.bws .bws-people__role:first-of-type { color: var(--bws-color-ink); font-weight: 600; }
/* ---------- Gallery block: a row of photos with short captions ---------- */
.bws-gallery__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--bws-space-5);
  margin-top: var(--bws-space-6);
}
@media (min-width: 768px) {
  .bws-gallery__grid { grid-template-columns: repeat(3, 1fr); }
}
.bws-gallery__item { margin: 0; }
.bws-gallery__item img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  -o-object-fit: cover;
     object-fit: cover;
  border-radius: 14px;
}
.bws-gallery__item figcaption {
  margin-top: var(--bws-space-2);
  font-size: var(--bws-text-sm);
  color: var(--bws-color-ink-soft);
}
/* ---------- School level intro (level pages) ---------- */
/* The current site's opening for each level: a big teal name, the lede, then
   each key fact as a solid teal label beside a mint list. Selectors carry
   extra weight on purpose: the inner-page rules tint even sections and turn
   a container's h2 into a small uppercase heading, and this block must win
   over both. */
.bws-page .bws-section.bws-level-intro:nth-of-type(n) {
  background: var(--bws-color-surface);
  padding-block: var(--bws-space-10) var(--bws-space-8);
}
/* Left-aligned with the lede and fact boxes below it (and the level menu). */
.bws-page .bws-section.bws-level-intro .bws-level-intro__title {
  max-width: none;
  margin: 0 0 var(--bws-space-5);
  font-size: var(--bws-text-4xl);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: 0;
  text-transform: none;
  color: var(--bws-color-brand);
}
.bws .bws-level-intro__lede {
  max-width: 44rem;
  margin: 0 0 var(--bws-space-6);
  font-size: var(--bws-text-lg);
  line-height: 1.6;
  color: var(--bws-color-ink);
}
.bws-level-intro__fact {
  display: grid;
  grid-template-columns: minmax(8rem, 11rem) minmax(0, 1fr);
  max-width: 44rem;
}
.bws-level-intro__fact + .bws-level-intro__fact { margin-top: var(--bws-space-3); }
.bws .bws-level-intro__label {
  margin: 0;
  padding: var(--bws-space-4) var(--bws-space-5);
  background: var(--bws-color-brand);
  color: #fff;
  font-family: var(--bws-font-display);
  font-size: var(--bws-text-lg);
  font-weight: 700;
  line-height: 1.2;
  text-transform: uppercase;
}
/* Two classes: the global ul[class] reset otherwise strips the bullets. */
.bws-level-intro__fact .bws-level-intro__items {
  margin: 0;
  padding: var(--bws-space-4) var(--bws-space-5) var(--bws-space-4) calc(var(--bws-space-5) + 1.1rem);
  list-style: disc;
  background: var(--bws-color-brand-100);
  color: var(--bws-color-brand);
  font-size: var(--bws-text-md);
  line-height: 1.5;
}
@media (max-width: 480px) {
  .bws-level-intro__fact { grid-template-columns: minmax(0, 1fr); }
  .bws .bws-level-intro__label { font-size: var(--bws-text-md); padding-block: var(--bws-space-3); }
}
/* ---------- BEACON portals pop-out (utility rail, ismanila.org-style) ---------- */
.bws-portal-menu { position: relative; }
.bws-portal-menu > summary { list-style: none; }
.bws-portal-menu > summary::-webkit-details-marker { display: none; }
/* Open: a gold ring on the icon, as on ISM's rail. */
.bws-portal-menu[open] > summary {
  border-color: var(--bws-color-accent);
  box-shadow: 0 0 0 2px var(--bws-color-accent);
}
.bws-portal-menu__panel {
  position: absolute;
  top: 50%;
  /* Measured from the rail's edge, not the icon's: the 48px icon sits
     centred in the wider rail, so clear that inset plus a 12px gap. */
  right: calc(100% + (var(--bws-rail-width) - 48px) / 2 + 12px);
  -webkit-transform: translateY(-50%);
          transform: translateY(-50%);
  min-width: 220px;
  padding: var(--bws-space-3) 0;
  background: #fff;
  border-radius: var(--bws-radius-md);
  box-shadow: 0 12px 32px rgba(0, 0, 0, .18);
  -webkit-animation: bws-portal-menu-in .18s ease-out;
          animation: bws-portal-menu-in .18s ease-out;
}
/* Arrow pointing back at the icon. */
.bws-portal-menu__panel::after {
  content: "";
  position: absolute;
  top: 50%;
  right: -8px;
  -webkit-transform: translateY(-50%);
          transform: translateY(-50%);
  border-block: 8px solid transparent;
  border-left: 8px solid #fff;
}
/* BEACON wordmark heading the card, set off from the links by a hairline.
   The hairline belongs to the wrapper, which shares the links' text column;
   the image inside is pulled left so the lighthouse — the stroke the eye
   reads as the wordmark's first letter — lands on that same edge. Flush to
   its own box the mark looked indented beside "My Portal", because 8.2% of
   the image's width is empty space before the tower begins. */
.bws-portal-menu__logo {
  display: block;
  margin: var(--bws-space-2) var(--bws-space-6) var(--bws-space-3);
  padding-bottom: var(--bws-space-3);
  border-bottom: 1px solid var(--bws-color-line);
}
.bws-portal-menu__logo img {
  display: block;
  width: auto;
  height: 32px;
  /* 8.2% of the rendered width — 32px tall × 439/116 ≈ 121px. */
  margin-left: -10px;
}
/* Tells a signed-in visitor they already are, so "My Portal" doesn't read as
   one more sign-in prompt. */
.bws-portal-menu__badge {
  display: inline-block;
  margin-left: var(--bws-space-2);
  padding: 2px 8px;
  font-size: var(--bws-text-xs);
  font-weight: 600;
  color: var(--bws-color-brand);
  background: var(--bws-color-brand-100);
  border-radius: var(--bws-radius-pill);
  vertical-align: middle;
}
.bws-portal-menu__panel a {
  display: block;
  padding: var(--bws-space-3) var(--bws-space-6);
  font-family: var(--bws-font-display);
  font-weight: 500;
  font-size: var(--bws-text-md);
  color: var(--bws-color-brand);
  white-space: nowrap;
}
.bws-portal-menu__panel a:hover,
.bws-portal-menu__panel a:focus-visible {
  background: var(--bws-color-brand-100);
  color: var(--bws-color-brand);
}
@-webkit-keyframes bws-portal-menu-in {
  from { opacity: 0; -webkit-transform: translate(8px, -50%); transform: translate(8px, -50%); }
  to { opacity: 1; -webkit-transform: translate(0, -50%); transform: translate(0, -50%); }
}
@keyframes bws-portal-menu-in {
  from { opacity: 0; -webkit-transform: translate(8px, -50%); transform: translate(8px, -50%); }
  to { opacity: 1; -webkit-transform: translate(0, -50%); transform: translate(0, -50%); }
}
@media (prefers-reduced-motion: reduce) {
  .bws-portal-menu__panel { -webkit-animation: none; animation: none; }
}
/* ---------- Contact pop-out (utility rail) ---------- */
/* Same mechanics as the portals menu above (a <details> card that pops out
   to the left), but for the ways to actually reach the school — phone,
   email, the inquiry form, and social — instead of just one chat icon that
   only ever linked to the admissions inquiry anchor. */
.bws-contact-menu { position: relative; }
.bws-contact-menu > summary { list-style: none; }
.bws-contact-menu > summary::-webkit-details-marker { display: none; }
.bws-contact-menu[open] > summary {
  border-color: var(--bws-color-accent);
  box-shadow: 0 0 0 2px var(--bws-color-accent);
}
.bws-contact-menu__panel {
  position: absolute;
  top: 50%;
  right: calc(100% + (var(--bws-rail-width) - 48px) / 2 + 12px);
  -webkit-transform: translateY(-50%);
          transform: translateY(-50%);
  min-width: 240px;
  padding: var(--bws-space-5) 0 var(--bws-space-3);
  background: #fff;
  border-radius: var(--bws-radius-md);
  box-shadow: 0 12px 32px rgba(0, 0, 0, .18);
  -webkit-animation: bws-portal-menu-in .18s ease-out;
          animation: bws-portal-menu-in .18s ease-out;
}
.bws-contact-menu__panel::after {
  content: "";
  position: absolute;
  top: 50%;
  right: -8px;
  -webkit-transform: translateY(-50%);
          transform: translateY(-50%);
  border-block: 8px solid transparent;
  border-left: 8px solid #fff;
}
/* Two classes: the global `.bws h2` rule (class + element) otherwise wins and
   turns this small label into a full-size heading that wraps on phones. */
.bws-contact-menu__panel .bws-contact-menu__heading {
  margin: 0 var(--bws-space-6) var(--bws-space-2);
  font-family: var(--bws-font-display);
  font-size: var(--bws-text-xs);
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--bws-color-ink-soft);
}
.bws-contact-menu__links { display: flex; flex-direction: column; }
.bws-contact-menu__links a {
  display: block;
  padding: var(--bws-space-2) var(--bws-space-6);
  font-family: var(--bws-font-display);
  font-weight: 500;
  font-size: var(--bws-text-md);
  color: var(--bws-color-brand);
  white-space: nowrap;
}
.bws-contact-menu__links a:hover,
.bws-contact-menu__links a:focus-visible {
  background: var(--bws-color-brand-100);
  color: var(--bws-color-brand);
}
.bws-contact-menu__social {
  display: flex;
  gap: var(--bws-space-2);
  margin: var(--bws-space-3) var(--bws-space-6) 0;
  padding-top: var(--bws-space-3);
  border-top: 1px solid var(--bws-color-line);
}
.bws-contact-menu__social a {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--bws-radius-pill);
  background: var(--bws-color-brand-100);
  color: var(--bws-color-brand);
}
.bws-contact-menu__social a:hover,
.bws-contact-menu__social a:focus-visible { background: var(--bws-color-accent-100); }
@media (prefers-reduced-motion: reduce) {
  .bws-contact-menu__panel { -webkit-animation: none; animation: none; }
}
/* ---------- Rail pop-outs on smaller screens ---------- */
/* Centred on their icon, both cards ran off the top of a tablet or phone
   (the rail's icons sit close to the top edge there), and their nowrap links
   pushed the contact card off the left edge of a phone. Tablets: open level
   with the icon's top instead, arrow still on the icon. */
@media (max-width: 1023px) {
  .bws-portal-menu__panel,
  .bws-contact-menu__panel {
    top: 0;
    -webkit-transform: none;
            transform: none;
    -webkit-animation-name: bws-rail-panel-in;
            animation-name: bws-rail-panel-in;
  }
  .bws-portal-menu__panel::after,
  .bws-contact-menu__panel::after {
    top: calc(var(--bws-rail-icon) / 2);
  }
}
/* Phones: there is no room beside a 40px icon, so the card spans from the
   screen's left margin to the rail, pinned near the top, scrolls if it is
   taller than the screen, and lets long links (the HR email) wrap. */
@media (max-width: 767px) {
  .bws-portal-menu__panel,
  .bws-contact-menu__panel {
    position: fixed;
    top: var(--bws-space-3);
    right: calc(var(--bws-rail-width) + var(--bws-space-2));
    left: var(--bws-space-3);
    min-width: 0;
    max-height: calc(100dvh - 2 * var(--bws-space-3));
    overflow-y: auto;
  }
  .bws-portal-menu__panel::after,
  .bws-contact-menu__panel::after { display: none; }
  .bws-portal-menu__panel a,
  .bws-contact-menu__links a {
    white-space: normal;
    overflow-wrap: anywhere;
  }
}
@-webkit-keyframes bws-rail-panel-in {
  from { opacity: 0; -webkit-transform: translateX(8px); transform: translateX(8px); }
  to { opacity: 1; -webkit-transform: none; transform: none; }
}
@keyframes bws-rail-panel-in {
  from { opacity: 0; -webkit-transform: translateX(8px); transform: translateX(8px); }
  to { opacity: 1; -webkit-transform: none; transform: none; }
}
/* ---------- Admissions: FAQ list ---------- */
/* Same disclosure chevron as the drawer's category groups, so an accordion
   reads the same way wherever it appears on the site. */
.bws-faq__list { display: flex; flex-direction: column; }
.bws-faq__item {
  border-bottom: 1px solid var(--bws-color-line);
}
.bws-faq__item:first-child { border-top: 1px solid var(--bws-color-line); }
.bws-faq__question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bws-space-4);
  padding: var(--bws-space-4) 0;
  font-family: var(--bws-font-display);
  font-weight: 600;
  font-size: var(--bws-text-lg);
  color: var(--bws-color-ink);
  cursor: pointer;
  list-style: none;
}
.bws-faq__question::-webkit-details-marker { display: none; }
.bws-faq__question::after {
  content: "";
  width: 8px;
  height: 8px;
  flex-shrink: 0;
  border-right: 2px solid var(--bws-color-ink-soft);
  border-top: 2px solid var(--bws-color-ink-soft);
  -webkit-transform: rotate(135deg);
          transform: rotate(135deg);
  transition: -webkit-transform .2s ease;
  transition: transform .2s ease;
  transition: transform .2s ease, -webkit-transform .2s ease;
}
.bws-faq__item[open] .bws-faq__question::after { -webkit-transform: rotate(225deg); transform: rotate(225deg); }
.bws-faq__answer { margin: 0 0 var(--bws-space-4); color: var(--bws-color-ink-soft); max-width: 60ch; }
/* Only takes effect once JS has wired up a group's exclusivity/sequencing
   (.is-enhanced, added by initFaqAccordion in home.js) — until then the
   wrapper is unstyled and native <details> shows/hides the answer
   instantly via [open], so a JS failure never leaves an answer stuck
   collapsed. */
.bws-faq__list.is-enhanced .bws-faq__answer-wrap {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .3s cubic-bezier(.16, 1, .3, 1);
  transition: grid-template-rows .3s cubic-bezier(.16, 1, .3, 1), -ms-grid-rows .3s cubic-bezier(.16, 1, .3, 1);
}
.bws-faq__list.is-enhanced .bws-faq__answer-wrap > .bws-faq__answer {
  overflow: hidden;
  min-height: 0;
}
.bws-faq__list.is-enhanced .bws-faq__item.is-open > .bws-faq__answer-wrap {
  grid-template-rows: 1fr;
}
/* The chevron's existing [open]-keyed rule (below) only flips at the very
   end of a close, once JS clears the native attribute — this rule keys off
   .is-open instead (cleared immediately on click) so the chevron rotates
   back in sync with the content collapsing, once a group is enhanced. */
.bws-faq__list.is-enhanced .bws-faq__item.is-open .bws-faq__question::after { -webkit-transform: rotate(225deg); transform: rotate(225deg); }
@media (prefers-reduced-motion: reduce) {
  .bws-faq__list.is-enhanced .bws-faq__answer-wrap { transition: none; }
}
/* ---------- Admissions: requirements checklist ---------- */
/* The reset above strips <ul> markers site-wide, so the check icon is drawn
   with a ::before rather than a list-style — it needs to sit at a fixed
   size regardless of the reset. */
.bws-checklist {
  display: flex;
  flex-direction: column;
  gap: var(--bws-space-3);
  margin-top: var(--bws-space-5);
}
.bws-checklist li {
  display: flex;
  align-items: flex-start;
  gap: var(--bws-space-3);
  color: var(--bws-color-ink);
}
.bws-checklist li::before {
  content: "";
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  margin-top: 2px;
  border-radius: 50%;
  background-color: var(--bws-color-brand-100);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23005051' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 12px;
}
/* ---------- Admissions: inquiry form + aside ---------- */
/* The two hand-rolled <fieldset> groups (Parent/guardian, Child) get real
   styling instead of the browser's default border-and-inset-legend chrome —
   a plain heading row reads calmer and matches every other section label
   on the page. */
.bws-fieldset {
  border: 0;
  padding: 0;
  margin: 0 0 var(--bws-space-6);
  min-width: 0;
}
.bws-fieldset legend {
  padding: 0 0 var(--bws-space-3);
  font-family: var(--bws-font-display);
  font-weight: 700;
  font-size: var(--bws-text-xs);
  letter-spacing: .08em;
  text-transform: uppercase;
  /* The deeper brand green, not brand-600: at this size #007c83 on the form's
     white panel is about 4:1, under the 4.5:1 minimum for text this small. */
  color: var(--bws-color-brand);
}
.bws-inquire {
  display: grid;
  gap: var(--bws-space-8);
}
.bws-inquire__form { min-width: 0; }
.bws-inquire__note {
  margin: var(--bws-space-2) 0 var(--bws-space-6);
  font-size: var(--bws-text-sm);
  color: var(--bws-color-ink-soft);
}
.bws-inquire__note a { color: var(--bws-color-brand-600); font-weight: 600; }
.bws-inquire__note a:hover { text-decoration: underline; }
.bws-inquire__aside {
  background: var(--bws-color-surface);
  border: 1px solid var(--bws-color-line);
  border-radius: var(--bws-radius-lg);
  padding: var(--bws-space-6);
  align-self: start;
  height: -webkit-fit-content;
  height: -moz-fit-content;
  height: fit-content;
}
/* A rounded panel, not a pill: the enrollment label is a full sentence
   ("Regular enrollment opens every May. Inquire anytime."), and a pill
   shape forces that onto a cramped two-line wrap that reads as broken. */
.bws-inquire__status {
  display: block;
  padding: var(--bws-space-3) var(--bws-space-4);
  border-radius: var(--bws-radius-md);
  font-weight: 600;
  font-size: var(--bws-text-sm);
  line-height: 1.4;
  background: var(--bws-color-brand-100);
  color: var(--bws-color-brand-600);
  margin-bottom: var(--bws-space-5);
}
.bws-inquire__status--open { background: #e3f3e8; color: var(--bws-color-success); }
.bws-inquire__status--reservation { background: var(--bws-color-accent-100); color: var(--bws-color-warning); }
.bws-inquire__aside h3 {
  font-size: var(--bws-text-md);
  margin-bottom: var(--bws-space-3);
}
.bws-inquire__aside h3:not(:first-of-type) { margin-top: var(--bws-space-6); }
.bws-inquire__steps {
  display: flex;
  flex-direction: column;
  gap: var(--bws-space-3);
  counter-reset: inquire-step;
}
.bws-inquire__steps li {
  display: flex;
  gap: var(--bws-space-3);
  color: var(--bws-color-ink-soft);
  font-size: var(--bws-text-sm);
}
.bws-inquire__steps li::before {
  counter-increment: inquire-step;
  content: counter(inquire-step);
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--bws-color-brand-100);
  color: var(--bws-color-brand-600);
  font-weight: 700;
  font-size: var(--bws-text-xs);
}
.bws-inquire__contact { display: flex; flex-direction: column; gap: var(--bws-space-2); }
.bws-inquire__contact a { display: flex; align-items: center; gap: var(--bws-space-2); color: var(--bws-color-brand-600); font-weight: 600; }
.bws-inquire__contact a:hover { text-decoration: underline; }
.bws-inquire__contact-icon {
  display: inline-grid;
  place-items: center;
  flex-shrink: 0;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  background: var(--bws-color-brand);
  color: #fff;
}
/* Sits right under the "Inquire about admission" heading, above the form
   fields — a tinted panel so it reads as its own card, not another form
   field. The note inside reuses .bws-inquire__note's own styling. */
.bws-inquire__talk {
  margin: var(--bws-space-4) 0 var(--bws-space-6);
  padding: var(--bws-space-5);
  background: var(--bws-color-brand-100);
  border-radius: var(--bws-radius-md);
}
.bws-inquire__talk h3 {
  font-size: var(--bws-text-md);
  margin-bottom: var(--bws-space-3);
}
.bws-inquire__talk .bws-inquire__note {
  margin: var(--bws-space-4) 0 0;
  padding-top: var(--bws-space-4);
  border-top: 1px solid var(--bws-color-line);
}
@media (min-width: 900px) {
  .bws-inquire { grid-template-columns: 1.6fr 1fr; }
  .bws-inquire__aside { position: -webkit-sticky; position: sticky; top: calc(var(--bws-header-height) + var(--bws-space-6)); }
}
/* ---------- Admissions: numbered process steps ---------- */
/* Static and single-file, unlike .bws-timeline above (that one is a
   date-based, scroll-animated zigzag for history-style content). This is
   four ordered steps in a row, discs sitting on a connecting rule. */
.bws-steps {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--bws-space-6);
  counter-reset: step;
}
.bws-steps__item {
  position: relative;
  padding-left: calc(32px + var(--bws-space-4));
}
.bws-steps__item h3 { font-size: var(--bws-text-md); margin-bottom: var(--bws-space-1); }
.bws-steps__item p { margin: 0; font-size: var(--bws-text-sm); }
.bws-steps__marker {
  position: absolute;
  left: 0;
  top: 0;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--bws-color-brand);
  color: #fff;
  font-family: var(--bws-font-display);
  font-weight: 700;
  font-size: var(--bws-text-sm);
}
/* The vertical rail: a line running down through each disc, stopping short
   of the last one. Positioned on the marker's own column rather than the
   item's edge so it stays centred through the disc regardless of gap size. */
.bws-steps__item:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 15px;
  top: 32px;
  bottom: calc(-1 * var(--bws-space-6));
  width: 2px;
  background: var(--bws-color-line);
}
@media (min-width: 768px) {
  /* Horizontal from here: the rule runs through every disc's centre in one
     line behind the row, each step's own text sitting below its disc. */
  .bws-steps {
    grid-template-columns: repeat(4, 1fr);
    gap: var(--bws-space-5);
    position: relative;
  }
  .bws-steps::before {
    content: "";
    position: absolute;
    top: 16px;
    /* Runs disc-centre to disc-centre across 4 equal columns: the first
       disc sits at the 1/8 mark of the row, the last at 7/8. */
    left: calc(100% / 8);
    right: calc(100% / 8);
    height: 2px;
    background: var(--bws-color-line);
  }
  .bws-steps__item {
    padding-left: 0;
    padding-top: calc(32px + var(--bws-space-4));
  }
  .bws-steps__item::before { display: none; }
  .bws-steps__marker { left: 50%; top: 0; -webkit-transform: translateX(-50%); transform: translateX(-50%); }
  .bws-steps__item h3,
  .bws-steps__item p { text-align: center; }
  /* The section heading stayed left-aligned by the sitewide default while
     the row of steps beneath it spread out centred and symmetric — it read
     as disconnected from what it was labelling. Scoped to this section by
     id, the same way #intro.bws-intro h2 is elsewhere: below 768px the
     steps stack left-aligned too, so the heading matches them without help. */
  #process h2 { text-align: center; }
}
/* ---------- Photo cards (cards data.with_images) and gallery variants ---------- */
/* Educational Technology pages: a photo on every card, a bullet list where a
   card needs one, a two-up gallery, and galleries of posters, certificates and
   newsletters shown whole rather than cropped. */
.bws-grid--photo-cards .bws-card__image { height: auto; aspect-ratio: 16 / 9; }
.bws-grid--photo-cards .bws-card--flush-top > a { display: inline-block; margin: 0 var(--bws-space-5) var(--bws-space-5); }
/* Scoped by the card, not the bare class: the `ul[class]` reset up top is an
   attribute selector, so it out-specifies a lone class and was zeroing this
   list's margin, padding and bullets — the points sat flush at the card edge
   while the paragraph beside them kept its inset. */
.bws-card .bws-card__points { margin: calc(-1 * var(--bws-space-3)) var(--bws-space-5) var(--bws-space-5); padding-left: 1.2em; list-style: disc; }
.bws-card .bws-card__points li + li { margin-top: 0.35em; }
.bws-gallery__lede { max-width: 48rem; }
@media (min-width: 768px) {
  .bws-gallery__grid--2 { grid-template-columns: repeat(2, 1fr); }
}
.bws-gallery--natural .bws-gallery__grid { align-items: start; }
.bws-gallery--natural .bws-gallery__item img { aspect-ratio: auto; height: auto; -o-object-fit: contain; object-fit: contain; }
.bws-richtext img.bws-inline-logo { display: block; width: 120px; height: auto; margin: 0 0 var(--bws-space-4); }
/* ---------- Snapshot, milestones and impact (Educational Technology overview) ---------- */
/* Snapshot: the section film beside teal-barred panels of figures. */
.bws-snapshot__layout { display: grid; gap: var(--bws-space-6); margin-top: var(--bws-space-6); }
@media (min-width: 1024px) {
  .bws-snapshot__layout { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); align-items: center; }
}
.bws-snapshot__film { margin: 0; }
.bws-snapshot__groups { display: grid; gap: var(--bws-space-5); }
.bws-snapshot__group { background: var(--bws-color-surface); border-radius: 16px; overflow: hidden; box-shadow: 0 10px 30px rgba(0, 60, 62, .08); }
.bws-snapshot__bar {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--bws-space-2) var(--bws-space-4);
  padding: var(--bws-space-3) var(--bws-space-5); background: var(--bws-color-brand); color: #fff;
}
.bws .bws-snapshot__bar h3 { margin: 0; color: #fff; font-size: var(--bws-text-sm); letter-spacing: .08em; text-transform: uppercase; }
.bws-snapshot__bar p { margin: 0; font-size: var(--bws-text-xs); font-style: italic; color: rgba(255, 255, 255, .85); }
.bws-snapshot__figures { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--bws-space-4) var(--bws-space-5); margin: 0; padding: var(--bws-space-5); }
/* Value over its label inside the two-column panel; one column on phones,
   where the value sits beside its label instead. */
.bws-snapshot__figure { display: flex; flex-direction: column; gap: var(--bws-space-1); min-width: 0; }
.bws-snapshot__figure dd {
  order: -1; margin: 0;
  font-family: var(--bws-font-display); font-size: clamp(1.6rem, 3vw, 2.2rem); font-weight: 700; line-height: 1; color: var(--bws-color-brand);
}
.bws-snapshot__figure dt { min-width: 0; font-size: var(--bws-text-sm); line-height: 1.35; color: var(--bws-color-ink-soft); }
@media (max-width: 479px) {
  .bws-snapshot__figures { grid-template-columns: minmax(0, 1fr); }
  .bws-snapshot__figure { flex-direction: row; align-items: center; gap: var(--bws-space-3); }
  .bws-snapshot__figure dd { flex: 0 0 auto; min-width: 2.4em; }
}
/* Milestones: year spans on one rule — across the page from 900px, a
   vertical rail below that. */
.bws-milestones h2, .bws-milestones__lede { text-align: center; }
.bws-section.bws-milestones .bws-milestones__list { position: relative; display: grid; gap: var(--bws-space-5); margin: var(--bws-space-6) 0 0; padding: 0; list-style: none; }
.bws-milestones__list::before { content: ""; position: absolute; background: var(--bws-color-brand-400); opacity: .35; }
.bws-milestones__item { position: relative; margin: 0; }
.bws-milestones__marker {
  position: relative; z-index: 1; display: block; width: 1.1rem; height: 1.1rem; border-radius: 50%;
  background: var(--bws-color-accent); box-shadow: 0 0 0 5px rgba(232, 168, 56, .22);
}
.bws .bws-milestones__date { margin: 0; font-family: var(--bws-font-display); font-size: var(--bws-text-xl); font-weight: 700; line-height: 1.2; color: var(--bws-color-brand); }
.bws .bws-milestones__text { margin: var(--bws-space-2) 0 0; font-size: var(--bws-text-sm); line-height: 1.45; color: var(--bws-color-ink-soft); }
.bws-milestones__cta { margin: var(--bws-space-6) 0 0; text-align: center; }
@media (max-width: 899px) {
  .bws-section.bws-milestones .bws-milestones__list { padding-left: 2.25rem; }
  .bws-milestones__list::before { left: .5rem; top: .5rem; bottom: .5rem; width: 2px; }
  .bws-milestones__marker { position: absolute; left: -2.25rem; top: .35rem; }
}
@media (min-width: 900px) {
  .bws-section.bws-milestones .bws-milestones__list { grid-template-columns: repeat(6, minmax(0, 1fr)); text-align: center; }
  .bws-milestones__list::before { left: 8%; right: 8%; top: .5rem; height: 2px; }
  .bws-milestones__marker { margin: 0 auto var(--bws-space-4); }
}
/* Impact: a portrait film with its lede, then headline results on teal and
   the ratings as filled bars. */
.bws-impact__layout { display: grid; gap: var(--bws-space-5); margin-top: var(--bws-space-6); }
@media (min-width: 1024px) {
  .bws-impact__layout { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
}
.bws-impact__intro, .bws-impact__ratings { background: var(--bws-color-surface); border-radius: 18px; padding: var(--bws-space-5); box-shadow: 0 10px 30px rgba(0, 60, 62, .08); }
.bws-impact__intro { display: grid; gap: var(--bws-space-5); align-content: center; }
/* Film beside the lede on tablets; stacked and centred on phones and in the
   narrower left column on desktop. */
@media (min-width: 600px) and (max-width: 1023px) {
  .bws-impact__intro { grid-template-columns: minmax(0, 11rem) minmax(0, 1fr); align-items: center; }
}
.bws-impact__film { display: block; width: 100%; aspect-ratio: 9 / 16; -o-object-fit: cover; object-fit: cover; border-radius: 12px; background: #000; }
@media (max-width: 599px), (min-width: 1024px) {
  .bws-impact__film { max-width: 13rem; margin-inline: auto; }
  .bws-impact__copy { text-align: center; }
}
.bws .bws-impact__lede { margin: 0 0 var(--bws-space-4); font-size: var(--bws-text-lg); line-height: 1.5; color: var(--bws-color-ink); }
.bws-impact__results { display: grid; gap: var(--bws-space-5); }
.bws-impact__highlights { display: grid; gap: var(--bws-space-5); margin: 0; padding: 0; list-style: none; }
@media (min-width: 600px) {
  .bws-impact__highlights { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.bws-impact__highlight { margin: 0; padding: var(--bws-space-5); border-radius: 18px; background: var(--bws-color-brand); color: #fff; text-align: center; }
.bws-impact__highlight img { display: block; width: 88px; height: 88px; margin: 0 auto var(--bws-space-3); padding: .6rem; border-radius: 50%; background: #fff; -o-object-fit: contain; object-fit: contain; }
.bws .bws-impact__highlight h3 { margin: 0 0 var(--bws-space-2); color: #fff; font-size: var(--bws-text-md); letter-spacing: .06em; text-transform: uppercase; }
.bws .bws-impact__highlight p { margin: 0; font-size: var(--bws-text-sm); line-height: 1.45; color: rgba(255, 255, 255, .88); }
.bws .bws-impact__ratings h3 { margin: 0 0 var(--bws-space-2); font-size: var(--bws-text-md); letter-spacing: .06em; text-transform: uppercase; color: var(--bws-color-brand); }
.bws .bws-impact__ratings > p { margin: 0 0 var(--bws-space-4); font-size: var(--bws-text-sm); color: var(--bws-color-ink-soft); }
.bws-impact__ratings ul { display: grid; gap: var(--bws-space-3); margin: 0; padding: 0; list-style: none; }
.bws-impact__rating { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: .4rem var(--bws-space-3); }
.bws-impact__rating-label { font-size: var(--bws-text-sm); font-weight: 600; color: var(--bws-color-ink); }
.bws-impact__rating-score { font-family: var(--bws-font-display); font-weight: 700; color: var(--bws-color-brand); }
.bws-impact__rating-out { font-size: .8em; font-weight: 400; color: var(--bws-color-ink-soft); }
.bws-impact__rating-bar { grid-column: 1 / -1; grid-row: 2; height: 8px; overflow: hidden; border-radius: 999px; background: var(--bws-color-brand-100); }
.bws-impact__rating-bar > span { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--bws-color-brand-600), var(--bws-color-accent)); }
/* ---------- Page-hero actions: a main link and an outlined second one ---------- */
.bws-hero__actions { display: flex; flex-wrap: wrap; gap: var(--bws-space-3); }
.bws-btn--outline-light { background: transparent; color: #fff; border-color: rgba(255, 255, 255, .9); }
.bws-btn--outline-light:hover { background: rgba(255, 255, 255, .14); color: #fff; }
/* ---------- Four-up galleries and a logo over call-to-action buttons ---------- */
.bws-gallery__grid--4 { grid-template-columns: repeat(2, 1fr); gap: var(--bws-space-3); }
@media (min-width: 900px) {
  .bws-gallery__grid--4 { grid-template-columns: repeat(4, 1fr); gap: var(--bws-space-5); }
}
.bws-gallery__grid--4 .bws-gallery__item img { aspect-ratio: 1 / 1; }
.bws-cta__logo { display: block; width: min(100%, 420px); height: auto; margin: 0 auto var(--bws-space-5); }
/* ---------- Section titles over wide content on inner pages ---------- */
/* Card grids, galleries, figure panels and results run wider than the 44rem
   reading column, so a left-aligned title started to the right of the
   content beneath it. Centre the title (and a gallery's intro) over it, as
   the milestones and people sections already do. */
.bws-page .bws-section.bws-cards > .bws-container > h2,
.bws-page .bws-section.bws-gallery > .bws-container > h2,
.bws-page .bws-section.bws-snapshot > .bws-container > h2,
.bws-page .bws-section.bws-impact > .bws-container > h2 { max-width: 48rem; text-align: center; }
.bws-page .bws-section.bws-gallery > .bws-container > .bws-gallery__lede { max-width: 48rem; margin-inline: auto; text-align: center; }
/* Photo cards: a title sized for a three-across card, and room above its link. */
.bws .bws-grid--photo-cards .bws-card h3 { font-size: var(--bws-text-xl); line-height: 1.25; margin-bottom: var(--bws-space-2); }
.bws-grid--photo-cards .bws-card--flush-top h3 + a { margin-top: var(--bws-space-1); }
/* ---------- Get In Touch: contact cards, message panel and map ---------- */
/* Site colours only: brand teal, its lighter teal and mint, and the gold
   accent. Anchor targets (#contact-form, #inquire, ...) clear the sticky
   header instead of landing underneath it. */
.bws [id] { scroll-margin-top: calc(var(--bws-header-height) + var(--bws-space-4)); }
.bws .bws-contact__cards {
  display: grid; gap: var(--bws-space-4); margin: 0 0 var(--bws-space-8); padding: 0; list-style: none;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 14.5rem), 1fr));
}
/* Four across on wide screens; the email card takes the width its longest
   address needs, so neither address breaks mid-word. */
@media (min-width: 1200px) {
  .bws .bws-contact__cards { grid-template-columns: 1fr 1fr auto 1fr; }
  .bws-contact__emails a { white-space: nowrap; }
}
.bws-contact__card {
  margin: 0; padding: var(--bws-space-5); border-radius: 18px;
  background: var(--bws-color-surface); box-shadow: 0 10px 30px rgba(0, 60, 62, .08);
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--bws-space-1);
}
.bws-contact__icon {
  display: inline-grid; place-items: center; flex: 0 0 auto; width: 2.75rem; height: 2.75rem; margin-bottom: var(--bws-space-3);
  border-radius: 50%; background: var(--bws-color-brand); color: #fff;
}
.bws-contact__icon--accent { width: 3.25rem; height: 3.25rem; background: var(--bws-color-accent); color: var(--bws-color-brand); }
.bws .bws-contact__card h3 { margin: 0 0 var(--bws-space-1); font-size: var(--bws-text-sm); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--bws-color-brand); }
.bws .bws-contact__card p { margin: 0; font-size: var(--bws-text-sm); line-height: 1.5; color: var(--bws-color-ink); }
.bws-contact__card a { font-size: var(--bws-text-sm); font-weight: 600; color: var(--bws-color-brand-600); overflow-wrap: anywhere; }
.bws-contact__card a:hover { text-decoration: underline; }
.bws-contact__emails { display: grid; gap: var(--bws-space-2); margin: 0; }
.bws-contact__emails dt { font-size: var(--bws-text-xs); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--bws-color-ink-soft); }
.bws-contact__emails dd { margin: 0; }
/* The message panel: a textured teal intro beside a white form card. */
.bws-contact__panel {
  display: grid; overflow: hidden; border-radius: 24px;
  background: var(--bws-color-surface); box-shadow: 0 20px 50px rgba(0, 60, 62, .14);
}
/* A grid item defaults to min-width:auto, so this single column could not go
   narrower than the widest thing inside it — the form's submit button and its
   192px min-width. Below about 384px that floored the column at 348px while
   the panel itself kept shrinking with the page, and overflow:hidden quietly
   ate the difference: the teal panel's lines came out cut mid-word on a phone.
   The green side was never at fault; it was just the other item in a column
   the form had pinned open. The ≥960px rule below already guards this with
   minmax(0, …) — the stacked column needs the same. */
.bws-contact__panel > * { min-width: 0; }
@media (min-width: 960px) {
  .bws-contact__panel { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
}
.bws-contact__intro {
  position: relative; isolation: isolate; padding: var(--bws-space-8) var(--bws-space-6); color: #fff;
  background:
    radial-gradient(110% 80% at 0% 0%, rgba(232, 168, 56, .20), transparent 55%),
    linear-gradient(180deg, var(--bws-color-brand-600) 0%, var(--bws-color-brand) 100%);
}
.bws-contact__intro::before {
  content: ""; position: absolute; inset: 0; z-index: -1; opacity: .35; mix-blend-mode: soft-light; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .55 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
.bws .bws-contact__eyebrow { margin: 0 0 var(--bws-space-2); font-size: var(--bws-text-xs); font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--bws-color-accent); }
.bws .bws-contact__intro h2 { margin: 0 0 var(--bws-space-3); font-size: clamp(1.9rem, 3vw, 2.5rem); line-height: 1.15; letter-spacing: 0; text-transform: none; color: #fff; }
.bws .bws-contact__lede { margin: 0; line-height: 1.6; color: rgba(255, 255, 255, .88); }
.bws .bws-contact__promises { display: grid; gap: var(--bws-space-3); margin: var(--bws-space-5) 0 0; padding: 0; list-style: none; }
.bws-contact__promises li { position: relative; padding-left: 2.1rem; line-height: 1.45; font-weight: 600; }
.bws-contact__promises li::before {
  content: ""; position: absolute; left: 0; top: .05rem; width: 1.4rem; height: 1.4rem; border-radius: 50%;
  background: var(--bws-color-accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23005051' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / .85rem no-repeat;
}
.bws-contact__shortcuts {
  display: grid; justify-items: start; gap: var(--bws-space-2);
  margin-top: var(--bws-space-6); padding-top: var(--bws-space-5); border-top: 1px solid rgba(255, 255, 255, .22);
}
.bws .bws-contact__shortcuts h3 { margin: 0 0 var(--bws-space-1); font-size: var(--bws-text-xs); letter-spacing: .1em; text-transform: uppercase; color: rgba(255, 255, 255, .75); }
.bws-contact__shortcuts a { display: block; font-weight: 600; line-height: 1.4; color: #fff; }
/* The arrow follows the last word, even when the link wraps. */
.bws-contact__shortcuts a::after { content: "\A0\2192"; color: var(--bws-color-accent); }
.bws-contact__shortcuts a:hover { text-decoration: underline; }
.bws-contact__shortcuts a:hover::after { color: #fff; }
.bws-contact__social { display: flex; gap: var(--bws-space-3); margin-top: var(--bws-space-6); }
.bws-contact__social a {
  display: grid; place-items: center; width: 2.5rem; height: 2.5rem; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, .45); color: #fff; transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.bws-contact__social a:hover { background: var(--bws-color-accent); border-color: var(--bws-color-accent); color: var(--bws-color-brand); }
.bws-contact__form-card { padding: var(--bws-space-8) var(--bws-space-6); }
.bws-contact__pair { display: grid; gap: 0 var(--bws-space-4); }
@media (min-width: 600px) {
  .bws-contact__pair { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.bws-contact__submit { min-width: 12rem; justify-content: center; }
@media (max-width: 599px) {
  .bws-contact__intro, .bws-contact__form-card { padding: var(--bws-space-6) var(--bws-space-5); }
  /* Full width already, so the 12rem floor buys nothing here and only serves
     to stop the whole panel shrinking on a narrow phone. */
  .bws-contact__submit { width: 100%; min-width: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .bws-contact__shortcuts a::after, .bws-contact__social a { transition: none; }
}
/* Map: a mint placeholder drawn as a street grid until "Show the map". */
.bws-contact__map {
  position: relative; overflow: hidden; margin-top: var(--bws-space-8); border-radius: 24px;
  border: 1px solid rgba(0, 80, 81, .12);
  background:
    repeating-linear-gradient(0deg, rgba(0, 80, 81, .07) 0 1px, transparent 1px 44px),
    repeating-linear-gradient(90deg, rgba(0, 80, 81, .07) 0 1px, transparent 1px 44px),
    linear-gradient(135deg, var(--bws-color-brand-100), var(--bws-color-surface));
}
.bws-contact__map-placeholder { display: grid; justify-items: center; gap: var(--bws-space-2); padding: var(--bws-space-8) var(--bws-space-5); text-align: center; }
.bws .bws-contact__map-placeholder h3 { margin: 0; font-size: var(--bws-text-xl); color: var(--bws-color-brand); }
.bws .bws-contact__map-placeholder p { margin: 0 0 var(--bws-space-3); max-width: 32rem; color: var(--bws-color-ink-soft); }
.bws-contact__map .bws-actions { justify-content: center; }
.bws-contact__map iframe { display: block; width: 100%; height: clamp(20rem, 45vw, 28rem); border: 0; }
/* ---------- Duties table (Our Community's Home-School Partnership) ---------- */
/* The school's duty beside the parents' matching duty, one pair per row;
   stacked as labelled pairs on phones. */
.bws-duties { margin: var(--bws-space-5) 0 var(--bws-space-6); overflow: hidden; border-radius: 16px; border: 1px solid rgba(0, 80, 81, .14); background: var(--bws-color-surface); }
.bws-duties table { width: 100%; border-collapse: collapse; font-size: var(--bws-text-sm); line-height: 1.5; }
.bws-duties th { padding: var(--bws-space-3) var(--bws-space-4); text-align: left; font-size: var(--bws-text-xs); letter-spacing: .1em; text-transform: uppercase; color: #fff; background: var(--bws-color-brand); }
.bws-duties th + th { background: var(--bws-color-brand-600); }
.bws-duties td { width: 50%; padding: var(--bws-space-3) var(--bws-space-4); vertical-align: top; color: var(--bws-color-ink); border-top: 1px solid rgba(0, 80, 81, .1); }
.bws-duties td + td { background: var(--bws-color-brand-100); }
@media (max-width: 599px) {
  .bws-duties thead { display: none; }
  .bws-duties tr { display: block; border-top: 1px solid rgba(0, 80, 81, .12); }
  .bws-duties tr:first-child { border-top: 0; }
  .bws-duties td { display: block; width: auto; border-top: 0; }
  .bws-duties td::before { display: block; margin-bottom: var(--bws-space-1); font-size: var(--bws-text-xs); font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--bws-color-brand); content: "The school"; }
  .bws-duties td + td::before { content: "The parents"; }
}
.bws .bws-faq__lede { margin: 0 0 var(--bws-space-5); line-height: 1.6; color: var(--bws-color-ink-soft); }
/* ---------- Get In Touch: "How can we help?" pathways ---------- */
.bws-contact__paths { margin: 0 0 var(--bws-space-8); }
.bws .bws-contact__paths-title { margin: 0 auto var(--bws-space-5); text-align: center; font-size: var(--bws-text-xl); font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--bws-color-brand); }
.bws-contact__path-grid { display: grid; gap: var(--bws-space-5); }
/* One card per row. From 900px each card puts its eyebrow, title and button
   in a left column and the text beside them. */
@media (min-width: 900px) {
  .bws .bws-contact__path {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
    grid-template-areas: "eyebrow body" "title body" "cta body";
    grid-template-rows: auto auto 1fr; -webkit-column-gap: var(--bws-space-8); column-gap: var(--bws-space-8);
    padding: var(--bws-space-6) var(--bws-space-8) var(--bws-space-6) var(--bws-space-6);
  }
  .bws .bws-contact__path-eyebrow { grid-area: eyebrow; }
  .bws .bws-contact__path h3 { grid-area: title; }
  .bws-contact__path .bws-contact__path-body { grid-area: body; margin-bottom: 0; }
  .bws-contact__path .bws-contact__path-cta { grid-area: cta; align-self: start; justify-self: start; margin-top: var(--bws-space-2); }
}
.bws-contact__path {
  display: flex; flex-direction: column; padding: var(--bws-space-6) var(--bws-space-5);
  border-radius: 20px; background: var(--bws-color-surface); box-shadow: 0 10px 30px rgba(0, 60, 62, .08);
}
.bws .bws-contact__path-eyebrow { margin: 0 0 var(--bws-space-1); font-size: var(--bws-text-xs); font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--bws-color-brand-600); }
.bws .bws-contact__path h3 { margin: 0 0 var(--bws-space-3); font-size: var(--bws-text-2xl); line-height: 1.2; color: var(--bws-color-brand); }
.bws .bws-contact__path-body p { margin: 0 0 var(--bws-space-3); font-size: var(--bws-text-sm); line-height: 1.6; color: var(--bws-color-ink); }
.bws-contact__path-body a { color: var(--bws-color-brand-600); font-weight: 600; }
.bws-contact__path-cta { align-self: flex-start; margin-top: auto; }
.bws-contact__path-body { margin-bottom: var(--bws-space-4); }
/* ---------- Photo carousel in a split (item.images: Why Brightwoods spaces) ---------- */
/* One photo at a time filling the split's image column. A counter badge,
   arrows on either side and dots along the bottom make it plain there are
   more photos; swipe and the arrow keys work too. */
.bws-split__image--carousel { position: relative; overflow: hidden; padding: 0; background: var(--bws-color-brand-100); }
.bws-photo-carousel { position: absolute; inset: 0; }
.bws-photo-carousel:focus-visible { outline: 3px solid var(--bws-color-accent); outline-offset: -3px; }
.bws-photo-carousel__viewport { position: absolute; inset: 0; touch-action: pan-y; }
.bws-photo-carousel__slide { position: absolute; inset: 0; margin: 0; }
.bws-photo-carousel__slide img { display: block; width: 100%; height: 100%; -o-object-fit: cover; object-fit: cover; }
.bws-photo-carousel__slide:not([hidden]) { -webkit-animation: bws-photo-fade .45s ease; animation: bws-photo-fade .45s ease; }
@-webkit-keyframes bws-photo-fade { from { opacity: .2; } to { opacity: 1; } }
@keyframes bws-photo-fade { from { opacity: .2; } to { opacity: 1; } }
.bws-photo-carousel::after {
  content: ""; position: absolute; inset: auto 0 0; height: 34%; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, transparent, rgba(0, 40, 41, .55));
}
.bws-photo-carousel__badge {
  position: absolute; top: var(--bws-space-4); left: var(--bws-space-4); z-index: 2;
  display: inline-flex; align-items: center; gap: .4rem; padding: .35rem .75rem; border-radius: 999px;
  background: rgba(0, 80, 81, .88); color: #fff; font-size: var(--bws-text-xs); font-weight: 700; letter-spacing: .06em;
}
.bws-photo-carousel__badge svg { color: var(--bws-color-accent); }
.bws-photo-carousel__nav {
  position: absolute; top: 50%; z-index: 2; display: grid; place-items: center;
  width: 2.75rem; height: 2.75rem; margin-top: -1.375rem; padding: 0; border: 0; border-radius: 50%;
  background: rgba(255, 255, 255, .92); color: var(--bws-color-brand); cursor: pointer;
  box-shadow: 0 6px 18px rgba(0, 40, 41, .25); transition: background-color .15s ease, color .15s ease;
}
.bws-photo-carousel__nav:hover { background: var(--bws-color-accent); color: var(--bws-color-brand); }
.bws-photo-carousel__nav:focus-visible { outline: 3px solid var(--bws-color-accent); outline-offset: 2px; }
.bws-photo-carousel__nav--prev { left: var(--bws-space-4); }
.bws-photo-carousel__nav--next { right: var(--bws-space-4); }
.bws-photo-carousel__dots {
  position: absolute; left: 50%; bottom: var(--bws-space-4); z-index: 2; -webkit-transform: translateX(-50%); transform: translateX(-50%);
  display: flex; align-items: center; gap: 0;
}
/* The dot a finger hits is 24px square (WCAG 2.2 target size); the dot it sees
   is the small pill drawn inside it. Sizing the button itself to the pill left
   a 9px tap target that missed as often as it hit. */
.bws-photo-carousel__dot {
  width: 24px; height: 24px; padding: 0; border: 0; background: none; cursor: pointer;
  display: grid; place-items: center;
}
.bws-photo-carousel__dot::before {
  content: ""; display: block; width: .55rem; height: .55rem; border-radius: 999px;
  background: rgba(255, 255, 255, .65); transition: width .2s ease, background-color .2s ease;
}
.bws-photo-carousel__dot.is-active::before { width: 1.6rem; background: var(--bws-color-accent); }
.bws-photo-carousel__dot:focus-visible { outline: 2px solid #fff; outline-offset: -2px; border-radius: 4px; }
@media (max-width: 599px) {
  .bws-photo-carousel__nav { width: 2.25rem; height: 2.25rem; margin-top: -1.125rem; }
}
@media (prefers-reduced-motion: reduce) {
  .bws-photo-carousel__slide:not([hidden]) { -webkit-animation: none; animation: none; }
  .bws-photo-carousel__dot, .bws-photo-carousel__nav { transition: none; }
}
/* Card grids can carry a one-line lede under their title. */
.bws .bws-cards__lede { max-width: 44rem; margin: calc(-1 * var(--bws-space-3)) auto var(--bws-space-6); text-align: center; line-height: 1.6; color: var(--bws-color-ink-soft); }
/* ---------- Inner-page card grids and long quotes ---------- */
/* Card titles sized for a three-across card, with the link held to the
   bottom so a row of cards lines up. */
.bws-page .bws-section.bws-cards .bws-card { display: flex; flex-direction: column; }
/* .bws-card--centered's text-align only reaches text inside auto-width
   boxes — it can't center the icon disc, a fixed 90px flex item, once this
   rule turns the card into a column flex container. align-items is the
   property that actually governs cross-axis (horizontal) position here. */
.bws-page .bws-section.bws-cards .bws-card--centered { align-items: center; }
.bws .bws-page .bws-section.bws-cards .bws-card h3 { font-size: var(--bws-text-xl); line-height: 1.25; margin-bottom: var(--bws-space-2); }
.bws-page .bws-section.bws-cards .bws-card p { line-height: 1.6; }
.bws-page .bws-section.bws-cards .bws-card > a:last-child { margin-top: auto; padding-top: var(--bws-space-3); font-weight: 600; color: var(--bws-color-brand-600); }
.bws-page .bws-section.bws-cards .bws-card > a:last-child::after { content: "\A0\2192"; color: var(--bws-color-accent); }
.bws .bws-quote--long .bws-quote__text { font-size: clamp(1.15rem, 1.8vw, 1.45rem); line-height: 1.6; }
/* ---------- Centred section opener (richtext data.align "center") ---------- */
/* A one- or two-line intro above full-width content: centred, so it doesn't
   start a third of the way in while the content below runs edge to edge. */
.bws-page .bws-section.bws-richtext--centered > .bws-container > h2,
.bws-page .bws-section.bws-richtext--centered > .bws-container > .bws-eyebrow { text-align: center; }
.bws-page .bws-section.bws-richtext--centered > .bws-container > .bws-richtext { max-width: 48rem; margin-inline: auto; text-align: center; }
/* ---------- Phones: the rail keeps its column, but a slimmer one ---------- */
/* All four icons stay, as a vertical dock on the right. It is sized here
   rather than through --bws-rail-icon/--bws-rail-pad because those two derive
   --bws-header-height: shrinking the rail through them would shrink the header
   bar and move the logo. Icons are 32px inside a 44px column, with tighter
   padding and gaps, which takes the dock from 271px tall to about 175px.
   No gutter is reserved for it — reserving one cost the page 52px of width and
   read worse than the overlap it prevented — so the top-right corner of the
   page still passes beneath it, over a smaller area than before. */
@media (max-width: 767px) {
  .bws-utility-rail {
    /* Top padding rather than a gap: the first icon's centre has to land on
       the header's own centre line (36px down a 72px bar) so the burger reads
       as part of the header instead of floating above it — plus the 3px the
       logo's low-sitting lettering needs to look level. 23 + half a 32px
       icon = 39. */
    padding: 23px 0 var(--bws-space-2);
    gap: var(--bws-space-2);
  }
  /* Drawer open, the dock is a lone × — and that 23px top offset, which exists
     only to line the burger up with the logo, then leaves 23px of teal above
     the button against 8px below it: a lopsided stub with a lip under the ×.
     The logo is hidden while the drawer is open, so the offset is aligning to
     something that is no longer on screen. Given the header's own height with
     the button centred in it, the tab reads as a deliberate corner block. */
  body:has(.bws-nav-toggle:checked) .bws-utility-rail {
    height: var(--bws-header-height);
    padding-block: 0;
    justify-content: center;
  }
  .bws-utility-rail__icon {
    width: 32px;
    height: 32px;
  }
  .bws-utility-rail__icon svg {
    width: 16px;
    height: 16px;
  }
  .bws-utility-rail__icon img {
    width: 18px;
    height: 18px;
  }
  .bws-utility-rail__rule {
    width: 20px;
    height: 1px;
  }
  /* The bars are 22px at ±7px/5px on the full-size icon; scaled to the 32px
     box they sit at 16px and ±5px. Both offsets stated, since the base rule
     is asymmetric (-7px above, 5px below) and inheriting half of it would
     leave the middle bar off-centre. */
  .bws-utility-rail__burger span,
  .bws-utility-rail__burger span::before,
  .bws-utility-rail__burger span::after {
    width: 16px;
  }
  .bws-utility-rail__burger span::before { top: -5px; }
  .bws-utility-rail__burger span::after { top: 4px; }
  /* ...and the × those two bars fold into has to be restated here, for the
     same reason the widths above are. The sitewide rule turns them with
     translate(5px, 5px), which carries each bar 7.07px towards the icon's
     centre — exactly right for the desktop bars, which sit symmetrically at
     ±7px. The phone bars sit at -5px and +6px instead, so that same carry
     lands one stroke 2px below the centre and the other 1px above: measured
     at 14.81 and 18.06 in a 32px box, 3.25px apart, which is what reads as a
     skewed ×. (Desktop measures as a single run at 23.94 against a centre of
     24 — the two strokes there coincide.)
     Written as translate-then-rotate so each bar moves to the centre by its
     own offset and then turns, instead of both sharing one diagonal carry
     that only suits one of them. */
  body:has(.bws-nav-toggle:checked) .bws-utility-rail__burger span::before {
    -webkit-transform: translateY(5px) rotate(45deg);
            transform: translateY(5px) rotate(45deg);
  }
  body:has(.bws-nav-toggle:checked) .bws-utility-rail__burger span::after {
    -webkit-transform: translateY(-6px) rotate(-45deg);
            transform: translateY(-6px) rotate(-45deg);
  }
}
/* ---------- Site search results ---------- */
/* Our own search over our own pages. The rail and drawer boxes post here
   instead of handing the visitor to Google. */
/* The banner: a plain <div>, not a .bws-section, so it sits outside both the
   .bws-page even/odd section-tint rotation and the id-based selector group
   above whose gradient+texture it borrows (see .bws-search__banner there).
   Needs its own position:relative — .bws-section normally supplies that for
   the ::before texture layer, but this element isn't one. */
.bws-search__banner {
  position: relative;
  padding-top: calc(var(--bws-header-height) + var(--bws-space-6));
  padding-bottom: var(--bws-space-8);
}
.bws-search__banner h1 { color: #fff; text-align: center; }
.bws-search__form {
  display: flex; gap: var(--bws-space-3); flex-wrap: wrap;
  margin: var(--bws-space-5) 0 0;
}
.bws-search__input {
  flex: 1 1 16rem; min-width: 0;
  padding: .75rem 1rem; font: inherit; color: var(--bws-color-ink);
  background: #fff; border: 1px solid var(--bws-color-line); border-radius: var(--bws-radius-sm);
}
.bws-search__input:focus-visible { outline: 2px solid var(--bws-color-brand-600); outline-offset: 1px; }
/* The submit button carries both an icon and a label; the label is what
   shows normally, and on narrow phones it's visually hidden (screen readers
   still get it) in favour of the icon alone, so the button doesn't eat into
   the input's width on small screens. */
.bws-search__submit-icon { display: none; }
@media (max-width: 480px) {
  .bws-search__submit {
    padding-left: var(--bws-space-3); padding-right: var(--bws-space-3);
  }
  .bws-search__submit-icon { display: inline-block; }
  .bws-search__submit-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;
  }
}
.bws-search__note, .bws-search__count { color: var(--bws-color-ink-soft); line-height: 1.6; }
.bws-search__count { margin-bottom: var(--bws-space-5); }
.bws-search__results { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--bws-space-5); }
.bws .bws-search__results { padding-left: 0; }
/* Each result is one card-shaped link (biggest tap target, unmistakably a
   button) rather than a title-link with separate plain-text lines below it —
   same surface/border/radius as .bws-card, and the same hover-lift language
   already used by the News and Learning Spaces cards. */
.bws-search__card {
  display: block;
  padding: var(--bws-space-5);
  background: var(--bws-color-surface);
  border: 1px solid var(--bws-color-line);
  border-radius: var(--bws-radius-md);
  box-shadow: var(--bws-shadow-sm);
  text-decoration: none;
  position: relative;
  transition: box-shadow .35s ease, border-color .35s ease, -webkit-transform .35s ease;
  transition: box-shadow .35s ease, transform .35s ease, border-color .35s ease;
  transition: box-shadow .35s ease, transform .35s ease, border-color .35s ease, -webkit-transform .35s ease;
}
.bws-search__card:hover,
.bws-search__card:focus-visible {
  -webkit-transform: translateY(-6px);
          transform: translateY(-6px);
  box-shadow: var(--bws-shadow-md);
  border-color: var(--bws-color-brand-400);
}
@media (prefers-reduced-motion: reduce) {
  .bws-search__card { transition: none; }
  .bws-search__card:hover, .bws-search__card:focus-visible { -webkit-transform: none; transform: none; }
}
.bws-search__result-title {
  display: block;
  font-size: var(--bws-text-xl); font-weight: 600; line-height: 1.3;
  color: var(--bws-color-brand-600);
  padding-right: var(--bws-space-8);
}
.bws-search__snippet { margin: var(--bws-space-2) 0 var(--bws-space-1); line-height: 1.6; color: var(--bws-color-ink); }
.bws-search__url { margin: 0; font-size: var(--bws-text-sm); color: var(--bws-color-ink-soft); word-break: break-word; }
.bws-search__arrow {
  position: absolute;
  top: var(--bws-space-5);
  right: var(--bws-space-5);
  color: var(--bws-color-brand-400);
  font-size: var(--bws-text-lg);
  transition: -webkit-transform .35s ease;
  transition: transform .35s ease;
  transition: transform .35s ease, -webkit-transform .35s ease;
}
.bws-search__card:hover .bws-search__arrow,
.bws-search__card:focus-visible .bws-search__arrow { -webkit-transform: translateX(4px); transform: translateX(4px); }
@media (prefers-reduced-motion: reduce) {
  .bws-search__arrow { transition: none; }
  .bws-search__card:hover .bws-search__arrow { -webkit-transform: none; transform: none; }
}
/* The pin-to-bottom now lives on .bws-news-card__meta (the date+link group);
   this just keeps the link's own spacing under the date. */
.bws-news-card__link {
  padding-top: var(--bws-space-2);
  font-weight: 600; color: var(--bws-color-brand-600); text-decoration: none;
}
.bws-news-card__link::after { content: "\A0\2192"; color: var(--bws-color-accent); }
.bws-news-card__link:hover { text-decoration: underline; }
.bws-news-card .bws-news-card__body { display: flex; flex-direction: column; }
/* The sideways track takes keyboard focus now that it is reachable by tab. */
.bws-news-grid:focus-visible { outline: 2px solid var(--bws-color-brand-600); outline-offset: 4px; border-radius: var(--bws-radius-sm); }
/* ---------- Post body (PostBlockRenderer output, /news/{slug}) ---------- */
/* PostBlockRenderer emits one .bws-post-block per block, optionally banded
   with .bws-post-band--{bg} (the same PALETTE keys the newsletter builder
   already offers authors). */
.bws-post-block { padding-block: var(--bws-space-5); }
.bws-post-band { padding-block: var(--bws-space-6); }
.bws-post-band--white { background: var(--bws-color-surface); }
.bws-post-band--cream { background: var(--bws-color-bg); }
.bws-post-band--brand { background: var(--bws-color-brand); color: #fff; }
.bws-post-band--brand_light { background: var(--bws-color-brand-100); }
.bws-post-band--gold { background: var(--bws-color-accent); color: var(--bws-color-ink); }
.bws-post-band--gold_light { background: var(--bws-color-accent-100); }
.bws-post-band--ink { background: var(--bws-color-ink); color: #fff; }
.bws-post__meta { color: var(--bws-color-ink-soft); font-size: var(--bws-text-sm); margin-bottom: var(--bws-space-5); }
.bws-post-figure--hero { margin: 0 0 var(--bws-space-5); }
.bws-post-figure--hero img { width: 100%; height: auto; display: block; border-radius: var(--bws-radius-md); }
.bws-post-figure--hero figcaption { margin-top: var(--bws-space-2); font-size: var(--bws-text-sm); color: var(--bws-color-ink-soft); }
/* image block: width is one of 100/75/50 (BlockValidator::IMAGE_WIDTHS). */
.bws-post-figure--w100, .bws-post-figure--w75, .bws-post-figure--w50 { margin: var(--bws-space-4) 0; }
.bws-post-figure--w100 img, .bws-post-figure--w75 img, .bws-post-figure--w50 img { width: 100%; height: auto; display: block; border-radius: var(--bws-radius-md); }
.bws-post-figure--w75 { max-width: 75%; }
.bws-post-figure--w50 { max-width: 50%; }
.bws-post-figure--left { margin-inline: 0; }
.bws-post-figure--center { margin-inline: auto; }
.bws-post-figure--right { margin-inline: 0 0 0 auto; }
.bws-post-split--right { direction: rtl; }
.bws-post-split--right > * { direction: ltr; }
.bws-post-actions--left { text-align: left; }
.bws-post-actions--center { text-align: center; }
.bws-post-actions--right { text-align: right; }
.bws-post-actions--left, .bws-post-actions--center, .bws-post-actions--right {
  display: flex; flex-wrap: wrap; gap: var(--bws-space-3); margin: var(--bws-space-5) 0;
}
.bws-post-actions--center { justify-content: center; }
.bws-post-actions--right { justify-content: flex-end; }
/* The renderer maps the newsletter button palette onto these three: brand →
   primary, gold → secondary, ink → outline (no .bws-btn--outline existed
   before posts needed a dark-on-light option distinct from --ghost's
   brand-coloured border). */
.bws-btn--outline {
  background: transparent;
  color: var(--bws-color-ink);
  border-color: var(--bws-color-ink);
}
.bws-btn--outline:hover { background: var(--bws-color-bg); }
.bws-post-divider { border: none; border-top: 1px solid var(--bws-color-line); margin: var(--bws-space-6) 0; }
.bws-post-spacer--8 { height: 8px; }
.bws-post-spacer--16 { height: 16px; }
.bws-post-spacer--24 { height: 24px; }
.bws-post-spacer--40 { height: 40px; }
.bws-news-seeall { text-align: center; margin-top: var(--bws-space-6); }
/* ---------- /news index and pager ---------- */
.bws-pagination {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--bws-space-4); margin-top: var(--bws-space-8);
}
.bws-pagination__link { color: var(--bws-color-brand-600); font-weight: 600; text-decoration: none; }
.bws-pagination__link:hover { text-decoration: underline; }
.bws-pagination__link--disabled { color: var(--bws-color-ink-soft); opacity: .5; pointer-events: none; }
.bws-pagination__status { color: var(--bws-color-ink-soft); font-size: var(--bws-text-sm); }
