/**
 * Recent Scholarship Awardees — page-scoped styles.
 *
 * Enqueued only on /scholarship-awardees/ (borrego_basic_awardees_enqueue),
 * with a dependency on basic-borrego-motion so it cascades after the entire
 * site chain. Nothing here may leak onto other pages, and nothing here may
 * leave content hidden when a feature is missing: the profiles region is
 * hidden ONLY under [data-bb-hydrated], which only awardees.js can stamp —
 * and only after its whole setup has succeeded.
 *
 * ART DIRECTION, one primary device per view:
 *   wall        organic portrait silhouettes (three rotating well shapes)
 *   celebration the gold halo behind the masthead portrait
 *   journey     the deckled archival treatment, used nowhere else
 *
 * The blob/deckle custom properties are declared LOCALLY on .bb-scholars
 * rather than read from art-direction.css, exactly as the board block
 * restates its two helpers: this page must not depend on a stylesheet whose
 * scoping might change.
 */

.bb-scholars {
	/* The --bb-scholars-well-* radius trio that used to sit here was never
	   read anywhere — the wells' radii are written out per shape below — and
	   was removed deliberately with the 1:1 well change. */
	--bb-scholars-deckle: 8px 22px 12px 20px / 20px 10px 24px 12px;

	/* Hoisted off the profile faces so the pending veil that sits UNDER the
	   flip rig and the faces themselves can never drift apart. */
	--bb-scholars-portrait-blob: 38% 62% 56% 44% / 44% 38% 62% 56%;

	/* The warm placeholder a photo resolves out of. Deliberately NOT the
	   forest gradient the wells wear: a portrait arriving out of near-black is
	   a flash; out of dune it is a develop. base-alt -> base, the exact
	   inverse of the well's forest-deep -> forest. */
	--bb-scholars-veil: linear-gradient(
		135deg,
		var( --wp--preset--color--base-alt ) 0%,
		var( --wp--preset--color--base ) 100%
	);

	background-color: var( --wp--preset--color--base );
}

/* --------------------------------------------------------------------------
   Intro
   -------------------------------------------------------------------------- */

.bb-scholars__intro {
	/* The page renders in a FLUSH main (basic_borrego_is_composed() signal 2),
	   so this top padding is the whole gap below the site header. The clamp is
	   .bb-section's rhythm verbatim (components.css), which is what keeps the
	   space under the menu identical to every other composed page. */
	padding-block: clamp( 3rem, 6vw, 5rem ) var( --wp--preset--spacing--50 );
}

.bb-scholars__intro-inner {
	margin-inline: auto;
	max-width: var( --wp--style--global--content-size, 760px );
	padding-inline: var( --wp--preset--spacing--40 );
}

.bb-scholars__eyebrow {
	color: var( --wp--preset--color--terracotta-text );
	margin: 0 0 var( --wp--preset--spacing--20 );
}

.bb-scholars__title {
	color: var( --wp--preset--color--forest );
	font-family: var( --wp--preset--font-family--display );
	font-size: var( --wp--preset--font-size--xx-large );
	font-weight: 500;
	line-height: 1.1;
	margin: 0 0 var( --wp--preset--spacing--20 );
}

.bb-scholars__brush {
	color: var( --wp--preset--color--terracotta );
	display: block;
	height: 0.55rem;
	margin-bottom: 1rem;
	width: 7.5rem;
}

.bb-scholars__lead p {
	color: var( --wp--preset--color--contrast );
	margin: 0;
	max-width: 46rem;
}

/* --------------------------------------------------------------------------
   Notices
   -------------------------------------------------------------------------- */

.bb-scholars__notice,
.bb-scholars__empty {
	margin-inline: auto;
	max-width: var( --wp--style--global--wide-size, 1200px );
	padding-inline: var( --wp--preset--spacing--40 );
}

.bb-scholars__empty {
	max-width: var( --wp--style--global--content-size, 760px );
	padding-block: var( --wp--preset--spacing--50 ) var( --wp--preset--spacing--70 );
	text-align: center;
}

.bb-scholars__notice {
	background-color: var( --wp--preset--color--base-alt );
	border-left: 3px solid var( --wp--preset--color--terracotta-text );
	color: var( --wp--preset--color--contrast );
	font-size: var( --wp--preset--font-size--small );
	margin-block-end: var( --wp--preset--spacing--40 );
	padding: var( --wp--preset--spacing--30 ) var( --wp--preset--spacing--40 );
}

/* --------------------------------------------------------------------------
   Year navigation chips
   -------------------------------------------------------------------------- */

.bb-scholars__yearnav {
	display: flex;
	flex-wrap: wrap;
	gap: var( --wp--preset--spacing--20 );
	margin-inline: auto;
	max-width: var( --wp--style--global--wide-size, 1200px );
	padding-block-end: var( --wp--preset--spacing--40 );
	padding-inline: var( --wp--preset--spacing--40 );
}

.bb-scholars__yearchip {
	background-color: var( --wp--preset--color--base-alt );
	border-radius: 999px;
	color: var( --wp--preset--color--forest );
	font-size: var( --wp--preset--font-size--small );
	font-weight: 600;
	padding: 0.45em 1.1em;
	text-decoration: none;
	transition: background-color var( --bb-dur-quick ) var( --bb-ease-out ), color var( --bb-dur-quick ) var( --bb-ease-out );
}

.bb-scholars__yearchip:hover,
.bb-scholars__yearchip:focus-visible {
	background-color: var( --wp--preset--color--forest );
	color: var( --wp--preset--color--base );
}

/* --------------------------------------------------------------------------
   Year bands
   -------------------------------------------------------------------------- */

.bb-scholars__year {
	padding-block: var( --wp--preset--spacing--50 ) var( --wp--preset--spacing--60 );
}

.bb-scholars__year--alt {
	background-color: var( --wp--preset--color--base-alt );
}

.bb-scholars__yearhead {
	align-items: baseline;
	display: flex;
	flex-wrap: wrap;
	gap: var( --wp--preset--spacing--20 ) var( --wp--preset--spacing--30 );
	margin-inline: auto;
	max-width: var( --wp--style--global--wide-size, 1200px );
	padding-block-end: var( --wp--preset--spacing--40 );
	padding-inline: var( --wp--preset--spacing--40 );
}

.bb-scholars__yeartitle {
	color: var( --wp--preset--color--forest );
	font-family: var( --wp--preset--font-family--display );
	font-size: var( --wp--preset--font-size--xx-large );
	font-weight: 500;
	line-height: 1.05;
	margin: 0;
}

.bb-scholars__yearcount {
	color: var( --wp--preset--color--terracotta-text );
	font-size: var( --wp--preset--font-size--small );
	font-weight: 600;
	letter-spacing: 0.08em;
	margin: 0;
	text-transform: uppercase;
}

/* Collapsed past years: the whole head is the summary. */
.bb-scholars__year--past > .bb-scholars__yearhead--summary {
	cursor: pointer;
	list-style: none;
	padding-block-end: 0;
}

.bb-scholars__year--past[ open ] > .bb-scholars__yearhead--summary {
	padding-block-end: var( --wp--preset--spacing--40 );
}

