/* The awards flyover — src/awards.md.
   Loaded on that page only, after explore.css.

   Twenty awards laid out across an aerial photograph of the school, five to a
   row, four rows. Scrolling flies the camera along them: left to right, down,
   right to left, down again. Built from
   Explore-Pages/Awards/Awards-FlyOver/awards-aerial-journey.html — the camera
   and its arithmetic are that file's, the type, colour and the rules below
   are the site's.

   Two states. Without the class the script adds, this is an ordinary
   responsive grid of twenty cards on the navy — which is what a reader gets
   with no JavaScript, under prefers-reduced-motion, on a window too short to
   fly across, or if the aerial photograph fails to load. Nothing is only
   reachable by flying. */

.awfly {
  position: relative;
  background: var(--bms-blue-900);
  color: var(--paper);
  --focus-ring: var(--paper);
}
.awfly-stage {
  position: relative;
  padding: var(--ex-space) var(--sp-6);
  overflow: clip;
  isolation: isolate;
}
.awfly-image,
.awfly-shade { display: none; }

/* Sits over the flight, naming where the camera is. Also the notice's home. */
.awfly-head {
  max-width: 80rem;
  margin: 0 auto var(--sp-8);
}
.awfly-skip {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--bms-sky);
  font-size: var(--step--1);
  font-weight: 600;
}
.awfly-note {
  max-width: 62ch;
  margin: var(--sp-4) 0 0;
  color: var(--bms-sky);
  line-height: 1.65;
}

.awfly-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
  gap: var(--sp-6);
  max-width: 82.5rem;
  padding: 0;
  margin: 0 auto;
  list-style: none;
}
.awcard { min-width: 0; }
.awcard-float { height: 100%; }
.awcard-link {
  /* The logo's slot, and the run of lines the longest award name needs. Named
     here because .awcard-top is sized from the two of them together. */
  --awcard-logo: 6.5rem;
  --awcard-names: 5.2em;
  display: flex;
  height: 100%;
  flex-direction: column;
  align-items: center;
  padding: var(--sp-4) var(--sp-4) var(--sp-3);
  border: 1px solid var(--hairline);
  background: var(--paper);
  color: var(--ink);
  text-align: center;
  text-decoration: none;
  transform: scale(1);
  transition: transform 280ms var(--ease), border-color 280ms var(--ease);
}
/* The logo and the name, centred together in the space between the top of the
   card and the date. The block is as tall as the logo's slot plus the longest
   name, which is the height the two of them used to take between them — so
   every card is the size it always was and a row of them still lines its dates
   up. What changes is where the pair sits inside it: a one-word award used to
   leave three empty lines under its name, because the name box held the run of
   lines whether or not it needed them. */
.awcard-top {
  display: flex;
  flex: 1 0 auto;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  /* The gap before the date is inside this box, not a margin under it. As a
     margin it sat outside the centring, so the pair came out a dozen pixels
     high in the space it was meant to be halfway down. The card's total height
     is the same either way. */
  min-height: calc(var(--awcard-logo) + var(--sp-3) + var(--awcard-names) + var(--sp-3));
}
.awcard-media {
  display: grid;
  place-items: center;
  width: 100%;
  height: var(--awcard-logo);
  margin-bottom: var(--sp-3);
}
.awcard-media img {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: var(--awcard-logo);
  object-fit: contain;
}
.awcard-name {
  margin: 0;
  font-size: var(--step-0);
  font-weight: 600;
  line-height: 1.3;
  text-wrap: balance;
}
.awcard-since {
  margin-top: auto;
  color: var(--ink-muted);
  font-size: var(--step--1);
  line-height: 1.5;
}
.awcard-more {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-2);
  color: var(--bms-blue-700);
  font-size: var(--step--1);
  font-weight: 600;
  line-height: 1.5;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.awcard-more svg { width: 0.8125rem; height: 0.8125rem; flex: none; }
/* The ring is on --paper here rather than the navy the section sets, because a
   card is a white surface: --focus-ring inherited from .awfly would be white
   on white. */
.awcard-link:focus-visible {
  outline: 3px solid var(--bms-blue-700);
  outline-offset: 5px;
  transform: scale(1.055);
}
@media (hover: hover) {
  .awcard-link:hover {
    border-color: var(--bms-blue-700);
    transform: scale(1.055);
  }
}

/* ---- The flight ------------------------------------------------------- */

/* Added by awards-flyover.js once it has measured a path. Everything above is
   what stands when it is not. */
