/**
 * Our People.
 *
 * Flat colour, no gradients. Everything scoped under .op so it survives
 * whatever theme it lands in, and the properties themes most often hijack
 * are restated rather than assumed.
 */

.op {
	--op-ink: #111111;
	--op-primary: #0862db;
	--op-accent: #028b2c;

	--op-accent-deep: #007718;
	--op-paper: #ffffff;
	--op-wash: #f4f7fb;
	--op-rule: #e2e8f2;
	--op-muted: #5b6472;
	--op-columns: 3;
	--op-ease: cubic-bezier(.22, 1, .36, 1);

	box-sizing: border-box;
	max-width: 68rem;
	margin-inline: auto;
	font-family: inherit;
	color: var(--op-ink);
}

.op *, .op *::before, .op *::after { box-sizing: inherit; }
.op img { max-width: 100%; display: block; }

.op button {
	font-family: inherit;
	margin: 0;
	-webkit-appearance: none;
	appearance: none;
}

/* ---- Heading ---- */

.op-head {
	margin-bottom: 1.75rem;
	text-align: var(--op-head-align, center);
}

.op-head--left { --op-head-align: left; }
.op-head--right { --op-head-align: right; }
.op-head--center { --op-head-align: center; }

.op .op-heading {
	margin: 0;
	padding: 0;
	font-family: var(--op-head-font, inherit);
	font-size: var(--op-head-size, clamp(1.6rem, 4vw, 2.25rem));
	font-weight: 700;
	letter-spacing: -.03em;
	line-height: 1.15;
	color: var(--op-head-colour, var(--op-ink));
}

/* The serif on the cards is a deliberate contrast against the letterspaced
   caps beneath it. Offered for the heading too, so a title can match. */
.op-head--serif { --op-head-font: Georgia, "Times New Roman", serif; }

.op .op-intro {
	margin: .7rem 0 0;
	max-width: 34rem;
	font-size: .9375rem;
	color: var(--op-muted);
}

.op-head--center .op-intro { margin-inline: auto; }
.op-head--right .op-intro { margin-left: auto; }

/* ---- The list ---- */

.op-list {
	display: grid;
	grid-template-columns: repeat(var(--op-columns), minmax(0, 1fr));
	gap: 1.75rem 1.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.op-person { margin: 0; text-align: center; }

/* ---- Photo ---- */

.op .op-photo {
	display: block;
	position: relative;
	width: 100%;
	margin: 0 0 .9rem;
	padding: 0;
	border: 0;
	border-radius: 12px;
	background: var(--op-wash);
	overflow: hidden;
}

.op .op-photo--button { cursor: pointer; }
.op .op-photo--button:focus-visible { outline: 3px solid var(--op-primary); outline-offset: 3px; }

.op .op-img,
.op .op-initials {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center top;
	transition: transform .5s var(--op-ease);
}

/* Photos are cropped to a shared shape, so a page of snapshots taken on
   different phones still lines up. */
.op-shape--portrait .op-photo { aspect-ratio: 4 / 5; }
.op-shape--square .op-photo { aspect-ratio: 1 / 1; }
.op-shape--wide .op-photo { aspect-ratio: 4 / 3; }

.op-shape--circle .op-photo {
	aspect-ratio: 1 / 1;
	border-radius: 50%;
	max-width: 14rem;
	margin-inline: auto;
}

/* Initials, for the people who never send a photo. A tidy monogram reads as
   deliberate; a grey silhouette reads as broken. */
.op .op-initials {
	display: grid;
	place-items: center;
	background: var(--op-ink);
	font-size: clamp(1.75rem, 5vw, 2.75rem);
	font-weight: 700;
	letter-spacing: .04em;
	color: #fff;
}

.op .op-photo--button:hover .op-img { transform: scale(1.04); }

.op .op-more {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	padding: .55rem;
	background: var(--op-ink);
	font-size: .75rem;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: #fff;
	opacity: 0;
	transform: translateY(100%);
	transition: opacity .25s, transform .25s var(--op-ease);
}

.op .op-photo--button:hover .op-more,
.op .op-photo--button:focus-visible .op-more { opacity: 1; transform: none; }

/* ---- Details ---- */

.op .op-name {
	margin: 0;
	padding: 0;
	font-size: 1.0625rem;
	font-weight: 700;
	letter-spacing: -.015em;
	line-height: 1.3;
	color: var(--op-ink);
}

.op .op-role {
	margin: .2rem 0 0;
	font-size: .75rem;
	font-weight: 700;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--op-accent-deep);
}