.bb-scholars__yearhead--summary::-webkit-details-marker {
	display: none;
}

.bb-scholars__yearchevron {
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	display: inline-block;
	height: 0.45em;
	margin-inline-start: 0.5em;
	rotate: 45deg;
	transition: rotate var( --bb-dur-base ) var( --bb-ease-out );
	width: 0.45em;
}

.bb-scholars__year--past[ open ] .bb-scholars__yearchevron {
	rotate: 225deg;
}

.bb-scholars__yearhead--summary:hover .bb-scholars__yeartitle,
.bb-scholars__yearhead--summary:focus-visible .bb-scholars__yeartitle {
	color: var( --wp--preset--color--terracotta-text );
}

/* --------------------------------------------------------------------------
   The wall
   -------------------------------------------------------------------------- */

.bb-scholars__grid {
	display: grid;
	gap: var( --wp--preset--spacing--40 );
	grid-template-columns: 1fr;
	margin-inline: auto;
	max-width: var( --wp--style--global--wide-size, 1200px );
	padding-inline: var( --wp--preset--spacing--40 );
}

@media ( min-width: 520px ) {
	.bb-scholars__grid { grid-template-columns: repeat( 2, 1fr ); }
}

@media ( min-width: 900px ) {
	.bb-scholars__grid { grid-template-columns: repeat( 3, 1fr ); }
}

@media ( min-width: 1280px ) {
	.bb-scholars__grid { grid-template-columns: repeat( 4, 1fr ); }
}

/* Subtle stagger, VISUAL ONLY — DOM and tab order stay alphabetical. Applied
   from the two-column width up; a single column must never stagger. */
@media ( min-width: 520px ) {
	.bb-scholar-card--shape-b { margin-block-start: 0.75rem; }
	.bb-scholar-card--shape-c { margin-block-start: 0.35rem; }
}

.bb-scholar-card {
	display: flex;
}

.bb-scholar-card__link {
	background-color: #fff;
	border-radius: 10px 10px 8px 8px;
	box-shadow: rgb( 42 42 36 / 0.1 ) 0 10px 26px;
	color: inherit;
	display: flex;
	flex-direction: column;
	overflow: clip;
	text-decoration: none;
	transition:
		translate var( --bb-dur-base ) var( --bb-ease-out ),
		box-shadow var( --bb-dur-base ) var( --bb-ease-out );
	width: 100%;
}

.bb-scholar-card__link:hover,
.bb-scholar-card__link:focus-visible {
	box-shadow: rgb( 42 42 36 / 0.2 ) 0 22px 46px;
	translate: 0 -6px;
}

.bb-scholar-card__link:focus-visible {
	outline: 2px solid var( --wp--preset--color--terracotta-text );
	outline-offset: 3px;
}

/* The organic silhouette — the wall's one device. The SQUARE well pins layout
   (zero CLS) and matches the hub crop editor's 1:1 frame exactly, so a
   manager-authored grid crop shows the framing they chose; the forest
   gradient letterboxes odd shapes, and the rotating radius variant is what
   makes fifty identical cards read as a field. The mask is GENEROUS at the
   top edge on purpose: it must never clip hair, graduation caps, or anything
   else a portrait leads with. Vertical radii are %-of-height, so the 4:5→1:1
   change scaled them ×1.25 to preserve the drawn arch. */
.bb-scholar-card__well {
	aspect-ratio: 1 / 1;
	background: linear-gradient( 135deg, var( --wp--preset--color--forest-deep ) 0%, var( --wp--preset--color--forest ) 100% );
	border-end-end-radius: 70% 15%;
	border-end-start-radius: 30% 15%;
	display: grid;
	flex-shrink: 0;
	/* Pre-create the stacking context that awardees.js's view-transition-name
	   would otherwise create at tap time. Establishing one mid-frame made
	   WebKit drop the absolutely-positioned photo for a single frame, so the
	   tapped card flashed as a bare forest silhouette immediately before the
	   morph. Recorded at 1x DPI, frame 39 of the open flight. Costs nothing
	   when no transition is running. */
	isolation: isolate;
	margin-inline: 6%;
	margin-block-start: 6%;
	overflow: clip;
	place-items: center;
	position: relative;
	width: 88%;
}

.bb-scholar-card--shape-a .bb-scholar-card__well { border-start-start-radius: 24% 38%; border-start-end-radius: 76% 38%; }
.bb-scholar-card--shape-b .bb-scholar-card__well { border-start-start-radius: 76% 38%; border-start-end-radius: 24% 38%; }
.bb-scholar-card--shape-c .bb-scholar-card__well { border-start-start-radius: 50% 45%; border-start-end-radius: 50% 45%; }

/* center 22% stays as the NO-CROP framing. This deliberately diverges from
   the hub contract's centered-cover fallback (public-class-pages-api.md,
   "Rendering one"): the theme ships ahead of managers authoring crops, and
   swapping every live scholar to a centered crop on deploy day would regress
   the head-biased framing the wall was tuned around. A scholar keeps this
   legacy framing until a manager crops them — so "matches the hub editor
   exactly" is only claimed for CROPPED scholars. */
.bb-scholar-card__photo {
	height: 100%;
	inset: 0;
	object-fit: cover;
	object-position: center 22%;
	position: absolute;
	width: 100%;
}

/* A manager-authored grid crop: the img becomes an oversized box positioned
   by the inline width/height/left/top percentages the feed precomputed
   (borrego_basic_classes_crop_style()); the square well is the clipping
   window. */
.bb-scholar-card__photo--cropped {
	inset: auto;        /* base inset:0 would pin right/bottom against inline left/top */
	max-width: none;
	object-fit: fill;   /* box ratio equals crop ratio by construction; neutralises cover + 22% */
	object-position: 0 0;
}

.bb-scholar-card__initials {
	color: var( --wp--preset--color--terracotta-on-dark );
	font-family: var( --wp--preset--font-family--display );
	font-size: 3.2rem;
	font-weight: 600;
	letter-spacing: 0.04em;
	line-height: 1;
}

/* Rendered but idle whenever a photo exists; awardees.js swaps it in when a
   portrait 404s. ADJACENT sibling on purpose — same contract as the board. */
.bb-scholar-card__initials--fallback { display: none; }
.bb-scholar-card__photo.is-hidden { display: none; }
.bb-scholar-card__photo.is-hidden + .bb-scholar-card__initials--fallback { display: block; }

/* --------------------------------------------------------------------------
   The load-in
   --------------------------------------------------------------------------
   THE PENDING STATE IS A CLASS APPLIED BY JAVASCRIPT — never a base style.
   awardees.js stamps .is-pending on the WELL only for a photo that was not
   already `complete` when it ran, so a cached photo, an eager photo that has
   already decoded, a photo that already 404'd, and a visitor with no
   JavaScript at all each take exactly the path they took before this block
   existed. There is no state in which this file hides content — the same
   fail-safe rule motion.css states for `opacity: 0`.

   THE VEIL IS A PSEUDO-ELEMENT THAT FADES OUT, AND NOTHING ON THE <img> IS
   TOUCHED. Two properties are already spoken for: `opacity` on the profile
   faces belongs to the flip (see the face-swap block further down), and
   `filter` is a GROUPING property, which flattens the preserve-3d rig the
   moment it is applied inside one. Dissolving a separate box off an untouched
   photo avoids both, and keeps the view-transition preloader's src churn on
   .bb-scholar-card__photo entirely out of the picture.

   ::after, not ::before: this must paint ABOVE the photo. `overflow: clip` and
   `isolation: isolate` on the well clip it to the arch and contain it for
   free. */