.awfly.is-flying .awfly-stage {
  position: sticky;
  top: 0;
  /* The LARGE viewport — the screen with the browser's own bars retracted —
     not the small one. Sized to 100svh, the stage stopped short once a phone
     browser shrank its address bar on scroll, and the section's navy showed
     in the gap beneath the photograph (Sean, iPhone Safari, 2026-09-19).
     Sized to 100lvh the photograph always reaches the bottom of the screen;
     while the bar is showing, the last sliver of it sits behind the bar. lvh
     does not change as the bars move, so nothing re-measures mid-scroll.
     100vh first for any browser without lvh, where it means the same. */
  height: 100vh;
  height: 100lvh;
  padding: 0;
  /* The page keeps vertical scrolling — which is what drives the camera — and
     nothing here asks for the horizontal. */
  touch-action: pan-y;
}
.awfly.is-flying .awfly-world {
  position: absolute;
  inset: 0 auto auto 0;
  transform-origin: top left;
  will-change: transform;
}
.awfly.is-flying .awfly-image {
  position: absolute;
  z-index: -1;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  user-select: none;
  pointer-events: none;
  -webkit-user-drag: none;
}
/* Top and bottom only: the cards sit in the middle band, and a vignette across
   the whole frame would grey the photograph rather than seat the type on it. */
.awfly.is-flying .awfly-shade {
  position: absolute;
  z-index: 2;
  inset: 0;
  display: block;
  pointer-events: none;
  background: linear-gradient(180deg, var(--fly-scrim) 0%, transparent 22%, transparent 78%, var(--fly-scrim-foot) 100%);
}
.awfly.is-flying .awfly-head {
  position: absolute;
  z-index: 3;
  top: var(--sp-6);
  left: clamp(var(--sp-6), 3vw, var(--sp-12));
  right: clamp(var(--sp-6), 3vw, var(--sp-12));
  max-width: none;
  margin: 0;
  text-shadow: 0 2px 12px var(--bms-blue-900);
}
.awfly.is-flying .awfly-list {
  display: block;
  max-width: none;
  margin: 0;
}
.awfly.is-flying .awcard {
  position: absolute;
  width: clamp(13rem, 17vw, 15rem);
  transform: translate(-50%, -50%);
}
.awfly.is-flying .awcard:is(:hover, :focus-within) { z-index: 1; }
.awfly.is-flying .awcard-link {
  border-color: transparent;
  box-shadow: var(--fly-shadow);
}

/* The cards drift, so the aerial reads as something being flown over rather
   than a picture with stickers on it. Each starts at a different point in the
   cycle — the script sets the delay — and only while on screen. */
.awfly.is-flying .awcard-float {
  animation: awcard-float var(--fly-float-time, 6.8s) ease-in-out infinite;
  animation-delay: var(--fly-float-delay, 0s);
  animation-play-state: paused;
}
.awfly.is-flying.is-in-view .awcard.is-on-screen .awcard-float { animation-play-state: running; }
/* Still while it is being pointed at or read. */
.awfly.is-flying .awcard:is(:hover, :focus-within) .awcard-float { animation-play-state: paused !important; }
@keyframes awcard-float {
  0%, 100% { transform: translate3d(-4px, 6px, 0) rotate(-1.1deg); }
  25%      { transform: translate3d(3px, -5px, 0) rotate(0.45deg); }
  50%      { transform: translate3d(6px, -14px, 0) rotate(1.35deg); }
  75%      { transform: translate3d(-3px, -3px, 0) rotate(-0.6deg); }
}

@media (max-width: 700px) {
  .awfly-list { gap: var(--sp-4); }
  .awfly.is-flying .awfly-head { top: var(--sp-4); }
}

@media print {
  .awfly.is-flying .awfly-stage {
    position: relative;
    height: auto;
    padding: 0;
    overflow: visible;
  }
  .awfly.is-flying .awfly-world {
    position: static;
    width: auto !important;
    height: auto !important;
    transform: none !important;
  }
  .awfly.is-flying .awfly-list {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--sp-4);
  }
  .awfly.is-flying .awcard {
    position: static;
    width: auto;
    transform: none;
    break-inside: avoid;
  }
  .awfly.is-flying .awcard-link { box-shadow: none; }
  .awcard-float { animation: none !important; }
  .awfly-image,
  .awfly-shade,
  .awfly-skip { display: none !important; }
}

/* The opening photograph is capped at 62svh, and at that cap a 2:3 portrait
   loses 182px — 91 off the top, where this student's head is. Anchored to the
   top edge instead, so the crop all comes off the tarmac at the bottom. */
.exoffer-portrait img { object-position: 50% 0; }