.op .op-blurb {
	margin: .5rem 0 0;
	font-size: .875rem;
	line-height: 1.55;
	color: var(--op-muted);
}

.op .op-contact { margin: .35rem 0 0; font-size: .8125rem; }
.op .op-contact a { color: var(--op-primary); text-decoration: none; }
.op .op-contact a:hover { text-decoration: underline; }

.op .op-socials {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: .4rem;
	margin: .6rem 0 0;
}

.op .op-social {
	padding: .2rem .55rem;
	border: 1px solid var(--op-rule);
	border-radius: 999px;
	font-size: .6875rem;
	font-weight: 700;
	color: var(--op-muted);
	text-decoration: none;
	transition: background-color .18s, color .18s, border-color .18s;
}

.op .op-social:hover { background: var(--op-ink); border-color: var(--op-ink); color: #fff; }

.op .op-link { margin: .5rem 0 0; font-size: .8125rem; }
.op .op-link a { color: var(--op-primary); font-weight: 700; }

/* ---- Row layout ---- */

.op--row .op-list { grid-template-columns: minmax(0, 1fr); gap: 1.25rem; }

.op--row .op-person {
	display: flex;
	align-items: flex-start;
	gap: 1.25rem;
	padding-bottom: 1.25rem;
	border-bottom: 1px solid var(--op-rule);
	text-align: left;
}

.op--row .op-person:last-child { border-bottom: 0; padding-bottom: 0; }
.op--row .op-photo { flex: 0 0 8rem; width: 8rem; margin-bottom: 0; }
.op--row .op-detail { flex: 1; min-width: 0; padding-top: .2rem; }
.op--row .op-socials { justify-content: flex-start; }

/* ---- Compact ---- */

.op--compact .op-blurb,
.op--compact .op-socials,
.op--compact .op-contact,
.op--compact .op-link { display: none; }

.op--compact .op-list { gap: 1.25rem 1rem; }

/* ---- Bio panel ---- */

.op-sheet {
	position: fixed;
	inset: 0;
	z-index: 99999;
	display: grid;
	place-items: center;
	padding: 1.25rem;
}

.op-sheet[hidden] { display: none; }

.op-sheet-veil {
	position: absolute;
	inset: 0;
	background: rgba(17, 17, 17, .64);
	animation: opVeil .25s ease both;
}

@keyframes opVeil { from { opacity: 0; } to { opacity: 1; } }

.op-sheet-card {
	position: relative;
	width: 100%;
	max-width: 30rem;
	max-height: 88vh;
	overflow-y: auto;
	padding: 1.9rem;
	background: var(--op-paper);
	border-radius: 16px;
	animation: opCard .32s var(--op-ease) both;
}

@keyframes opCard {
	from { opacity: 0; transform: translateY(14px) scale(.98); }
	to { opacity: 1; transform: none; }
}

.op-sheet-x {
	position: absolute;
	top: .75rem;
	right: .75rem;
	width: 2rem;
	height: 2rem;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: var(--op-wash);
	font-size: 1.4rem;
	line-height: 1;
	color: var(--op-muted);
	cursor: pointer;
}

.op-sheet-x:hover { background: var(--op-ink); color: #fff; }
.op-sheet-x:focus-visible { outline: 2px solid var(--op-primary); outline-offset: 2px; }

.op-sheet-photo {
	width: 6rem;
	height: 6rem;
	margin: 0 auto 1rem;
	border-radius: 50%;
	object-fit: cover;
	object-position: center top;
}

.op-sheet-initials {
	display: grid;
	place-items: center;
	width: 6rem;
	height: 6rem;
	margin: 0 auto 1rem;
	border-radius: 50%;
	background: var(--op-ink);
	font-size: 2rem;
	font-weight: 700;
	color: #fff;
}

.op-sheet-body { text-align: center; }

.op-sheet-body h3 {
	margin: 0;
	padding: 0;
	font-size: 1.35rem;
	font-weight: 700;
	letter-spacing: -.02em;
	color: var(--op-ink);
}

.op-sheet-body .op-sheet-role {
	margin: .25rem 0 1.1rem;
	font-size: .75rem;
	font-weight: 700;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--op-accent-deep);
}

.op-sheet-body .op-sheet-text {
	margin: 0;
	font-size: .9375rem;
	line-height: 1.65;
	text-align: left;
	color: var(--op-muted);
	white-space: pre-wrap;
}

.op-setup {
	max-width: 40rem;
	margin-inline: auto;
	padding: .9rem 1.1rem;
	border-left: 3px solid #0862db;
	background: #eef4fe;
	font-size: .9375rem;
	color: #111111;
}

/* ---- Responsive ---- */

@media (max-width: 60rem) {
	.op-list { grid-template-columns: repeat(min(var(--op-columns), 3), minmax(0, 1fr)); }
}

@media (max-width: 44rem) {
	.op-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.op--row .op-person { flex-direction: column; align-items: center; text-align: center; }
	.op--row .op-photo { flex-basis: auto; width: 10rem; }
	.op--row .op-socials { justify-content: center; }
}

@media (max-width: 26rem) {
	.op-list { grid-template-columns: minmax(0, 1fr); }
	.op-sheet-card { padding: 1.4rem 1.15rem; }
}

@media (prefers-reduced-motion: reduce) {
	.op *, .op *::before, .op *::after {
		animation: none !important;
		transition-duration: .01ms !important;
	}
}

/* ---- Whoever heads the unit ----
   Given the full width of the row and set beside their photo rather than
   under it. On a departmental page the first question is who to speak to,
   and a card the same size as everyone else's does not answer it. */

.op--grid .op-person--lead {
	grid-column: 1 / -1;
	display: flex;
	align-items: center;
	gap: 1.75rem;
	padding-bottom: 1.5rem;
	margin-bottom: .25rem;
	border-bottom: 2px solid var(--op-ink);
	text-align: left;
}

.op--grid .op-person--lead .op-photo {
	flex: 0 0 11rem;
	width: 11rem;
	margin-bottom: 0;
}

.op--grid .op-person--lead .op-detail { flex: 1; min-width: 0; }

.op--grid .op-person--lead .op-name {
	font-size: clamp(1.35rem, 3vw, 1.75rem);
	letter-spacing: -.03em;
}

.op--grid .op-person--lead .op-role { font-size: .8125rem; }

.op--grid .op-person--lead .op-blurb {
	max-width: 34rem;
	font-size: .9375rem;
}

.op--grid .op-person--lead .op-socials { justify-content: flex-start; }

/* In a row layout everyone already sits this way, so the lead only needs
   the rule beneath them to set them apart. */
.op--row .op-person--lead { border-bottom-width: 2px; border-bottom-color: var(--op-ink); }
.op--row .op-person--lead .op-photo { flex-basis: 10rem; width: 10rem; }

/* Compact hides the detail, so the lead is marked by size alone. */
.op--compact .op-person--lead .op-photo { outline: 3px solid var(--op-ink); outline-offset: 3px; }

@media (max-width: 44rem) {
	.op--grid .op-person--lead {
		flex-direction: column;
		align-items: center;
		text-align: center;
	}

	.op--grid .op-person--lead .op-photo { flex-basis: auto; width: 12rem; }
	.op--grid .op-person--lead .op-socials { justify-content: center; }
}

/* ==========================================================================
   Tall cards: the photo fades into a panel of brand colour, and the text
   sits on that panel.

   The fade is doing real work here, not decoration. Text laid straight over
   a photograph is legible or not depending on what the photographer framed;
   a solid panel underneath guarantees it, whatever anyone uploads.
   ========================================================================== */

.op--cards {
	--op-panel: var(--op-primary);
	--op-card-radius: 14px;
	--op-veil: 26%;
}

/* The brand green measures 4.44:1 against white, just under what small text
   needs, so the green panel uses a deepened shade. Nobody can see the
   difference; everybody can read the name. */
.op-tone--accent.op--cards { --op-panel: #007f20; }
.op-tone--ink.op--cards { --op-panel: var(--op-ink); }

.op--cards .op-list {
	grid-template-columns: repeat(var(--op-columns), minmax(0, 1fr));
	gap: 1.5rem 1.25rem;
	align-items: stretch;
}

.op--cards .op-person {
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	min-height: 26rem;
	border-radius: var(--op-card-radius);
	background: var(--op-panel);
	overflow: hidden;
	text-align: center;
}

/* The photo fills the card and the panel rises over it. */
/* The card defines the shape, so every shape rule is undone here rather than
   partly undone. Leaving max-width behind from the circle setting shrank the
   photo to a disc floating in the middle of the card — a card layout should
   not care what the shape setting says. */
.op--cards .op-photo,
.op--cards.op-shape--circle .op-photo,
.op--cards.op-shape--square .op-photo,
.op--cards.op-shape--wide .op-photo,
.op--cards.op-shape--portrait .op-photo {
	position: absolute;
	inset: 0;
	width: 100%;
	max-width: none;
	height: auto;
	margin: 0;
	margin-inline: 0;
	border-radius: 0;
	background: none;
	aspect-ratio: auto;
}

.op--cards .op-img,
.op--cards .op-initials {
	width: 100%;
	height: 100%;
	max-width: none;
	border-radius: 0;
	object-fit: cover;
	object-position: center top;
}

.op--mono .op-img { filter: grayscale(1) contrast(1.05); }

/* Colour returns on hover: a small reward for looking closer, and it makes a
   grid of monochrome portraits feel alive rather than archival. */
.op--cards.op--mono .op-person:hover .op-img,
.op--cards.op--mono .op-person:focus-within .op-img { filter: grayscale(0); }

.op--cards .op-photo::after {
	content: "";
	position: absolute;
	inset: 0;
	/* --op-veil is how much of the card ends up solid colour. The fade runs
	   for twenty points above that, so the colour arrives under the chin
	   rather than across the face. Lower it and you see more of the person;
	   raise it and there is more room for a long name or a third line. */
	background:
		linear-gradient(
			to bottom,
			rgba(255, 255, 255, .38) 0%,
			rgba(255, 255, 255, 0) 18%,
			transparent calc(80% - var(--op-veil, 26%)),
			var(--op-panel) calc(100% - var(--op-veil, 26%)),
			var(--op-panel) 100%
		);
	pointer-events: none;
}

.op--cards .op-initials {
	width: 100%;
	height: 100%;
	background: var(--op-panel);
	font-size: 3.5rem;
}

.op--cards .op-detail {
	position: relative;
	z-index: 2;
	padding: 0 1.15rem 1.35rem;
}

.op--cards .op-name {
	margin: 0;
	font-family: Georgia, "Times New Roman", serif;
	font-size: 1.375rem;
	font-weight: 700;
	letter-spacing: -.01em;
	color: #fff;
}

.op--cards .op-role {
	margin: .3rem 0 0;
	font-size: .6875rem;
	font-weight: 600;
	letter-spacing: .22em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, .92);
}

.op--cards .op-blurb {
	margin: .65rem 0 0;
	font-size: .8125rem;
	line-height: 1.5;
	color: rgba(255, 255, 255, .9);
}

.op--cards .op-contact { color: rgba(255, 255, 255, .9); }
.op--cards .op-contact a,
.op--cards .op-link a { color: #fff; text-decoration: underline; }

/* Icons stay at full white. At the sizes these are drawn, anything less
   fails contrast against the panel — the numbers are not close. */
.op--cards .op-socials {
	justify-content: center;
	gap: .85rem;
	margin-top: .9rem;
}

.op--cards .op-social {
	padding: 0;
	border: 0;
	border-radius: 0;
	color: #fff;
	opacity: .95;
	transition: opacity .18s, transform .18s var(--op-ease);
}

.op--cards .op-social:hover { background: none; opacity: 1; transform: translateY(-2px); }
.op--cards .op-social:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

.op-social--icon svg { display: block; width: 1.15rem; height: 1.15rem; }

.op--cards .op-photo--button { cursor: pointer; }

/* "Read more" would sit on top of the name here, so the whole panel is the
   affordance instead and the label is not needed. */
.op--cards .op-more { display: none; }

/* The unit head gets a taller card and a rule, rather than the full-width
   treatment the grid layout uses — a row of tall cards should stay a row. */
.op--cards .op-person--lead {
	grid-column: auto;
	display: flex;
	min-height: 28rem;
	padding-bottom: 0;
	margin-bottom: 0;
	border-bottom: 0;
	outline: 3px solid var(--op-ink);
	outline-offset: 3px;
	text-align: center;
}

.op--cards .op-person--lead .op-photo { flex: none; width: 100%; }
.op--cards .op-person--lead .op-name { font-size: 1.5rem; }
.op--cards .op-person--lead .op-socials { justify-content: center; }

@media (max-width: 60rem) {
	.op--cards .op-list { grid-template-columns: repeat(min(var(--op-columns), 3), minmax(0, 1fr)); }
}

@media (max-width: 44rem) {
	.op--cards .op-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.op--cards .op-person { min-height: 22rem; }
	.op--cards .op-name { font-size: 1.15rem; }
	.op--cards .op-person--lead { min-height: 23rem; }
}

@media (max-width: 26rem) {
	.op--cards .op-list { grid-template-columns: minmax(0, 1fr); }
	.op--cards .op-person { min-height: 24rem; }
}