.bb-scholar-card__well.is-pending::after,
.bb-scholar-card__well.is-settling::after {
	background-image: var( --bb-scholars-veil );
	content: "";
	inset: 0;
	pointer-events: none;
	position: absolute;
}

@keyframes bb-scholars-veil-out {
	from { opacity: 1; }
	to   { opacity: 0; }
}

/* --bb-dur-page, not --bb-dur-base: the token scale is named for the SIZE of
   the thing that moves, and a wall of portraits resolving is section-scale.

   linear, not --bb-ease-out. An eased opacity curve is the right shape for
   something ARRIVING, but this is a cross-fade between two opaque layers, and
   --bb-ease-out puts 91% of it in the first half — measured 0.09 at the
   midpoint. That reads as the snap the veil exists to remove. Linear is what
   makes a dissolve look even, and it is the same choice the scroll reveal
   below already makes. */
.bb-scholar-card__well.is-settling::after {
	animation: bb-scholars-veil-out var( --bb-dur-page ) linear both;
}

.bb-scholar-card__body {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: var( --wp--preset--spacing--20 );
	padding: var( --wp--preset--spacing--30 ) var( --wp--preset--spacing--40 ) var( --wp--preset--spacing--40 );
}

.bb-scholar-card__name {
	color: var( --wp--preset--color--forest );
	font-family: var( --wp--preset--font-family--display );
	/* clamp() is the long-name insurance: Playfair at a fixed size wraps a
	   50-character compound name into four lines. */
	font-size: clamp( 1.1rem, 0.9rem + 0.8vw, 1.3rem );
	font-weight: 600;
	line-height: 1.2;
	margin: 0;
	overflow-wrap: anywhere;
}

.bb-scholar-card__quote {
	-webkit-box-orient: vertical;
	color: var( --wp--preset--color--terracotta-text );
	display: -webkit-box;
	font-family: var( --wp--preset--font-family--display );
	font-size: var( --wp--preset--font-size--medium );
	font-style: italic;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	line-height: 1.35;
	margin: 0;
	overflow: hidden;
}

.bb-scholar-card__more {
	align-items: center;
	color: var( --wp--preset--color--terracotta-text );
	display: inline-flex;
	font-size: var( --wp--preset--font-size--small );
	font-weight: 600;
	gap: 0.4em;
	margin-top: auto;
	position: relative;
}

.bb-scholar-card__more > span[ aria-hidden ] {
	display: inline-block;
	transition: translate var( --bb-dur-base ) var( --bb-ease-out );
}

.bb-scholar-card__link:hover .bb-scholar-card__more > span[ aria-hidden ],
.bb-scholar-card__link:focus-visible .bb-scholar-card__more > span[ aria-hidden ] {
	translate: 0.3rem 0;
}

/* The terracotta brush wipe under the name — the nav-underline mechanic. */
.bb-scholar-card__more::after {
	background: currentColor;
	block-size: 2px;
	border-radius: 2px;
	content: "";
	inset-block-end: -0.35em;
	inset-inline: 0;
	position: absolute;
	scale: 0 1;
	transform-origin: left center;
	transition: scale var( --bb-dur-base ) var( --bb-ease-out );
}

.bb-scholar-card__link:hover .bb-scholar-card__more::after,
.bb-scholar-card__link:focus-visible .bb-scholar-card__more::after {
	scale: 1 1;
}

/* Scroll-driven entrance, copied with motion.css's exact double gate and
   declaration order — see the traps documented there before editing. */
@media ( prefers-reduced-motion: no-preference ) {
	@supports ( animation-timeline: view() ) {
		@keyframes bb-scholars-reveal {
			from { opacity: 0; translate: 0 1.5rem; }
			to   { opacity: 1; translate: 0 0; }
		}

		.bb-scholar-card {
			animation: bb-scholars-reveal linear both;
			animation-timeline: view();
			animation-range: entry 5% entry 55%;
		}
	}
}

/* --------------------------------------------------------------------------
   The profiles region — two authorities
   --------------------------------------------------------------------------
   Without JavaScript: ordinary in-flow articles below the grids, each one a
   readable celebration page reached by its fragment. With JavaScript:
   awardees.js stamps data-bb-hydrated and this region stands down; articles
   are moved into the dialog on demand. The attribute is the ONLY thing that
   hides this content, and only a fully successful hydration sets it. */

.bb-scholars[ data-bb-hydrated ] .bb-scholars__profiles {
	display: none;
}

.bb-scholars__profiles {
	border-top: 1px solid rgb( 42 42 36 / 0.12 );
}

/* A fragment navigation focuses the tabindex="-1" article and Chrome draws
   its default ring around the whole page-width profile. Pointer/fragment
   focus needs no ring; keyboard focus lands on the controls inside. */
.bb-scholar-profile:focus {
	outline: none;
}

.bb-scholars__profiles .bb-scholar-profile {
	border-bottom: 1px solid rgb( 42 42 36 / 0.12 );
}

/* Hide the fun-side BUTTON until JavaScript owns it; the static figure at the
   end of the body is the no-JS home of the same photo. Once hydrated, the
   figure retires and the flip takes over — the photo is reachable in every
   state. */
.bb-scholars:not( [ data-bb-hydrated ] ) .bb-scholar-profile__funbtn {
	display: none;
}

.bb-scholars[ data-bb-hydrated ] .bb-scholar-profile__fun-static {
	display: none;
}

/* --------------------------------------------------------------------------
   The celebration page (in flow and inside the dialog alike)
   -------------------------------------------------------------------------- */

.bb-scholar-profile__mast {
	background: linear-gradient( 160deg, var( --wp--preset--color--forest-deep ) 0%, var( --wp--preset--color--forest ) 100% );
	color: var( --wp--preset--color--base );
	-webkit-mask-image: var( --bb-wave-bottom );
	mask-image: var( --bb-wave-bottom );
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-size: 100% 100%;
	mask-size: 100% 100%;
	padding-block: var( --wp--preset--spacing--60 ) var( --wp--preset--spacing--70 );
}

.bb-scholar-profile__mast-inner {
	align-items: center;
	display: flex;
	flex-direction: column;
	gap: var( --wp--preset--spacing--40 );
	margin-inline: auto;
	max-width: var( --wp--style--global--wide-size, 1200px );
	padding-inline: var( --wp--preset--spacing--40 );
	text-align: center;
}

@media ( min-width: 760px ) {
	.bb-scholar-profile__mast-inner {
		flex-direction: row;
		gap: var( --wp--preset--spacing--50 );
		text-align: start;
	}
}

.bb-scholar-profile__portrait {
	align-items: center;
	display: flex;
	flex-direction: column;
	flex-shrink: 0;
	gap: var( --wp--preset--spacing--30 );
}

/* The halo anchors to THIS box — portrait only — so its rays can never reach
   the fun-side button below. */
.bb-scholar-profile__stagebox {
	display: block;
	position: relative;
}

/* The masthead portrait's pending veil — on the STAGEBOX, deliberately NOT on
   the rig and NOT a pseudo-element inside it.

   .bb-scholar-profile__well below is a preserve-3d rendering context whose
   back-face culling this file already documents as unreliable in WebKit (see
   the DO NOT TRUST backface-visibility note on the face swap). Anything added
   inside it becomes a fourth coplanar 3D child of that rig. The stagebox is
   the rig's PARENT, is exactly the rig's box — a block item in a centred flex
   column — and sits outside the 3D context entirely, so a veil here is
   visually identical and costs the flip nothing: no opacity, no transform, no
   filter, no property the flip reads.

   .is-pending is always gone before the flip can run: the fun-side button
   cannot be reached until the portrait has loaded. */
.bb-scholar-profile__stagebox.is-pending::after,
.bb-scholar-profile__stagebox.is-settling::after {
	background-image: var( --bb-scholars-veil );
	border-radius: var( --bb-scholars-portrait-blob );
	content: "";
	inset: 0;
	pointer-events: none;
	position: absolute;
}

.bb-scholar-profile__stagebox.is-settling::after {
	animation: bb-scholars-veil-out var( --bb-dur-page ) linear both;
}

/* The celebration view's one device: a gold sun-ray halo, slowly turning.
   Purely decorative, aria-hidden, and effectively static under reduced
   motion — style.css's blanket rule zeroes the duration. */
.bb-scholar-profile__halo {
	background: repeating-conic-gradient(
		var( --wp--preset--color--gold ) 0deg 4deg,
		transparent 4deg 16deg
	);
	border-radius: 50%;
	inset: -6%;
	/* closest-side, NOT the default farthest-corner: the ring must hug the
	   portrait, never reach the button below the stage box. */
	-webkit-mask-image: radial-gradient( circle closest-side, transparent 84%, #fff 85%, #fff 99%, transparent 100% );
	mask-image: radial-gradient( circle closest-side, transparent 84%, #fff 85%, #fff 99%, transparent 100% );
	opacity: 0.75;
	pointer-events: none;
	position: absolute;
}

@keyframes bb-scholars-halo {
	to { rotate: 360deg; }
}

.bb-scholar-profile__halo {
	animation: bb-scholars-halo 90s linear infinite;
}

/* The portrait rig. The blob mask lives on the FACES, never on this element:
   mask-image on the preserve-3d rig flattens the 3D and kills the flip — the
   trap documented at the top of the board block's style.css. */
.bb-scholar-profile__well {
	aspect-ratio: 1;
	display: block;
	perspective: 1200px;
	position: relative;
	/* rotateY(0deg), not the initial `none`. WebKit only honours the faces'
	   backface-visibility when the rig carries a real 3D transform; with
	   `none` it flattens the context, DOM order wins, and the fun-side photo
	   — which comes second — paints straight over the portrait. Safari showed
	   every scholar's fun photo as their portrait; Chrome showed the right one,
	   which is exactly why it went unnoticed. Measured by sampling the centre
	   pixel on a plain deep link: WebKit rgb(90,102,76) vs Chromium
	   rgb(113,78,55). Animating from rotateY(0deg) to rotateY(180deg) is also
	   a better-defined transition than animating from `none`. */
	transform: rotateY( 0deg );
	transform-style: preserve-3d;
	transition: transform 0.7s cubic-bezier( 0.2, 0.8, 0.2, 1 );
	width: min( 16rem, 60vw );
}

.bb-scholar-profile__well.is-fun {
	transform: rotateY( 180deg );
}

/* The 3D faces are WRAPPER spans, not the imgs: the face carries the blob
   radius, the clip and backface-visibility, so a cropped img can be an
   oversized offset box inside its square clipping window — an img cannot be
   both the clipped face and the thing the clip crops. The initials span keeps
   the same treatment (it sits inside the front face). */
.bb-scholar-profile__face,
.bb-scholar-profile__initials {
	backface-visibility: hidden;
	-webkit-backface-visibility: hidden;
	border-radius: var( --bb-scholars-portrait-blob );
	height: 100%;
	inset: 0;
	overflow: clip;
	position: absolute;
	width: 100%;
}

.bb-scholar-profile__photo {
	display: block;
	height: 100%;
	object-fit: cover;
	width: 100%;
}

/* A detail/funny crop: positioned by the inline percentages inside the face's
   square clip. fill, not cover — the box ratio equals the crop ratio by
   construction, so fill is exact and neutralises the cover default. */
.bb-scholar-profile__photo--cropped {
	max-width: none;
	object-fit: fill;
	position: absolute;
}

.bb-scholar-profile__face--fun {
	transform: rotateY( 180deg );
}

/* DO NOT TRUST backface-visibility HERE — swap the faces explicitly.

   In WebKit the rig's 3D context is flat in practice: neither giving the well
   a real rotateY(0deg) transform nor separating the faces with translateZ
   changes anything, so the back face is never culled and the fun photo —
   second in DOM order — paints straight over the portrait. In Safari every
   scholar with a fun photo wore it AS their portrait, on the plain page, with
   no transition involved. Chrome culls correctly, which is exactly why it went
   unnoticed. Measured by sampling the portrait's centre pixel on a deep link:
   WebKit rgb(90,102,76) — the green fun photo — against Chromium
   rgb(113,78,55), the salmon portrait.

   The swap is delayed to 0.35s, half of the 0.7s rotation, which is the
   instant the rig is edge-on and nothing is legible anyway. Opacity, not
   visibility: visibility would also hide it from the view transition snapshot
   mid-flip.

   The swap lives on the FACE wrappers, so the initials span — inside the
   front face — participates too. */
.bb-scholar-profile__face--front,
.bb-scholar-profile__face--fun {
	transition: opacity 0s linear 0.35s;
}

.bb-scholar-profile__face--fun {
	opacity: 0;
}

.bb-scholar-profile__well.is-fun .bb-scholar-profile__face--fun {
	opacity: 1;
}

.bb-scholar-profile__well.is-fun .bb-scholar-profile__face--front {
	opacity: 0;
}

.bb-scholar-profile__initials {
	align-items: center;
	background: linear-gradient( 135deg, var( --wp--preset--color--forest ) 0%, var( --wp--preset--color--forest-deep ) 100% );
	border: 2px solid var( --wp--preset--color--terracotta-on-dark );
	color: var( --wp--preset--color--terracotta-on-dark );
	display: flex;
	font-family: var( --wp--preset--font-family--display );
	font-size: 4rem;
	font-weight: 600;
	justify-content: center;
	letter-spacing: 0.04em;
}

.bb-scholar-profile__funbtn {
	background-color: transparent;
	border: 1.5px solid var( --wp--preset--color--terracotta-on-dark );
	border-radius: 999px;
	color: var( --wp--preset--color--terracotta-on-dark );
	cursor: pointer;
	font-family: var( --wp--preset--font-family--body );
	font-size: var( --wp--preset--font-size--small );
	font-weight: 600;
	min-height: 44px;
	padding: 0.5em 1.3em;
	transition: background-color var( --bb-dur-quick ) var( --bb-ease-out ), color var( --bb-dur-quick ) var( --bb-ease-out );
}

.bb-scholar-profile__funbtn:hover,
.bb-scholar-profile__funbtn:focus-visible {
	background-color: var( --wp--preset--color--terracotta-on-dark );
	color: var( --wp--preset--color--forest-deep );
}

.bb-scholar-profile__funbtn:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}

.bb-scholar-profile__funbtn .bb-scholar-profile__funbtn-hide { display: none; }
.bb-scholar-profile__funbtn[ aria-pressed="true" ] .bb-scholar-profile__funbtn-show { display: none; }
.bb-scholar-profile__funbtn[ aria-pressed="true" ] .bb-scholar-profile__funbtn-hide { display: inline; }

.bb-scholar-profile__year {
	color: var( --wp--preset--color--terracotta-on-dark );
	margin: 0 0 var( --wp--preset--spacing--20 );
}

.bb-scholar-profile__name {
	color: var( --wp--preset--color--base );
	font-family: var( --wp--preset--font-family--display );
	font-size: clamp( 2rem, 1.2rem + 3.4vw, 3.4rem );
	font-weight: 900;
	line-height: 1.05;
	margin: 0 0 var( --wp--preset--spacing--20 );
	overflow-wrap: anywhere;
}

/* The length-sensitive step-down: a 50-character compound name at weight 900
   must wrap into a headline, not a wall. */
.bb-scholar-profile__name--long {
	font-size: clamp( 1.4rem, 1rem + 2.2vw, 2.2rem );
	font-weight: 700;
}

.bb-scholar-profile__brush {
	color: var( --wp--preset--color--terracotta-on-dark );
	display: block;
	height: 0.55rem;
	margin-bottom: 1rem;
	width: 7.5rem;
}

@media ( max-width: 759px ) {
	.bb-scholar-profile__brush { margin-inline: auto; }
}

.bb-scholar-profile__schools {
	color: var( --wp--preset--color--base-alt );
	font-size: var( --wp--preset--font-size--medium );
	margin: 0;
}

/* --- Body ---------------------------------------------------------------- */

.bb-scholar-profile__body {
	display: flex;
	flex-direction: column;
	gap: var( --wp--preset--spacing--50 );
	margin-inline: auto;
	max-width: var( --wp--style--global--content-size, 760px );
	padding-block: var( --wp--preset--spacing--50 ) var( --wp--preset--spacing--70 );
	padding-inline: var( --wp--preset--spacing--40 );
}

.bb-scholar-profile__pullquote {
	border: 0;
	margin: 0;
	padding: 0;
	position: relative;
	text-align: center;
}

.bb-scholar-profile__pullquote p {
	color: var( --wp--preset--color--forest );
	font-family: var( --wp--preset--font-family--display );
	font-size: clamp( 1.5rem, 1.1rem + 1.8vw, 2.2rem );
	font-style: italic;
	line-height: 1.25;
	margin: 0;
}

.bb-scholar-profile__pullquote--long p {
	font-size: clamp( 1.15rem, 1rem + 0.9vw, 1.5rem );
}

.bb-scholar-profile__pullquote-glyph {
	color: var( --wp--preset--color--terracotta );
	display: block;
	font-family: var( --wp--preset--font-family--display );
	font-size: 3.4rem;
	line-height: 0.4;
}

.bb-scholar-profile__bio p,
.bb-scholar-profile__prose p {
	color: var( --wp--preset--color--contrast );
	line-height: 1.65;
	margin: 0;
	/* Answers arrive with \n\n paragraph breaks and no markup. */
	white-space: pre-line;
}

.bb-scholar-profile__section-eyebrow {
	color: var( --wp--preset--color--terracotta-text );
	margin: 0 0 var( --wp--preset--spacing--20 );
}

/* --- Milestones ----------------------------------------------------------
   Built only from facts. Vertical rail by default; horizontal from 760px. */

.bb-scholar-profile__milestones {
	display: flex;
	flex-direction: column;
	gap: var( --wp--preset--spacing--30 );
	list-style: none;
	margin: 0;
	padding: 0;
	position: relative;
}

.bb-scholar-profile__milestone {
	display: grid;
	column-gap: var( --wp--preset--spacing--20 );
	grid-template-columns: auto 1fr;
	position: relative;
}

.bb-scholar-profile__milestone-dot {
	background: var( --wp--preset--color--gold );
	border-radius: 50% 42% 55% 45%;
	grid-row: 1 / span 2;
	height: 0.85rem;
	margin-top: 0.3rem;
	width: 0.85rem;
}

.bb-scholar-profile__milestone--current .bb-scholar-profile__milestone-dot {
	background: transparent;
	border: 2px solid var( --wp--preset--color--gold );
}

.bb-scholar-profile__milestone-label {
	color: var( --wp--preset--color--forest );
	font-weight: 600;
}

.bb-scholar-profile__milestone-detail {
	color: var( --wp--preset--color--contrast );
	font-size: var( --wp--preset--font-size--small );
	grid-column: 2;
}

@media ( min-width: 760px ) {
	.bb-scholar-profile__milestones {
		flex-direction: row;
		flex-wrap: wrap;
		gap: var( --wp--preset--spacing--40 );
	}

	.bb-scholar-profile__milestone {
		flex: 1 1 0;
		grid-template-columns: 1fr;
		min-width: 8rem;
		row-gap: 0.35rem;
	}

	.bb-scholar-profile__milestone-dot {
		grid-row: auto;
		margin-top: 0;
	}

	/* The connecting thread, drawn behind the dots. */
	.bb-scholar-profile__milestone:not( :last-child )::after {
		background: rgb( 201 162 39 / 0.4 );
		content: "";
		height: 2px;
		left: 1.4rem;
		position: absolute;
		right: calc( -1 * var( --wp--preset--spacing--40 ) );
		top: 0.42rem;
	}

	.bb-scholar-profile__milestone-detail {
		grid-column: 1;
	}
}

/* --- Short-answer cards --------------------------------------------------- */

.bb-scholar-profile__qa {
	display: grid;
	gap: var( --wp--preset--spacing--30 );
	grid-template-columns: 1fr;
}

@media ( min-width: 600px ) {
	.bb-scholar-profile__qa { grid-template-columns: repeat( 2, 1fr ); }
}

.bb-scholar-profile__qa-card {
	background-color: var( --wp--preset--color--base-alt );
	border-radius: 8px 34px 8px 34px;
	padding: var( --wp--preset--spacing--30 ) var( --wp--preset--spacing--40 );
}

.bb-scholar-profile__qa-label {
	color: var( --wp--preset--color--terracotta-text );
	margin: 0 0 0.35rem;
}

.bb-scholar-profile__qa-value {
	color: var( --wp--preset--color--forest );
	font-family: var( --wp--preset--font-family--display );
	font-size: var( --wp--preset--font-size--large );
	line-height: 1.3;
	margin: 0;
}

/* --- Journey strip --------------------------------------------------------
   The archival treatment lives ONLY here. Deckled corners, alternating tilt,
   a horizontal snap strip with a partial next image peeking in. */

.bb-scholar-profile__journey-track {
	display: flex;
	gap: var( --wp--preset--spacing--40 );
	list-style: none;
	margin: 0;
	overflow-x: auto;
	overscroll-behavior-x: contain;
	padding: var( --wp--preset--spacing--30 ) var( --wp--preset--spacing--20 );
	scroll-snap-type: x mandatory;
	scroll-padding-inline: var( --wp--preset--spacing--20 );
}

.bb-scholar-profile__journey-item {
	flex: 0 0 min( 78%, 20rem );
	scroll-snap-align: start;
}

.bb-scholar-profile__journey-figure {
	background: #fff;
	border-radius: var( --bb-scholars-deckle );
	box-shadow: rgb( 42 42 36 / 0.16 ) 0 10px 24px;
	margin: 0;
	padding: var( --wp--preset--spacing--20 );
	transform: rotate( -1.6deg );
}

.bb-scholar-profile__journey-item:nth-child( even ) .bb-scholar-profile__journey-figure {
	transform: rotate( 1.4deg );
}

.bb-scholar-profile__journey-photo {
	aspect-ratio: 4 / 3;
	border-radius: calc( var( --wp--preset--spacing--20 ) / 2 );
	display: block;
	height: auto;
	object-fit: cover;
	width: 100%;
}

.bb-scholar-profile__journey-caption {
	color: var( --wp--preset--color--contrast );
	display: flex;
	flex-direction: column;
	font-size: var( --wp--preset--font-size--small );
	gap: 0.1em;
	padding: var( --wp--preset--spacing--20 ) var( --wp--preset--spacing--20 ) 0;
}

.bb-scholar-profile__journey-date {
	color: var( --wp--preset--color--terracotta-text );
	font-size: var( --wp--preset--font-size--x-small );
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.bb-scholar-profile__journey-controls {
	align-items: center;
	display: flex;
	gap: var( --wp--preset--spacing--30 );
	justify-content: center;
	padding-block-start: var( --wp--preset--spacing--20 );
}

.bb-scholar-profile__journey-btn {
	align-items: center;
	background-color: var( --wp--preset--color--terracotta-text );
	border: 0;
	border-radius: 50%;
	color: var( --wp--preset--color--base );
	cursor: pointer;
	display: inline-flex;
	font-size: 1.1rem;
	height: 2.75rem;
	justify-content: center;
	transition: background-color var( --bb-dur-quick ) var( --bb-ease-out );
	width: 2.75rem;
}

.bb-scholar-profile__journey-btn:hover,
.bb-scholar-profile__journey-btn:focus-visible {
	background-color: var( --wp--preset--color--forest );
}

.bb-scholar-profile__journey-btn:focus-visible {
	outline: 2px solid var( --wp--preset--color--terracotta-text );
	outline-offset: 2px;
}

.bb-scholar-profile__journey-pos {
	color: var( --wp--preset--color--contrast );
	font-size: var( --wp--preset--font-size--small );
	font-variant-numeric: tabular-nums;
}

/* --- Fun-side static figure (no-JS only; see the hydration rules above) --- */

.bb-scholar-profile__fun-static {
	background: #fff;
	border-radius: var( --bb-scholars-deckle );
	box-shadow: rgb( 42 42 36 / 0.16 ) 0 10px 24px;
	margin: 0 auto;
	max-width: 18rem;
	padding: var( --wp--preset--spacing--20 );
	transform: rotate( -1.6deg );
}

.bb-scholar-profile__fun-static img {
	border-radius: 4px;
	display: block;
	height: auto;
	width: 100%;
}

/* With a funny crop the img is wrapped in this square clipping frame — an
   explicit contract, because a bare inline span would not form the box the
   crop percentages resolve against. The inline crop style (width/height/left/
   top) wins over the element rule above; the img just needs the frame and its
   own --cropped positioning. */
.bb-scholar-profile__fun-static-frame {
	aspect-ratio: 1;
	border-radius: 4px;
	display: block;
	overflow: hidden;
	position: relative;
	width: 100%;
}

.bb-scholar-profile__fun-static-frame img {
	border-radius: 0; /* the radius genuinely moves to the frame */
}

.bb-scholar-profile__fun-static figcaption {
	color: var( --wp--preset--color--contrast );
	font-size: var( --wp--preset--font-size--small );
	padding: var( --wp--preset--spacing--20 ) var( --wp--preset--spacing--20 ) 0;
}

.bb-scholar-profile__back {
	margin: 0;
	text-align: center;
}

.bb-scholar-profile__back a {
	color: var( --wp--preset--color--terracotta-text );
	font-weight: 600;
}

/* --------------------------------------------------------------------------
   The stage
   --------------------------------------------------------------------------
   A full-viewport <dialog>. showModal() supplies the top layer, focus
   containment and Escape; everything below makes it read as a PAGE — cream
   ground, sticky chrome, its own scroller — rather than a modal. */

/* THE STAGE IS AN ORDINARY PAGE SECTION, NOT A MODAL.
   It was once a full-viewport showModal() takeover with a view-transition
   morph out of the tapped card. That hid the site header, and the morph was
   invisible in Safari (WebKit could not rasterise the portrait snapshot inside
   the 420ms flight, so the picture simply popped in at the end). Both problems
   disappear when the detail is just a section of the page: the header stays
   put and clickable, and there is no snapshot for any engine to miss.

   The element is still a <dialog> so the no-JS markup and the close/Escape
   semantics stay intact — but it is opened by setting the `open` attribute,
   never showModal(), so it never enters the top layer. */
.bb-scholar-stage {
	background: var( --wp--preset--color--base );
	border: 0;
	color: var( --wp--preset--color--contrast );
	display: block;
	inline-size: auto;
	margin: 0;
	max-height: none;
	max-width: none;
	min-block-size: 60vh;
	padding: 0;
	position: static;
}

.bb-scholar-stage:not( [ open ] ) {
	display: none;
}

/* Grid and detail are two views of one page: showing either one hides the
   other, so the visitor never scrolls past a wall of cards to reach the
   scholar they just tapped.

   Everything EXCEPT the stage is hidden, rather than an itemised list of
   intro/yearnav/grid. The year bands wrap their own headings, so hiding the
   grids alone left "Class of 2026" and "Class of 2025" stranded above the
   scholar. Excluding by the stage's own attribute cannot drift as the page
   markup grows. */
.bb-scholars.is-detail > *:not( [ data-bb-stage ] ) {
	display: none;
}

/* The fallback open, for engines without View Transitions: a quiet
   rise-and-fade. Under reduced motion the blanket rule in style.css zeroes it.

   Gated on html.bb-has-vt, which awardees.js adds at init when
   document.startViewTransition exists. It CANNOT be gated on the transient
   html.bb-stage-opening class instead: that class is removed when the
   transition finishes, and re-enabling `animation` on an element that already
   has the `open` attribute restarts it — a second, spurious rise-and-fade
   playing straight after the morph. */
@keyframes bb-scholars-stage-in {
	from { opacity: 0; translate: 0 0.75rem; }
	to   { opacity: 1; translate: 0 0; }
}

html:not( .bb-has-vt ) .bb-scholar-stage[ open ] {
	animation: bb-scholars-stage-in var( --bb-dur-base ) var( --bb-ease-out );
}

/* Sticky, not fixed: fixed would float over the site header now that the
   stage sits in the page flow instead of the top layer.

   Both bars are also NAMED for view transitions — see the block at the end of
   this file. Unnamed they ride inside the root snapshot, and every prev/next
   re-blends them ("3 of 8" popping in and out). */
.bb-scholar-stage__bar {
	align-items: center;
	background: rgb( 239 231 219 / 0.92 );
	backdrop-filter: blur( 6px );
	display: flex;
	inset-block-start: 0;
	inset-inline: 0;
	justify-content: space-between;
	padding: max( var( --wp--preset--spacing--20 ), env( safe-area-inset-top ) ) var( --wp--preset--spacing--40 ) 0.85rem;
	/* Sticky, not fixed: fixed would float over the site header now that the
	   stage sits in the page flow instead of the top layer. */
	position: sticky;
	z-index: 5;
}

/* Where-am-I: the bar's wayfinding mark. The class year as an eyebrow, the
   scholar's name in the display face, and the milestone road miniaturised as
   the name's own underline — a gold marker glides along it to the scholar's
   position in the class. (The marker is a CSS blob, border-radius
   50% 42% 55% 45%, not a drawing; it was called a poppy before this site
   settled on desert plants, and there is no artwork here to swap.) Identity and position in one composed unit, and it
   keeps telling you whose page you are on after the masthead scrolls away. */
.bb-scholar-stage__where {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	min-height: 2.75rem;
	min-width: 0;
	justify-content: center;
}

.bb-scholar-stage__who {
	display: flex;
	flex-direction: column;
	gap: 0.1rem;
	min-width: 0;
}

.bb-scholar-stage__who-year {
	color: var( --wp--preset--color--terracotta-text );
	font-size: 0.66rem;
	font-weight: 650;
	letter-spacing: 0.13em;
	text-transform: uppercase;
}

.bb-scholar-stage__who-name {
	color: var( --wp--preset--color--forest );
	font-family: var( --wp--preset--font-family--display );
	font-size: 1.1rem;
	font-weight: 600;
	line-height: 1.15;
	max-width: min( 60vw, 22rem );
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.bb-scholar-stage__track {
	background: rgb( 42 42 36 / 0.18 );
	border-radius: 2px;
	display: block;
	height: 2px;
	position: relative;
	width: clamp( 6rem, 22vw, 11rem );
}

.bb-scholar-stage__track::before,
.bb-scholar-stage__track::after {
	background: rgb( 42 42 36 / 0.25 );
	border-radius: 50%;
	content: "";
	height: 0.3rem;
	position: absolute;
	top: 50%;
	translate: 0 -50%;
	width: 0.3rem;
}

.bb-scholar-stage__track::before { left: -0.15rem; }
.bb-scholar-stage__track::after { right: -0.15rem; }

.bb-scholar-stage__thumb {
	background: var( --wp--preset--color--gold );
	border-radius: 50% 42% 55% 45%;
	height: 0.8rem;
	inset-inline-start: 0;
	position: absolute;
	top: 50%;
	translate: -50% -50%;
	transition: inset-inline-start var( --bb-dur-page ) var( --bb-ease-brand );
	width: 0.8rem;
}

/* "All scholars" — the close control wears a miniature of the wall it
   returns to: four card-dots and the words, in a pill. On hover the pill
   fills forest and the mini-wall lights up cream, a little preview of
   heading back out into the field. */
.bb-scholar-stage__close {
	align-items: center;
	background-color: transparent;
	border: 1.5px solid var( --wp--preset--color--terracotta-text );
	border-radius: 999px;
	color: var( --wp--preset--color--terracotta-text );
	cursor: pointer;
	display: inline-flex;
	font-family: var( --wp--preset--font-family--body );
	font-size: var( --wp--preset--font-size--small );
	font-weight: 650;
	gap: 0.6em;
	min-height: 2.75rem;
	padding: 0.4em 1.2em;
	transition:
		background-color var( --bb-dur-quick ) var( --bb-ease-out ),
		border-color var( --bb-dur-quick ) var( --bb-ease-out ),
		color var( --bb-dur-quick ) var( --bb-ease-out );
	white-space: nowrap;
}

.bb-scholar-stage__close-glyph {
	display: grid;
	gap: 2px;
	grid-template-columns: repeat( 2, 0.32rem );
}

.bb-scholar-stage__close-glyph span {
	aspect-ratio: 1;
	background: currentColor;
	border-radius: 30%;
	display: block;
	transition: translate var( --bb-dur-base ) var( --bb-ease-out );
}

.bb-scholar-stage__close:hover,
.bb-scholar-stage__close:focus-visible {
	background-color: var( --wp--preset--color--forest );
	border-color: var( --wp--preset--color--forest );
	color: var( --wp--preset--color--base );
}

/* The mini-wall breathes apart on hover — the field opening back up. */
.bb-scholar-stage__close:hover .bb-scholar-stage__close-glyph span:nth-child( 1 ),
.bb-scholar-stage__close:focus-visible .bb-scholar-stage__close-glyph span:nth-child( 1 ) { translate: -1px -1px; }
.bb-scholar-stage__close:hover .bb-scholar-stage__close-glyph span:nth-child( 2 ),
.bb-scholar-stage__close:focus-visible .bb-scholar-stage__close-glyph span:nth-child( 2 ) { translate: 1px -1px; }
.bb-scholar-stage__close:hover .bb-scholar-stage__close-glyph span:nth-child( 3 ),
.bb-scholar-stage__close:focus-visible .bb-scholar-stage__close-glyph span:nth-child( 3 ) { translate: -1px 1px; }
.bb-scholar-stage__close:hover .bb-scholar-stage__close-glyph span:nth-child( 4 ),
.bb-scholar-stage__close:focus-visible .bb-scholar-stage__close-glyph span:nth-child( 4 ) { translate: 1px 1px; }

.bb-scholar-stage__close:focus-visible {
	outline: 2px solid var( --wp--preset--color--terracotta-text );
	outline-offset: 3px;
}

/* The fixed bars overlay the content, so the scroller needs clearance: the
   mast band runs up under the bar's blur, but its TEXT must start well below
   it, and the article's last line must be able to scroll clear of the footer. */
/* The bars are sticky now, so they occupy real flow space and the article no
   longer has to reserve room underneath them. */
.bb-scholar-stage__slot .bb-scholar-profile__mast {
	padding-block-start: var( --wp--preset--spacing--50 );
}

.bb-scholar-stage__footer {
	align-items: center;
	background: rgb( 239 231 219 / 0.92 );
	backdrop-filter: blur( 6px );
	border-top: 1px solid rgb( 42 42 36 / 0.12 );
	inset-block-end: 0;
	inset-inline: 0;
	display: flex;
	gap: var( --wp--preset--spacing--20 );
	justify-content: space-between;
	padding: var( --wp--preset--spacing--20 ) var( --wp--preset--spacing--40 ) max( var( --wp--preset--spacing--20 ), env( safe-area-inset-bottom ) );
	position: sticky;
	z-index: 5;
}

/* --------------------------------------------------------------------------
   View transitions
   --------------------------------------------------------------------------
   Tapping a card morphs its portrait, name and quote into the scholar page;
   closing reverses it; prev/next slides classmates sideways.

   THE PER-SCHOLAR NAMES ARE NOT DECLARED HERE. awardees.js stamps them on the
   ONE tapped card and the ONE profile at tap time, and releases them when the
   transition ends. They cannot live in a stylesheet: the wall renders dozens
   of .bb-scholar-card__name and .bb-scholar-card__photo elements, and two
   RENDERED elements sharing a view-transition-name makes ViewTransition.ready
   reject — the browser then silently skips the transition entirely. Only the
   stage chrome is named below, and only because the stage is display:none
   whenever it is closed, so those names are never live on the wall.

   This morph was removed once for not rendering in Safari. The fix was not in
   this file — it is the decode gate in awardees.js. Read the header comment
   there before changing anything here, and re-prove any change in WebKit at
   real speed, by frames. Chrome will happily show you something Safari never
   renders. */

/* The portrait pair.
   OLD is the CARD WELL, not the card photo: the well is what carries the
   organic radius and the overflow clip, and a snapshot is captured without
   its ancestors' clipping — naming the photo would start the flight as a bare
   rectangle popping out of the arch. NEW is the front FACE WRAPPER
   (.bb-scholar-profile__face--front), which now carries the blob radius and
   the clip — naming a cropped img would snapshot it unclipped and oversized.
   Each snapshot brings its own shape, so the cross-fade does the shape morph
   and no ::view-transition-image-pair clip is needed; adding one here would
   square off the arch corners.

   The sizes are left to the UA defaults on purpose. Both boxes are 1:1 now
   (square card well, square profile face), so the default block-size:auto is
   a plain scale; object-fit cover + the blend fix below stay as the one-frame
   safety net for any residual mismatch. */
::view-transition-old( bb-scholar-portrait ),
::view-transition-new( bb-scholar-portrait ) {
	/* !important because the UA's -ua-mix-blend-mode-plus-lighter is an
	   ANIMATION, and a plain declaration loses to it. Without this the two
	   portraits brighten into a ghost halfway through the flight. Same trap as
	   the one documented in motion.css. */
	mix-blend-mode: normal !important;
	object-fit: cover;
}

/* The classmate belt. Named on the SLOT — one persistent element — rather
   than on the articles, which are different heights: a named article makes
   the group interpolate its box and the sticky bars hop, which is exactly
   the failure the first version of this shipped with. Snapping the group
   removes box interpolation altogether, so only the snapshots travel. */
@keyframes bb-scholars-page-out-left  { to   { translate: -100% 0; } }
@keyframes bb-scholars-page-in-right  { from { translate:  100% 0; } }
@keyframes bb-scholars-page-out-right { to   { translate:  100% 0; } }
@keyframes bb-scholars-page-in-left   { from { translate: -100% 0; } }

::view-transition-group( bb-scholar-page ) {
	animation-name: none;
}

::view-transition-image-pair( bb-scholar-page ) {
	overflow: clip;
}

::view-transition-old( bb-scholar-page ),
::view-transition-new( bb-scholar-page ) {
	animation-duration: var( --bb-dur-page );
	animation-fill-mode: both;
	animation-timing-function: cubic-bezier( 0.45, 0.05, 0.15, 1 );
	mix-blend-mode: normal !important;
}

/* NO DESCENDANT SPACE before the pseudo. The ::view-transition tree hangs off
   the root element itself, so `html.bb-nav-back ::view-transition-old(…)`
   matches nothing at all. That typo shipped once. */
html.bb-nav-fwd::view-transition-old( bb-scholar-page )  { animation-name: bb-scholars-page-out-left; }
html.bb-nav-fwd::view-transition-new( bb-scholar-page )  { animation-name: bb-scholars-page-in-right; }
html.bb-nav-back::view-transition-old( bb-scholar-page ) { animation-name: bb-scholars-page-out-right; }
html.bb-nav-back::view-transition-new( bb-scholar-page ) { animation-name: bb-scholars-page-in-left; }

/* Persistent chrome: snap the GEOMETRY, cross-fade only the PIXELS. Same
   treatment motion.css gives the site header, and for the same reason — a bar
   whose group animates drifts while the page beneath it slides. */
.bb-scholar-stage__bar {
	view-transition-name: bb-stage-bar;
}

.bb-scholar-stage__footer {
	view-transition-name: bb-stage-footer;
}

::view-transition-group( bb-stage-bar ),
::view-transition-group( bb-stage-footer ) {
	animation-name: none;
}

/* On open and close the bars exist in only ONE of the two states, so the pair
   has a single child. Snapping alone would hard-cut them in; fade instead. */
@keyframes bb-scholars-chrome-fade { from { opacity: 0; } }

::view-transition-new( bb-stage-bar ):only-child,
::view-transition-new( bb-stage-footer ):only-child {
	animation: bb-scholars-chrome-fade var( --bb-dur-base ) var( --bb-ease-out ) both;
}

::view-transition-old( bb-stage-bar ):only-child,
::view-transition-old( bb-stage-footer ):only-child {
	animation: bb-scholars-chrome-fade var( --bb-dur-base ) var( --bb-ease-out ) both reverse;
}


/* --------------------------------------------------------------------------
   Reduced motion
   -------------------------------------------------------------------------- */

@media ( prefers-reduced-motion: reduce ) {
	.bb-scholar-card__link,
	.bb-scholar-card__more > span[ aria-hidden ],
	.bb-scholar-card__more::after,
	.bb-scholar-profile__well {
		transition: none !important;
	}

	/* The face swap is delayed to the midpoint of a rotation that no longer
	   happens. Without this the wrong photo shows for 350ms after every flip:
	   style.css's blanket rule zeroes transition-duration but not delay. */
	.bb-scholar-profile__face--front,
	.bb-scholar-profile__face--fun {
		transition-delay: 0s !important;
	}

	.bb-scholar-card__link:hover,
	.bb-scholar-card__link:focus-visible {
		translate: 0 0;
	}

	.bb-scholar-profile__halo {
		animation: none;
	}

	/* awardees.js already declines to start a transition under reduced motion,
	   so this is a backstop, not the mechanism. Scoped to these four names
	   rather than ( * ): this stylesheet loads on one page, but ( * ) would
	   still reach the site-wide cross-document transitions declared in
	   motion.css while a visitor is on it. */
	::view-transition-group( bb-scholar-portrait ),
	::view-transition-group( bb-scholar-name ),
	::view-transition-group( bb-scholar-quote ),
	::view-transition-group( bb-scholar-page ),
	::view-transition-old( bb-scholar-page ),
	::view-transition-new( bb-scholar-page ) {
		animation-duration: 0.01ms !important;
	}
}
