/**
 * Page section styles and long-form content.
 */

/* ---------------------------------------------------------------- prose */

.a8-prose {
	font-size: 17px;
	line-height: 1.7;
}

.a8-prose > * + * {
	margin-top: var( --a8-space-5 );
}

.a8-prose :is( h2, h3, h4, h5 ) {
	margin-top: var( --a8-space-7 );
	margin-bottom: var( --a8-space-3 );
}

/*
 * A policy or terms page is one long document: its subheads are numbered
 * sections, set small and in lilac as the reference sets them, not at the
 * display sizes the rest of the site uses for h2.
 */
.a8-prose--doc :is( h2, h3, h4, h5 ) {
	color: var( --a8-brand-ink );
	font-size: var( --a8-h5 );
	line-height: 1.2;
}

.a8-prose > :first-child {
	margin-top: 0;
}

.a8-prose img {
	border-radius: var( --a8-radius-sm );
}

.a8-prose blockquote {
	margin: var( --a8-space-6 ) 0;
	padding: var( --a8-space-5 ) var( --a8-space-6 );
	background: var( --a8-off-white );
	border-left: 4px solid var( --a8-accent );
	border-radius: 0 var( --a8-radius-sm ) var( --a8-radius-sm ) 0;
	font-size: var( --a8-h5 );
	line-height: 1.5;
}

.a8-prose blockquote p:last-child {
	margin-bottom: 0;
}

.a8-prose :is( code, kbd ) {
	padding: 2px 6px;
	background: var( --a8-off-white );
	border-radius: 4px;
	font-size: .9em;
}

.a8-prose table {
	display: block;
	overflow-x: auto;
	white-space: nowrap;
}

.a8-prose :is( th, td ) {
	padding: var( --a8-space-3 ) var( --a8-space-4 );
	border-bottom: 1px solid var( --a8-border );
	text-align: left;
}

/* ----------------------------------------------------------------- hero */

/*
 * The reference hero is a photograph under a flat black wash, with the copy on
 * the left and three portrait cards stacked on the right. Its bottom corners
 * are rounded and the lowest card hangs over the band below, so the section
 * cannot clip its own overflow.
 */
.a8-hero {
	position: relative;
	/* Above the following band, so the overhanging card stays visible. */
	z-index: 2;
	display: flex;
	align-items: center;
	padding-block: 50px;
	background: var( --a8-brand );
	background-size: cover;
	background-position: center;
	border-radius: 0;
	color: var( --a8-text-invert );
}

.a8-hero::after {
	content: '';
	position: absolute;
	inset: 0;
	border-radius: inherit;
	/* #000000AD painted at opacity .5. */
	background: rgba( 0, 0, 0, .34 );
}

/*
 * The reference crops its cover photo well to the left. That crop belongs to
 * the homepage hero — the one carrying the collage — and only makes sense at
 * the width it was chosen for, so other heroes stay centred.
 */
@media ( min-width: 901px ) {
	.a8-hero:has( .a8-hero__collage ) {
		background-position: -455px -51px;
	}
}

.a8-hero__inner {
	position: relative;
	z-index: 1;
	display: grid;
	grid-template-columns: 1fr 1fr;
	/* Without it a service page's intro ran right up to the edge of its photo. */
	column-gap: var( --a8-space-8 );
	align-items: center;
	min-height: 400px;
	width: 100%;
}

.a8-hero__content {
	/*
	 * The reference ran this column to 90% of its half. SpectraTech's own
	 * headline is 78 characters, and at 90% it broke over six lines; the full
	 * half gets it to four.
	 */
	max-width: 100%;
}

/*
 * Fluid rather than the flat 66px the rest of the h1 scale uses, for the same
 * reason: the headline is set by an editor and can be any length, and a hero
 * that grows to six lines of 66px is a wall rather than an opening.
 */
.a8-hero__title {
	color: var( --a8-text-invert );
	margin-bottom: 20px;
	font-size: clamp( 32px, 3.8vw, 56px );
	letter-spacing: -1px;
}

.a8-hero__body {
	margin-bottom: 20px;
}

.a8-hero__body p:last-child {
	margin-bottom: 0;
}

.a8-hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var( --a8-space-3 );
}

/*
 * A phone cannot fit two buttons on a line, and stacked at their own widths
 * they made a ragged pair. Full width, the way the trust panel's buttons
 * already are at this size.
 */
@media ( max-width: 620px ) {
	/* Filled and outline only: a text button is a link with an underline,
	   and stretched it put its rule on one side and its label on the other. */
	.a8-hero__actions .a8-btn:not( .a8-btn--text ) {
		width: 100%;
	}
}

.a8-hero__media img {
	border-radius: var( --a8-radius-lg );
}

/* ------------------------------------------------------------ collage */

.a8-hero__collage {
	position: relative;
	/* Indented from its half of the grid, then held to the reference's
	   502 × 517 proportions so the cards scale with the column. */
	margin-left: calc( 15% + 10px );
	aspect-ratio: 502 / 517;
}

.a8-hero__collage img {
	position: absolute;
	width: 47.6%;
	height: auto;
	aspect-ratio: 518 / 686;
	object-fit: cover;
	border-radius: var( --a8-radius-lg );
}

.a8-hero__collage img:nth-child( 1 ) {
	left: 0;
	top: 29%;
}

.a8-hero__collage img:nth-child( 2 ) {
	right: 0;
	top: 0;
}

/* Deliberately overhangs the hero, overlapping the band below. */
.a8-hero__collage img:nth-child( 3 ) {
	right: 0;
	top: 66%;
}

@media ( max-width: 900px ) {
	.a8-hero__inner {
		grid-template-columns: 1fr;
		min-height: 0;
	}

	.a8-hero__content {
		max-width: none;
	}

	/* The collage is decoration; a hero's own photo still earns its place. */
	.a8-hero__collage {
		display: none;
	}

	.a8-hero__media {
		margin-top: var( --a8-space-6 );
	}
}

/* ---------------------------------------------------------- intro strip */

/*
 * The statement that carries on from the hero: a wide, light banner rather
 * than a full-bleed navy band. An icon tile, a hairline, the statement in
 * display type with its last word in the logo's run of colour, and a company
 * photograph set into the right-hand end behind a curved edge, over two soft
 * glows of the brand blue and pink. Compact on purpose: it is a bridge
 * between the hero and the first section, not a section of its own.
 */
.a8-strip {
	position: relative;
	padding-block: clamp( 28px, 3.6vw, 52px );
	background: var( --a8-white );
}

/* The hero fades into the strip's white itself, so nothing tucks under it. */
.a8-hero + .a8-strip {
	margin-top: 0;
}

.a8-strip__banner {
	--a8-strip-photo: 36%;
	position: relative;
	display: flex;
	align-items: center;
	gap: var( --a8-space-6 );
	overflow: hidden;
	isolation: isolate;
	min-height: 184px;
	padding: 36px clamp( 28px, 4vw, 52px );
	background:
		linear-gradient( 100deg, #FBFBFE 0%, #F6F5FC 55%, #F3F1FB 100% );
	border: 1px solid #E6E3F5;
	border-radius: var( --a8-radius-panel );
	box-shadow: var( --a8-card-rest );
	transition:
		box-shadow var( --a8-t-edge ) var( --a8-ease-card ),
		border-color var( --a8-t-edge ) var( --a8-ease-card );
}

/* The copy stops short of the photograph. */
.a8-strip__banner--photo {
	padding-right: calc( var( --a8-strip-photo ) + var( --a8-space-5 ) );
}

.a8-strip__banner:hover {
	border-color: #D8D1F0;
	box-shadow: var( --a8-lift );
}

/* --- the glows ------------------------------------------------------------ */

.a8-strip__glow {
	position: absolute;
	z-index: -1;
	display: block;
	aspect-ratio: 1;
	border-radius: 50%;
	pointer-events: none;
}

/* Behind the icon tile. */
.a8-strip__glow--blue {
	top: -70%;
	left: -8%;
	width: 34%;
	background: radial-gradient( circle, rgba( 0, 147, 255, .13 ) 0%, rgba( 0, 147, 255, 0 ) 68% );
	animation: a8-bloom-a 26s ease-in-out infinite alternate;
}

/* Under the accent word, where it meets the photograph. */
.a8-strip__glow--pink {
	right: 18%;
	bottom: -95%;
	width: 42%;
	background: radial-gradient( circle, rgba( 242, 2, 93, .12 ) 0%, rgba( 123, 44, 191, .06 ) 45%, rgba( 242, 2, 93, 0 ) 70% );
	animation: a8-bloom-b 30s ease-in-out infinite alternate;
}

/* --- the icon tile and the rule -------------------------------------------- */

.a8-strip__defs {
	position: absolute;
	width: 0;
	height: 0;
}

.a8-strip__mark {
	display: grid;
	flex: none;
	place-items: center;
	width: 76px;
	height: 76px;
	background: var( --a8-white );
	border-radius: 22px;
	box-shadow:
		0 1px 2px rgba( 10, 0, 87, .06 ),
		0 14px 30px -14px rgba( 10, 0, 87, .28 );
	transition: transform var( --a8-t-edge ) var( --a8-ease-card );
}

.a8-strip__mark svg {
	width: 36px;
	height: 36px;
	/* Beats the icon's own fill="currentColor"; see the gradient in the template. */
	fill: url( #a8-strip-spectrum );
}

.a8-strip__banner:hover .a8-strip__mark {
	transform: translateY( -3px );
}

.a8-strip__rule {
	display: block;
	flex: none;
	align-self: stretch;
	width: 1px;
	margin-block: 10px;
	background: linear-gradient( 180deg, rgba( 10, 0, 87, 0 ), rgba( 10, 0, 87, .16 ) 20%, rgba( 10, 0, 87, .16 ) 80%, rgba( 10, 0, 87, 0 ) );
	transform-origin: 50% 50%;
}

/* --- the statement -------------------------------------------------------- */

.a8-strip__text {
	margin: 0;
	color: var( --a8-brand );
	font-size: clamp( 28px, 3.3vw, 50px );
	font-weight: var( --a8-weight-bold );
	line-height: 1.1;
	letter-spacing: -1.4px;
	text-wrap: balance;
}

/*
 * The closing word takes the spectrum. background-clip is the only way to run
 * a gradient through glyphs; the fallback colour means a browser without the
 * clip still shows readable pink rather than nothing. At this size the lightest
 * stop, the logo blue, is 3.2:1 on the banner, inside the 3:1 large-text rule.
 */
.a8-strip__accent {
	color: var( --a8-pink-ink );
	background: linear-gradient( 96deg, var( --a8-azure ) 0%, var( --a8-violet ) 52%, var( --a8-pink ) 100% );
	-webkit-background-clip: text;
	background-clip: text;
}

@supports ( -webkit-background-clip: text ) or ( background-clip: text ) {
	.a8-strip__accent {
		-webkit-text-fill-color: transparent;
	}
}

/* --- the photograph ------------------------------------------------------- *
 *
 * Set into the right-hand end, full height, with its left edge cut as a wide
 * arc. A tinted glass ring follows that arc just inside the banner, and a
 * brand wash lies over the lower-left of the picture where it meets the copy.
 */
.a8-strip__media {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	z-index: -1;
	width: var( --a8-strip-photo );
	overflow: hidden;
	clip-path: ellipse( 100% 128% at 100% 50% );
}

.a8-strip__img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* The team is standing: keep faces, lose floor. */
	object-position: 50% 28%;
	transform: scale( 1.02 );
	transition: transform 900ms cubic-bezier( .2, .6, .2, 1 );
}

.a8-strip__media::after {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(
		100deg,
		rgba( 123, 44, 191, .30 ) 0%,
		rgba( 242, 2, 93, .12 ) 28%,
		rgba( 10, 0, 87, 0 ) 55%
	);
	pointer-events: none;
}

/* The glass ring: the same arc, a little further in, in white over a tint. */
.a8-strip__banner--photo::after {
	content: '';
	position: absolute;
	top: -20%;
	right: calc( var( --a8-strip-photo ) - 34px );
	z-index: -1;
	width: 150px;
	height: 140%;
	border: 2px solid rgba( 255, 255, 255, .9 );
	border-right: 0;
	border-radius: 100% 0 0 100% / 50% 0 0 50%;
	background: linear-gradient( 100deg, rgba( 228, 236, 255, .55 ), rgba( 241, 233, 255, .15 ) 60%, rgba( 255, 255, 255, 0 ) );
	pointer-events: none;
	transition: transform var( --a8-t-image ) var( --a8-ease-card );
}

.a8-strip__banner:hover .a8-strip__img {
	transform: scale( 1.07 );
}

.a8-strip__banner:hover::after {
	transform: translateX( -8px );
}

/* --- the entrance --------------------------------------------------------- *
 *
 * Riding the page-wide reveal: the banner rises as every section does, then
 * the rule draws down and the photograph settles from a slight zoom, so the
 * pieces arrive in order rather than all at once.
 */
.js .a8-strip__banner.a8-reveal:not( .is-visible ) .a8-strip__rule {
	transform: scaleY( 0 );
}

.js .a8-strip__banner.a8-reveal.is-visible .a8-strip__rule {
	animation: a8-strip-rule 700ms var( --a8-ease-card ) 240ms both;
}

.js .a8-strip__banner.a8-reveal.is-visible .a8-strip__img {
	animation: a8-strip-settle 1400ms cubic-bezier( .2, .6, .2, 1 ) both;
}

@keyframes a8-strip-rule {
	from { transform: scaleY( 0 ); }
	to   { transform: scaleY( 1 ); }
}

@keyframes a8-strip-settle {
	from { transform: scale( 1.12 ); }
	to   { transform: scale( 1.02 ); }
}

@media ( prefers-reduced-motion: reduce ) {
	.a8-strip__glow {
		animation: none;
	}

	.js .a8-strip__banner.a8-reveal .a8-strip__rule,
	.js .a8-strip__banner.a8-reveal.is-visible .a8-strip__img {
		transform: none;
		animation: none;
	}

	.a8-strip__banner:hover .a8-strip__mark,
	.a8-strip__banner:hover .a8-strip__img,
	.a8-strip__banner:hover::after {
		transform: none;
	}
}

/* --- tablet ---------------------------------------------------------------- */

@media ( max-width: 1024px ) {
	.a8-strip__banner {
		--a8-strip-photo: 34%;
		gap: var( --a8-space-5 );
		min-height: 150px;
		padding-block: 28px;
		border-radius: var( --a8-radius-lg );
	}

	.a8-strip__mark {
		width: 60px;
		height: 60px;
		border-radius: 18px;
	}

	.a8-strip__mark svg {
		width: 28px;
		height: 28px;
	}
}

/* --- phone ----------------------------------------------------------------- *
 *
 * No room beside the statement for a picture, so it moves to the top as a
 * band whose lower edge is the same arc turned on its side, and the rule
 * goes: the tile and the statement sit side by side under it.
 */
@media ( max-width: 767px ) {
	.a8-strip__banner,
	.a8-strip__banner--photo {
		flex-wrap: wrap;
		gap: var( --a8-space-4 );
		min-height: 0;
		padding: 24px;
	}

	.a8-strip__banner--photo {
		padding-top: calc( 42vw + 20px );
	}

	.a8-strip__media {
		top: 0;
		bottom: auto;
		left: 0;
		width: 100%;
		height: 42vw;
		clip-path: ellipse( 130% 100% at 50% 0% );
	}

	.a8-strip__banner--photo::after {
		display: none;
	}

	.a8-strip__rule {
		display: none;
	}

	.a8-strip__mark {
		width: 52px;
		height: 52px;
		border-radius: 16px;
	}

	.a8-strip__mark svg {
		width: 26px;
		height: 26px;
	}

	.a8-strip__text {
		flex: 1 1 200px;
		font-size: clamp( 26px, 7.4vw, 34px );
	}

	.a8-strip__glow--blue {
		top: auto;
		bottom: -40%;
		width: 80%;
	}

	.a8-strip__glow--pink {
		right: -30%;
		width: 90%;
	}
}

/* --------------------------------------------------------- service group */

.a8-servicegroup + .a8-servicegroup {
	margin-top: var( --a8-space-8 );
}

.a8-servicegroup__intro {
	margin-bottom: var( --a8-space-6 );
}

/* --------------------------------------------------------------- stats */

.a8-stats {
	display: grid;
	gap: var( --a8-space-6 );
	grid-template-columns: repeat( auto-fit, minmax( 180px, 1fr ) );
}

/* --------------------------------------------------------------- meta */

.a8-card__meta {
	margin: 0;
	color: var( --a8-text-muted );
	font-size: 13px;
	letter-spacing: .02em;
}

.a8-card__meta a {
	color: inherit;
	text-decoration: none;
}

/* ---------------------------------------------------------- ticklist */

.a8-ticklist {
	margin: var( --a8-space-5 ) 0 0;
	padding: 0;
	list-style: none;
	display: flex;
	flex-direction: column;
	gap: var( --a8-space-3 );
}

.a8-ticklist li {
	display: flex;
	align-items: flex-start;
	gap: var( --a8-space-3 );
	margin: 0;
}

.a8-ticklist__icon {
	flex: none;
	width: 22px;
	height: 22px;
	padding: 3px;
	background: var( --a8-tint );
	border-radius: 50%;
	color: var( --a8-brand );
}

/* ---------------------------------------------------------- offices */

/*
 * Contact block: copy on the left, the enquiry form on the right, inset from
 * the middle as the reference insets it.
 */
.a8-contact {
	display: grid;
	grid-template-columns: 1fr 1fr;
	align-items: start;
}

.a8-contact__form {
	padding-left: 120px;
}

/* The reference's contact fields sit on off-white rather than white. */
.a8-contact .a8-input {
	padding: 13px 22px;
	background: var( --a8-off-white );
	font-size: var( --a8-body );
}

.a8-contact .a8-form__grid {
	grid-template-columns: 1fr;
	gap: 20px;
}

/* Full width, and otherwise the same button as everywhere else. */
.a8-contact .a8-form__grid .a8-btn {
	width: 100%;
}

@media ( max-width: 860px ) {
	.a8-contact {
		grid-template-columns: 1fr;
		gap: var( --a8-space-7 );
	}

	.a8-contact__form {
		padding-left: 0;
	}
}

.a8-offices {
	display: grid;
	gap: var( --a8-space-5 );
	margin-top: var( --a8-space-6 );
}

/* A card like any other: the shared ground, edge and hover are applied in
   "The card design language" below. */
.a8-office {
	padding: var( --a8-card-pad );
	background: var( --a8-white );
	border: var( --a8-card-border-w ) solid var( --a8-border-card );
	border-radius: var( --a8-radius-lg );
	box-shadow: var( --a8-card-rest );
}

.a8-office__country {
	margin: 0 0 var( --a8-space-2 );
	font-size: var( --a8-h6 );
	text-transform: uppercase;
	letter-spacing: .06em;
}

.a8-office__address {
	margin: 0 0 var( --a8-space-2 );
	font-style: normal;
	font-size: var( --a8-small );
}

.a8-office__links {
	display: flex;
	flex-wrap: wrap;
	gap: var( --a8-space-4 );
	margin: 0;
	font-size: var( --a8-small );
}

/* ---------------------------------------------------------- gallery */

.a8-gallery {
	display: grid;
	gap: var( --a8-space-4 );
	grid-template-columns: repeat( auto-fill, minmax( 220px, 1fr ) );
}

.a8-gallery__item {
	margin: 0;
}

.a8-gallery__item img {
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: var( --a8-radius-sm );
}

/* -------------------------------------------------------------- CTA */

.a8-cta {
	max-width: 62ch;
	margin-inline: auto;
	text-align: center;
}

/* --------------------------------------------------- service groups */

.a8-servicegroup__title {
	margin-bottom: var( --a8-space-5 );
}

/* One card per service line, for pages that want the shape of the offer
   rather than every service in it. */
.a8-servicelines {
	margin-top: var( --a8-space-7 );
}

.a8-servicelines__list {
	margin: 0;
	padding: 0;
	color: var( --a8-brand );
	font-size: var( --a8-small );
	line-height: 1.8;
	list-style: none;
}

.a8-servicelines__list li {
	position: relative;
	padding-left: 16px;
}

.a8-servicelines__list li::before {
	content: '';
	position: absolute;
	top: .7em;
	left: 0;
	width: 6px;
	height: 6px;
	background: var( --a8-tone, var( --a8-pink-ink ) );
	border-radius: 50%;
}

.a8-servicegroup + .a8-servicegroup {
	margin-top: var( --a8-space-8 );
	padding-top: var( --a8-space-8 );
	border-top: 1px solid var( --a8-border );
}

/* ----------------------------------------------------- numbered steps */

.a8-steps {
	counter-reset: a8-step;
	margin: var( --a8-space-6 ) 0 0;
	padding: 0;
	list-style: none;
	display: grid;
	gap: var( --a8-space-5 );
}

.a8-steps__item {
	display: flex;
	gap: var( --a8-space-5 );
	align-items: flex-start;
	padding: var( --a8-card-pad );
	background: var( --a8-white );
	border: var( --a8-card-border-w ) solid var( --a8-border-card );
	border-radius: var( --a8-radius-lg );
	box-shadow: var( --a8-card-rest );
}

.a8-steps__num {
	flex: none;
	display: grid;
	place-items: center;
	width: 44px;
	height: 44px;
	background: var( --a8-tint );
	border-radius: 50%;
	color: var( --a8-brand );
	font-size: var( --a8-h6 );
	font-weight: var( --a8-weight-bold );
	font-variant-numeric: tabular-nums;
}

.a8-steps__title {
	margin: 0 0 var( --a8-space-2 );
	font-size: var( --a8-h5 );
}

.a8-steps__item p {
	margin: 0;
}

@media ( min-width: 900px ) {
	.a8-steps {
		grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
	}
}

/* ---------------------------------------------------------- fact list */

.a8-factlist {
	margin: 0;
	display: grid;
	gap: var( --a8-space-3 );
}

/* The card's heading sat 8px off the first label, closer than the labels sit
   to each other. */
.a8-office__country + .a8-factlist {
	margin-top: var( --a8-space-4 );
}

.a8-factlist dt {
	color: var( --a8-text-muted );
	font-size: 12px;
	text-transform: uppercase;
	letter-spacing: .07em;
}

.a8-factlist dd {
	margin: 0 0 var( --a8-space-2 );
	font-weight: var( --a8-weight-medium );
	color: var( --a8-brand );
}

/* --------------------------------------------------------- service hero */

/*
 * Service hero: copy on the left, a rounded photo on the right, on a ground
 * darker than the rest of the site. No cover photo, so no wash over it.
 */
.a8-hero--service {
	background: var( --a8-brand-darkest );
	border-radius: 0;
}

.a8-hero--service::after {
	content: none;
}

.a8-hero--service .a8-hero__content {
	max-width: none;
}

.a8-hero--service .a8-hero__title {
	font-size: var( --a8-h2 );
	line-height: var( --a8-h2-lh );
}

.a8-hero--service .a8-hero__lede {
	max-width: 26ch;
	margin-bottom: var( --a8-space-5 );
	font-size: 22px;
	line-height: 1.5;
	letter-spacing: -.3px;
}

.a8-hero--service .a8-hero__media img {
	width: 100%;
	border-radius: var( --a8-radius-panel );
}

/*
 * One service's photo was never captured by the crawler. Without it the copy
 * takes the whole row instead of leaving half the hero empty, held to a
 * readable measure.
 */
.a8-hero:not( .a8-hero--cinema ) .a8-hero__inner:not( :has( .a8-hero__media, .a8-hero__collage ) ) {
	grid-template-columns: 1fr;
}

.a8-hero:not( .a8-hero--cinema ) .a8-hero__inner:not( :has( .a8-hero__media, .a8-hero__collage ) ) .a8-hero__content {
	max-width: 62ch;
}

.a8-hero--service .a8-breadcrumbs {
	margin-bottom: var( --a8-space-5 );
	color: var( --a8-text-invert-muted );
}

.a8-hero--service .a8-breadcrumbs a,
.a8-hero--service .a8-breadcrumbs span {
	color: var( --a8-text-invert-muted );
}

.a8-hero--service .a8-breadcrumbs a:hover {
	color: var( --a8-text-invert );
}

/* ---------------------------------------------------- service sections */

/*
 * What this service covers. These were stripped back to bare rows — no ground,
 * no border, no padding — while still carrying the card's hover edge, which
 * then drew itself along the bottom of the text with nothing between them.
 * They are ordinary cards now, the same as Explore our core features.
 */
.a8-service__benefits .a8-grid {
	margin-top: var( --a8-space-6 );
}

/* =========================================================================
 * Events — the /events/ grid, the tiles, and an event page
 * ====================================================================== */

/*
 * Image-led tiles. The date, category and title are always legible over a
 * gradient scrim; the short description and the prompt slide up on hover or
 * keyboard focus.
 *
 * The reveal is gated behind `hover: hover` further down, so a phone gets the
 * description permanently instead of hiding it behind a gesture it cannot
 * make. Everything above that media query is the mobile state.
 */

.a8-events-grid {
	display: grid;
	gap: var( --a8-space-5 );
	grid-template-columns: repeat( 3, minmax( 0, 1fr ) );
	margin-top: var( --a8-space-7 );
}

@media ( max-width: 1024px ) {
	.a8-events-grid {
		grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
	}

	/* Three highlights in two columns left one tile alone beside a hole; the
	   odd one out takes the row as a wide banner instead. */
	.a8-events-grid > :last-child:nth-child( odd ) {
		grid-column: 1 / -1;
	}
}

@media ( max-width: 620px ) {
	.a8-events-grid {
		grid-template-columns: 1fr;
	}
}

.a8-event-card {
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	overflow: hidden;
	min-height: 380px;
	background: var( --a8-brand-deep );
	/* The card's own edge and resting shadow; the hover is the shared one. */
	border: var( --a8-card-border-w ) solid var( --a8-border-card );
	border-radius: var( --a8-radius-lg );
	box-shadow: var( --a8-card-rest );
	color: var( --a8-text-invert );
	isolation: isolate;
}

.a8-event-card__media {
	position: absolute;
	inset: 0;
	z-index: -2;
}

.a8-event-card__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform var( --a8-t-image ) cubic-bezier( .2, .6, .2, 1 );
}

.a8-event-card__img--empty {
	display: block;
	background: var( --a8-spectrum-soft ), var( --a8-brand );
}

.a8-event-card:hover .a8-event-card__img,
.a8-event-card:focus-within .a8-event-card__img {
	transform: scale( 1.06 );
}

/*
 * The scrim carries the text contrast, so it has to be opaque enough on its
 * own: white on the darkest stop is 15:1, and the tile never depends on how
 * light the photograph behind it happens to be.
 */
.a8-event-card::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: -1;
	background: linear-gradient(
		to top,
		rgba( 8, 0, 48, .94 ) 0%,
		rgba( 8, 0, 48, .88 ) 34%,
		rgba( 8, 0, 48, .55 ) 62%,
		rgba( 8, 0, 48, .18 ) 100%
	);
	transition: opacity var( --a8-transition );
}

/*
 * Not positioned, so the title link's overlay resolves to the whole tile. It
 * was `relative`, which trapped the overlay inside the text block: the
 * photograph — two thirds of the tile — and "See the photos" were dead. The
 * text still paints over the scrim, which sits at z-index -1 in the tile.
 */
.a8-event-card__body {
	padding: var( --a8-card-pad );
}

.a8-event-card__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var( --a8-space-2 );
	margin: 0 0 var( --a8-space-2 );
	color: var( --a8-text-invert );
	font-size: 13px;
	font-weight: var( --a8-weight-medium );
	letter-spacing: .01em;
}

.a8-event-card__cat {
	padding: 3px 10px;
	background: rgba( 255, 255, 255, .16 );
	border-radius: var( --a8-radius-pill );
	font-size: 12px;
	font-weight: var( --a8-weight-bold );
	text-transform: uppercase;
	letter-spacing: .04em;
}

.a8-event-card__title {
	margin: 0;
	font-size: var( --a8-h4 );
	line-height: 1.2;
	letter-spacing: -.4px;
}

.a8-event-card__title a {
	color: var( --a8-text-invert );
	text-decoration: none;
}

/* One tab stop per tile: the title link covers the whole card. */
.a8-event-card__title a::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 2;
	border-radius: inherit;
}

.a8-event-card__title a:hover,
.a8-event-card__title a:focus-visible {
	color: var( --a8-pink-light );
}

.a8-event-card__summary {
	margin: var( --a8-space-3 ) 0 0;
	color: var( --a8-text-invert-muted );
	font-size: var( --a8-small );
	line-height: 1.55;
}

.a8-event-card__more {
	display: flex;
	align-items: center;
	gap: var( --a8-space-2 );
	margin: var( --a8-space-4 ) 0 0;
	color: var( --a8-pink-light );
	font-size: 12px;
	font-weight: var( --a8-weight-bold );
	text-transform: uppercase;
	letter-spacing: .04em;
}

/* The same round arrow as the feature cards, in white glass on the photo. */
.a8-event-card__more svg {
	flex: none;
	box-sizing: content-box;
	width: 16px;
	height: 16px;
	padding: 8px;
	background: rgba( 255, 255, 255, .16 );
	border-radius: 50%;
	fill: currentColor;
	transition:
		transform var( --a8-t-edge ) var( --a8-ease-card ),
		background-color var( --a8-t-edge ) var( --a8-ease-card ),
		color var( --a8-t-edge ) var( --a8-ease-card );
}

/* Navy on the light pink is 9:1. */
.a8-event-card:is( :hover, :focus-within ) .a8-event-card__more svg {
	background: var( --a8-pink-light );
	color: var( --a8-brand );
	transform: translateX( 4px );
}

.a8-event-card__count {
	margin-left: auto;
	color: var( --a8-text-invert-muted );
	font-weight: var( --a8-weight-normal );
	text-transform: none;
	letter-spacing: 0;
}

/*
 * Pointer devices get the reveal. Touch screens keep the description on show,
 * which is why the collapsed state lives here rather than in the base rules.
 */
@media ( hover: hover ) and ( pointer: fine ) {
	.a8-event-card__reveal {
		display: grid;
		grid-template-rows: 0fr;
		opacity: 0;
		transition: grid-template-rows var( --a8-transition ), opacity var( --a8-transition );
	}

	.a8-event-card__reveal-inner {
		overflow: hidden;
		min-height: 0;
	}

	.a8-event-card:hover .a8-event-card__reveal,
	.a8-event-card:focus-within .a8-event-card__reveal {
		grid-template-rows: 1fr;
		opacity: 1;
	}
}

/*
 * Reduced motion keeps the reveal — it carries information — but drops the
 * movement that would otherwise announce it.
 */
@media ( prefers-reduced-motion: reduce ) {
	.a8-event-card,
	.a8-event-card__img,
	.a8-event-card__reveal,
	.a8-event-card::before {
		transition: none;
	}

	.a8-event-card:hover,
	.a8-event-card:focus-within,
	.a8-event-card:hover .a8-event-card__img,
	.a8-event-card:focus-within .a8-event-card__img {
		transform: none;
	}
}

/* ------------------------------------------------------- category chips */

.a8-event-filters {
	display: flex;
	flex-wrap: wrap;
	gap: var( --a8-space-2 );
}

.a8-chip {
	display: inline-block;
	padding: 8px 18px;
	background: var( --a8-white );
	border: 1px solid var( --a8-border );
	border-radius: var( --a8-radius-pill );
	color: var( --a8-brand );
	font-size: var( --a8-small );
	font-weight: var( --a8-weight-medium );
	text-decoration: none;
	transition: background var( --a8-transition ), border-color var( --a8-transition ), color var( --a8-transition );
}

.a8-chip:hover,
.a8-chip:focus-visible {
	background: var( --a8-tint );
	border-color: var( --a8-brand );
	color: var( --a8-brand );
}

.a8-chip.is-current {
	background: var( --a8-brand );
	border-color: var( --a8-brand );
	color: var( --a8-text-invert );
}

.a8-chip--sm {
	padding: 3px 12px;
	font-size: 12px;
	font-weight: var( --a8-weight-bold );
	text-transform: uppercase;
	letter-spacing: .04em;
}

/* ------------------------------------------------------------ event page */

.a8-pagehead--events,
.a8-pagehead--event {
	background: var( --a8-brand );
	color: var( --a8-text-invert );
}

.a8-pagehead--events .a8-pagehead__title,
.a8-pagehead--event .a8-pagehead__title {
	color: var( --a8-text-invert );
}

.a8-pagehead--events .a8-pagehead__intro,
.a8-pagehead--event .a8-pagehead__intro {
	color: var( --a8-text-invert-muted );
}

.a8-pagehead--events .a8-breadcrumbs a,
.a8-pagehead--event .a8-breadcrumbs a,
.a8-pagehead--events .a8-breadcrumbs span,
.a8-pagehead--event .a8-breadcrumbs span,
.a8-pagehead--events .a8-breadcrumbs li::after,
.a8-pagehead--event .a8-breadcrumbs li::after {
	color: var( --a8-text-invert-muted );
}

.a8-pagehead--events .a8-breadcrumbs a:hover,
.a8-pagehead--event .a8-breadcrumbs a:hover {
	color: var( --a8-text-invert );
}

.a8-event__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var( --a8-space-3 );
	margin: 0 0 var( --a8-space-3 );
	color: var( --a8-text-invert-muted );
	font-size: var( --a8-small );
}

.a8-event__meta .a8-chip {
	background: rgba( 255, 255, 255, .16 );
	border-color: transparent;
	color: var( --a8-text-invert );
}

.a8-event__meta .a8-chip:hover,
.a8-event__meta .a8-chip:focus-visible {
	background: var( --a8-white );
	color: var( --a8-brand );
}

/* The hero photo lifts out of the purple band into the white below it. */
.a8-event__hero {
	margin-top: calc( var( --a8-space-8 ) * -1 );
}

/* The band keeps its own bottom padding clear of the photo's overlap, or the
   photo lands on the last line of the intro. */
.a8-pagehead--event:has( + .a8-event__hero ) {
	padding-bottom: calc( var( --a8-space-8 ) + var( --a8-space-7 ) );
}

.a8-event__hero-img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 9;
	object-fit: cover;
	border-radius: var( --a8-radius-lg );
	box-shadow: var( --a8-shadow );
}

/*
 * The event gallery, which is the one grid on the site that does not square
 * its pictures off.
 *
 * HR's event photographs arrive in nineteen aspect ratios between 0.46 and
 * 1.78. The grid used to force every one of them into 3:2 and crop with
 * `object-fit: cover`, which on a tall portrait threw away three quarters of
 * the frame — the thing the photograph was taken for was usually in the part
 * that went.
 *
 * Columns rather than grid, because this is the one layout that genuinely
 * needs masonry: CSS grid cannot pack rows of mixed heights without either
 * cropping to a common shape or leaving holes under the short ones. Multi-
 * column does it natively, with no JavaScript and no measuring pass. The
 * trade is reading order — a screen reader walks down each column rather than
 * across the rows — which for an unlabelled set of photographs from one day
 * costs nothing.
 */
.a8-gallery--masonry {
	display: block;
	columns: 4 260px;
	column-gap: var( --a8-space-4 );
	margin-top: var( --a8-space-6 );
}

.a8-gallery--masonry .a8-gallery__item {
	/* Column layout has no row gap of its own. */
	margin: 0 0 var( --a8-space-4 );
	break-inside: avoid;
	/* Safari still wants the old name for it. */
	-webkit-column-break-inside: avoid;
}

/*
 * The figure carries the picture's own ratio, written out by the template, and
 * the image fills it exactly. `object-fit: fill` is right here and nowhere
 * else on the site: the box is already the shape of the file, so filling it
 * cannot distort anything, and it stops the inherited `cover` from cropping.
 */
.a8-gallery--masonry .a8-gallery__item img {
	display: block;
	width: 100%;
	height: 100%;
	aspect-ratio: inherit;
	object-fit: fill;
	border-radius: var( --a8-radius );
	transition: transform var( --a8-t-image ) cubic-bezier( .2, .6, .2, 1 ), box-shadow var( --a8-transition );
}

.a8-gallery--masonry .a8-gallery__item:hover img {
	transform: translateY( -3px );
	box-shadow: var( --a8-lift );
}

@media ( max-width: 620px ) {
	/*
	 * One column on a phone. Two columns of a 0.46 portrait would be a pair of
	 * 80px-wide slivers.
	 */
	.a8-gallery--masonry {
		columns: 1;
	}
}

@media ( prefers-reduced-motion: reduce ) {
	.a8-gallery--masonry .a8-gallery__item:hover img {
		transform: none;
	}
}

.a8-events__all {
	margin-top: var( --a8-space-7 );
	text-align: center;
}

.a8-events__empty {
	margin-top: var( --a8-space-6 );
	color: var( --a8-text-muted );
}

/* =========================================================================
 * The two closing steps: trust, then enquiry
 *
 * They used to be one purple slab — a purple CTA band butted straight onto
 * the purple footer pitch, with a second form in it. They are now opposites:
 * a contained dark panel of reasons, then a light block where the only thing
 * to do is get in touch. The footer drops its own pitch band when a page ends
 * on the enquiry section (see a8_lead_rendered()).
 * ====================================================================== */

.a8-cta__actions {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var( --a8-space-3 );
	margin-top: var( --a8-space-6 );
}

.a8-cta__actions--start {
	justify-content: flex-start;
	margin-top: var( --a8-space-7 );
}

/* ------------------------------------------------------------ trust band */

/*
 * Contained rather than full-bleed, so it reads as an object on the page and
 * cannot merge into whatever band follows it.
 */
.a8-band {
	position: relative;
	display: grid;
	grid-template-columns: minmax( 0, 5fr ) minmax( 0, 6fr );
	gap: var( --a8-space-8 );
	align-items: center;
	overflow: hidden;
	padding: 64px;
	background: var( --a8-brand );
	border-radius: var( --a8-radius-panel );
	color: var( --a8-text-invert );
}

/* The logo's own run of colour, as a 4px edge along the top. */
.a8-band::before {
	content: '';
	position: absolute;
	inset: 0 0 auto;
	height: 4px;
	background: var( --a8-spectrum );
}

/* A soft off-centre bloom so the panel is not a flat rectangle of navy. */
.a8-band::after {
	content: '';
	position: absolute;
	right: -12%;
	bottom: -45%;
	width: 60%;
	aspect-ratio: 1;
	background: radial-gradient( circle, rgba( 232, 68, 126, .30 ) 0%, rgba( 232, 68, 126, 0 ) 68% );
	pointer-events: none;
}

.a8-band__copy,
.a8-band__points {
	position: relative;
	z-index: 1;
}

.a8-band__title {
	margin: 0 0 var( --a8-space-4 );
	color: var( --a8-text-invert );
	font-size: var( --a8-h2 );
	line-height: var( --a8-h2-lh );
	letter-spacing: -1.2px;
}

.a8-band__body {
	max-width: 46ch;
	color: var( --a8-text-invert-muted );
}

.a8-band__body p:last-child {
	margin-bottom: 0;
}

.a8-band__points {
	display: grid;
	grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
	gap: var( --a8-space-6 ) var( --a8-space-5 );
	margin: 0;
	padding: 0;
	list-style: none;
}

.a8-band__point {
	display: flex;
	gap: var( --a8-space-3 );
}

.a8-band__icon {
	display: grid;
	flex: none;
	place-items: center;
	width: 44px;
	height: 44px;
	background: rgba( 255, 255, 255, .1 );
	border-radius: 50%;
	color: var( --a8-pink-light );
}

.a8-band__icon svg {
	width: 20px;
	height: 20px;
}

.a8-band__point-title {
	margin: 0 0 4px;
	color: var( --a8-text-invert );
	font-size: var( --a8-h6 );
	font-weight: var( --a8-weight-bold );
	line-height: 1.3;
}

.a8-band__point-body {
	margin: 0;
	color: var( --a8-text-invert-muted );
	font-size: var( --a8-small );
	line-height: 1.55;
}

@media ( max-width: 1024px ) {
	.a8-band {
		grid-template-columns: 1fr;
		gap: var( --a8-space-7 );
		padding: 48px 40px;
	}
}

@media ( max-width: 620px ) {
	.a8-band {
		padding: 32px 24px;
		border-radius: var( --a8-radius-lg );
	}

	.a8-band__points {
		grid-template-columns: 1fr;
		gap: var( --a8-space-5 );
	}

	.a8-cta__actions--start .a8-btn:not( .a8-btn--text ) {
		width: 100%;
		text-align: center;
	}
}

/* ------------------------------------------------------ enquiry section */

.a8-lead {
	display: grid;
	grid-template-columns: minmax( 0, 5fr ) minmax( 0, 7fr );
	gap: var( --a8-space-8 );
	align-items: start;
}

.a8-lead__title {
	margin: 0 0 var( --a8-space-4 );
	font-size: var( --a8-h2 );
	line-height: var( --a8-h2-lh );
	letter-spacing: -1.2px;
}

.a8-lead__body {
	max-width: 46ch;
	color: var( --a8-text );
}

.a8-lead__points {
	margin-top: var( --a8-space-5 );
}

/* --------------------------------------------------- direct contact rows */

.a8-channels {
	display: grid;
	gap: var( --a8-space-4 );
	margin: var( --a8-space-7 ) 0 0;
	padding: var( --a8-space-6 ) 0 0;
	border-top: 1px solid var( --a8-border );
	list-style: none;
}

.a8-channel {
	display: flex;
	align-items: flex-start;
	gap: var( --a8-space-4 );
}

.a8-channel__icon {
	display: grid;
	flex: none;
	place-items: center;
	width: 44px;
	height: 44px;
	background: var( --a8-tint );
	border-radius: var( --a8-radius-sm );
	color: var( --a8-brand );
}

.a8-channel__icon svg {
	width: 20px;
	height: 20px;
}

.a8-channel__text {
	display: block;
	padding-top: 2px;
}

.a8-channel__label {
	display: block;
	color: var( --a8-text-muted );
	font-size: 12px;
	font-weight: var( --a8-weight-bold );
	text-transform: uppercase;
	letter-spacing: .05em;
}

.a8-channel__value {
	display: block;
	color: var( --a8-brand );
	font-size: var( --a8-h6 );
	font-style: normal;
	font-weight: var( --a8-weight-medium );
	line-height: 1.5;
	text-decoration: none;
}

/* The address link looks like the phone and email above it at rest, and
   every one of them underlines when pointed at. */
.a8-channel__value a {
	color: var( --a8-brand );
	text-decoration: none;
}

a.a8-channel__value:hover,
a.a8-channel__value:focus-visible,
.a8-channel__value a:hover,
.a8-channel__value a:focus-visible {
	color: var( --a8-brand );
	text-decoration: underline;
}

/* --------------------------------------------------------- the form card */

.a8-lead__card {
	position: relative;
	padding: var( --a8-space-7 );
	background: var( --a8-white );
	border: 1px solid var( --a8-border );
	border-radius: var( --a8-radius-lg );
	box-shadow: var( --a8-lift-strong );
}

/* Repeats the logo run along the card's top edge, tying it to the band above. */
.a8-lead__card::before {
	content: '';
	position: absolute;
	inset: 0 0 auto;
	height: 4px;
	background: var( --a8-spectrum );
	border-radius: var( --a8-radius-lg ) var( --a8-radius-lg ) 0 0;
}

.a8-lead__form-heading {
	margin: 0 0 var( --a8-space-5 );
	font-size: var( --a8-h4 );
	letter-spacing: -.4px;
}

/* The card already carries a heading, and the submit is the only thing to do. */
.a8-lead__card .a8-form button[type="submit"] {
	width: 100%;
	text-align: center;
}

.a8-lead__note {
	margin: var( --a8-space-4 ) 0 0;
	color: var( --a8-text-muted );
	font-size: var( --a8-small );
	text-align: center;
}

@media ( max-width: 1024px ) {
	.a8-lead {
		grid-template-columns: 1fr;
		gap: var( --a8-space-7 );
	}

	.a8-lead__body {
		max-width: none;
	}
}

@media ( max-width: 620px ) {
	.a8-lead__card {
		padding: var( --a8-space-5 );
	}
}

/* =========================================================================
 * Hero: the cinematic video band
 *
 * The footage is the background of the whole section, not a panel beside the
 * copy. Three layers: the video, a wash of the video's own colours that the
 * copy sits on, and a bloom that picks up the pink glow already in the plate.
 *
 * The wash is masked as well as gradient-filled. Without the mask its
 * backdrop-filter would stop at a hard vertical line, which is exactly the
 * "separate coloured box" look this replaces.
 *
 * Colours here were sampled from the video: its left third averages #C2BEC8
 * with a pink cast low-left and a cooler grey up top. The wash lifts that to
 * ~#EDEBF2 behind the copy, where the brand navy reads at 15:1 and the pink
 * eyebrow at 5.2:1.
 *
 * All motion is transform/opacity only. The global prefers-reduced-motion rule
 * in base.css collapses it; the block at the end cleans up the two cases where
 * "collapsed" would still look wrong.
 * ====================================================================== */

/*
 * The height comes from the video, not from a round number. The source is
 * 1280x720; the element below is 88% of the band's width (capped at 1500px),
 * so its natural 16:9 height is 0.88 x 0.5625 = 49.5vw. Showing 78% of that is
 * 38.6vw, which keeps the logo badge — y 12-86% of the frame, so 74% of its
 * height — whole with a little margin, and nothing more.
 *
 * The old `clamp( 560px, 46vw, 700px )` was both taller and, once the 1.22
 * transform magnified the frame, showed only 54-68% of it above 1280px: the
 * badge was being cut top and bottom at every desktop width.
 */
.a8-hero--cinema {
	position: relative;
	display: flex;
	align-items: center;
	overflow: hidden;
	min-height: clamp( 420px, 38.6vw, 660px );
	padding-block: var( --a8-space-7 );
	background: var( --a8-hero-bg );
}

/* The dark wash exists to make white copy readable over a photograph. */
.a8-hero--cinema::after {
	display: none;
}

.a8-hero__stage {
	position: absolute;
	inset: 0;
	z-index: 0;
	overflow: hidden;
	pointer-events: none;
}

/*
 * Right-aligned and narrower than the band rather than magnified: the badge
 * lands at 38-74% across because the element's own centre sits at 56%, and the
 * source is *downscaled* at every width up to about 1450 instead of being
 * blown up 1.2-1.8x. The 1500px cap stops the element outrunning the source on
 * very wide screens — 1.17x at 1920 is the worst case now.
 *
 * The uncovered strip on the left is under the opaque end of the wash, which
 * is why the band still reads as one continuous scene.
 */
.a8-hero__video-el {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: auto;
	width: min( 84%, 1500px );
	height: 100%;
	object-fit: cover;
	object-position: center;
	/*
	 * A nudge right, to put more air between the badge and the copy.
	 *
	 * `object-position` cannot do this: the element box is wider than 16:9, so
	 * cover binds on width and the only crop is vertical — the x axis is inert.
	 * The element is already flush right, so a plain translate is the one lever
	 * that moves the frame without touching its scale, the band height or the
	 * layout. 3% of the element is 2.6% of the band; the badge goes to 41-77%
	 * across and the uncovered strip on the left grows to 15%, still under the
	 * opaque end of the wash.
	 */
	transform: translateX( 11% );
}

.a8-hero__wash {
	position: absolute;
	inset: 0;
	display: block;
	background: linear-gradient(
		100deg,
		rgba( 238, 236, 243, .84 ) 0%,
		rgba( 234, 231, 240, .80 ) 26%,
		rgba( 231, 228, 238, .77 ) 42%,
		rgba( 229, 226, 236, .38 ) 55%,
		rgba( 229, 226, 236, 0 ) 70%
	);
	-webkit-backdrop-filter: blur( 17px ) saturate( 108% );
	backdrop-filter: blur( 17px ) saturate( 108% );
	/* Fades the blur out with the tint, so there is no vertical seam. */
	
	-webkit-mask-image: linear-gradient( 100deg, #000 0%, #000 32%, rgba( 0, 0, 0, .25 ) 52%, transparent 65% );
	mask-image: linear-gradient( 100deg, #000 0%, #000 32%, rgba( 0, 0, 0, .25 ) 52%, transparent 65% );
}

/* Picks up the pink glow the plate already has in its lower left. */
.a8-hero__bloom {
	position: absolute;
	bottom: -34%;
	left: -12%;
	display: block;
	width: 46%;
	aspect-ratio: 1;
	background: radial-gradient( circle, rgba( 242, 2, 93, .16 ) 0%, rgba( 242, 2, 93, 0 ) 68% );
	animation: a8-bloom-b 32s ease-in-out infinite alternate;
}

/*
 * The band's lower edge dissolves into the white page below instead of
 * stopping on a line. It was a 3px spectrum hairline, which drew a hard seam
 * between the video and the next section.
 *
 * Two ramps multiplied together: the mask fades the whole layer in from the
 * top, and the white inside it fades in again, so it eases in rather than
 * starting as a visible band, and reaches solid white exactly at the bottom,
 * where the next section's own white takes over. The light blur softens the
 * last few pixels of video under it and fades in with the same mask. Kept
 * short so the logo in the footage is never washed out.
 */
.a8-hero__edge {
	position: absolute;
	right: 0;
	bottom: 0;
	left: 0;
	z-index: 3;
	height: clamp( 44px, 5.5vw, 84px );
	background: linear-gradient( 180deg, rgba( 255, 255, 255, 0 ) 0%, rgba( 255, 255, 255, .7 ) 60%, var( --a8-white ) 100% );
	-webkit-backdrop-filter: blur( 4px );
	backdrop-filter: blur( 4px );
	-webkit-mask-image: linear-gradient( 180deg, transparent 0%, #000 100% );
	mask-image: linear-gradient( 180deg, transparent 0%, #000 100% );
	pointer-events: none;
}

.a8-hero--cinema .a8-hero__inner {
	position: relative;
	z-index: 2;
	display: block;
	min-height: 0;
}

/*
 * Capped so the column always ends left of the video's disc, not just left of
 * the wordmark. Measured against the badge box (x 30-71% of the frame) at
 * 1025, 1100, 1280 and 1440: at least 20px of clear ground at every one.
 */
/*
 * Measured against the badge box at 1025 / 1100 / 1200 / 1280 / 1366 / 1440 /
 * 1500 / 1600 / 1700 / 1920: at least 25px of clear ground at every one.
 */
.a8-hero--cinema .a8-hero__content {
	max-width: min( 35%, 420px );
}

/*
 * The column cannot widen — the logo is in the way — so the headline comes
 * down instead. At the site-wide hero size it was setting 13 characters to a
 * line over six lines, which is a ragged stack rather than a headline; this
 * lands it at 22-26 characters over three or four.
 */
.a8-hero--cinema .a8-hero__title {
	font-size: clamp( 30px, 2.8vw, 44px );
	line-height: 1.12;
}

/* --------------------------------------------- stacked, below 1025px ----
 *
 * Cover-cropping a 16:9 plate into a tall box crops it to a third of its
 * width and cuts the mark in half. The composition turns vertical instead:
 * copy on the wash at the top, the whole frame underneath, same soft join.
 */
@media ( max-width: 1024px ) {
	/*
	 * Stacked, the video is full width, so its natural 16:9 height is 56.25vw.
	 * 54vw shows 96-100% of the frame on a phone and 79% at 1024, where the cap
	 * bites — comfortably above the 74% the badge needs. Sized off the viewport
	 * rather than the hero, which the copy above it defines.
	 */
	.a8-hero--cinema {
		align-items: flex-start;
		min-height: 0;
		padding-bottom: clamp( 190px, 54vw, 430px );
	}

	.a8-hero__video-el {
		top: auto;
		right: 0;
		bottom: 0;
		left: 0;
		width: 100%;
		height: clamp( 190px, 54vw, 430px );
		/*
		 * Full width here, so the nudge would open a bare strip on the left
		 * with no wash over it. The copy sits above the video in this layout
		 * anyway, so there is nothing to move away from.
		 */
		transform: none;
	}

	.a8-hero__wash {
		background: linear-gradient(
			180deg,
			rgba( 238, 236, 243, .99 ) 0%,
			rgba( 236, 233, 242, .97 ) 34%,
			rgba( 233, 230, 240, .75 ) 50%,
			rgba( 231, 228, 238, .28 ) 62%,
			rgba( 229, 226, 236, 0 ) 74%
		);
		-webkit-mask-image: linear-gradient( 180deg, #000 0%, #000 42%, rgba( 0, 0, 0, .3 ) 58%, transparent 74% );
		mask-image: linear-gradient( 180deg, #000 0%, #000 42%, rgba( 0, 0, 0, .3 ) 58%, transparent 74% );
	}

	.a8-hero--cinema .a8-hero__content {
		max-width: none;
	}

	.a8-hero__bloom {
		bottom: -20%;
		width: 70%;
	}
}



/*
 * No backdrop-filter (Firefox before 103, older Safari): the gradient alone
 * still carries the copy, so only the blur is lost.
 */
@supports not ( ( backdrop-filter: blur( 1px ) ) or ( -webkit-backdrop-filter: blur( 1px ) ) ) {
	.a8-hero__wash {
		background: linear-gradient(
			100deg,
			rgba( 238, 236, 243, 1 ) 0%,
			rgba( 235, 232, 241, .99 ) 30%,
			rgba( 232, 229, 239, .88 ) 46%,
			rgba( 229, 226, 236, .45 ) 58%,
			rgba( 229, 226, 236, 0 ) 72%
		);
	}
}

/* ------------------------------------------------------------ light tone */

.a8-hero--light {
	background: var( --a8-hero-bg );
	color: var( --a8-text );
}

.a8-hero--light::after {
	display: none;
}

.a8-hero--light .a8-hero__title {
	color: var( --a8-brand );
}

.a8-hero--light .a8-hero__body {
	color: var( --a8-text );
	font-size: 18px;
}

/* Pink-ink is 5.2:1 on the wash; the light pink used on navy is 2:1. */
.a8-hero--light .a8-eyebrow {
	color: var( --a8-pink-ink );
}

.a8-hero--light + .a8-strip {
	margin-top: 0;
}

/* ------------------------------------------ ambient glows, no-video hero */

.a8-hero__aura {
	position: absolute;
	inset: 0;
	z-index: 1;
	overflow: hidden;
	border-radius: inherit;
	pointer-events: none;
}

.a8-hero__glow {
	position: absolute;
	display: block;
	aspect-ratio: 1;
	border-radius: 50%;
	will-change: transform;
}

.a8-hero__glow--azure {
	top: -30%;
	left: -14%;
	width: 62%;
	background: radial-gradient( circle, rgba( 0, 147, 255, .34 ) 0%, rgba( 0, 147, 255, 0 ) 66% );
	animation: a8-bloom-a 26s ease-in-out infinite alternate;
}

.a8-hero__glow--pink {
	right: -10%;
	bottom: -46%;
	width: 54%;
	background: radial-gradient( circle, rgba( 242, 2, 93, .30 ) 0%, rgba( 242, 2, 93, 0 ) 66% );
	animation: a8-bloom-b 34s ease-in-out infinite alternate;
}

@keyframes a8-bloom-a {
	from { transform: translate3d( 0, 0, 0 ) scale( 1 ); }
	to   { transform: translate3d( 9%, 7%, 0 ) scale( 1.12 ); }
}

@keyframes a8-bloom-b {
	from { transform: translate3d( 0, 0, 0 ) scale( 1.08 ); }
	to   { transform: translate3d( -8%, -6%, 0 ) scale( 1 ); }
}

/* -------------------------------------------------------- staged entrance */

/*
 * Scoped to `.js`: the entrance starts at opacity 0, so unconditionally
 * applied it would hide the headline in any browser that never ran the
 * animation. Without JavaScript the copy is simply there.
 *
 * With a video the copy waits for playback — main.js adds `.is-revealed` on
 * the first frames, or immediately if autoplay is refused.
 */
.js .a8-hero:not( .a8-hero--cinema ) .a8-hero__content > *,
.js .a8-hero--cinema.is-revealed .a8-hero__content > * {
	animation: a8-hero-rise 800ms cubic-bezier( .22, .8, .28, 1 ) both;
}

.js .a8-hero--cinema:not( .is-revealed ) .a8-hero__content > * {
	opacity: 0;
}

.js .a8-hero .a8-hero__content > *:nth-child( 1 ) { animation-delay: 60ms; }
.js .a8-hero .a8-hero__content > *:nth-child( 2 ) { animation-delay: 180ms; }
.js .a8-hero .a8-hero__content > *:nth-child( 3 ) { animation-delay: 300ms; }
.js .a8-hero .a8-hero__content > *:nth-child( 4 ) { animation-delay: 420ms; }

@keyframes a8-hero-rise {
	from { opacity: 0; transform: translate3d( 0, 22px, 0 ); }
	to   { opacity: 1; transform: none; }
}

/*
 * The collage cards arrive in the order they are stacked, then breathe. The
 * float offsets are tiny on purpose — the third card overhangs the band below
 * and a larger movement would read as a layout bug.
 */
.js .a8-hero__collage img {
	animation:
		a8-hero-card 800ms cubic-bezier( .22, .8, .28, 1 ) both,
		a8-hero-drift 9s ease-in-out 1.4s infinite alternate;
}

.js .a8-hero__collage img:nth-child( 1 ) { animation-delay: 260ms, 1.4s; }
.js .a8-hero__collage img:nth-child( 2 ) { animation-delay: 180ms, 1.9s; }
.js .a8-hero__collage img:nth-child( 3 ) { animation-delay: 340ms, 2.4s; }

@keyframes a8-hero-card {
	from { opacity: 0; transform: translate3d( 0, 26px, 0 ) scale( .97 ); }
	to   { opacity: 1; transform: none; }
}

@keyframes a8-hero-drift {
	from { transform: translate3d( 0, 0, 0 ); }
	to   { transform: translate3d( 0, -7px, 0 ); }
}

@media ( prefers-reduced-motion: reduce ) {
	/*
	 * base.css collapses every animation to .01ms but leaves the delays, so
	 * the staggered copy would still flash in over a third of a second.
	 */
	.js .a8-hero .a8-hero__content > *,
	.js .a8-hero__collage img {
		animation-delay: 0s !important;
	}

	/* The video never plays, so the class that unhides the copy never lands. */
	.js .a8-hero--cinema:not( .is-revealed ) .a8-hero__content > * {
		opacity: 1;
	}
}

/* =========================================================================
 * Partners, team, success stories, map, and the treatments HR asked for on
 * service cards and media images.
 *
 * Every hover here also answers to `:focus-within` or `:focus-visible`, so a
 * keyboard reaches everything a mouse does, and every one of them is a
 * `transform`/`opacity`/`clip-path` change rather than a layout change.
 * ====================================================================== */

/*
 * The section ground is the editor's to set, not the component's: success
 * stories used to hardcode the off-white and that put identical grey bands in
 * a row. They take `background` from the builder like everything else now.
 */

/* ----------------------------------------------------------------- team */

.a8-team {
	display: grid;
	grid-template-columns: repeat( var( --a8-team-cols, 4 ), minmax( 0, 1fr ) );
	gap: var( --a8-space-6 ) var( --a8-space-5 );
	margin: var( --a8-space-7 ) 0 0;
	padding: 0;
	list-style: none;
}

.a8-team--3 { --a8-team-cols: 3; }
.a8-team--4 { --a8-team-cols: 4; }

@media ( max-width: 1024px ) {
	.a8-team { --a8-team-cols: 2; }
}

@media ( max-width: 480px ) {
	.a8-team { --a8-team-cols: 1; }
}

/*
 * A team member is a card like every other: the shared ground, edge, shadow
 * and hover, with the portrait running edge to edge across the top and the
 * name and role in the card's own padding below it.
 */
.a8-person {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	background: var( --a8-white );
	border: var( --a8-card-border-w ) solid var( --a8-border-card );
	border-radius: var( --a8-radius-lg );
	box-shadow: var( --a8-card-rest );
}

.a8-person__portrait {
	position: relative;
	display: grid;
	overflow: hidden;
	aspect-ratio: 4 / 5;
	background: var( --a8-tint );
	place-items: center;
}

.a8-person__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform var( --a8-t-image ) cubic-bezier( .2, .6, .2, 1 );
}

.a8-person:hover .a8-person__img,
.a8-person:focus-within .a8-person__img {
	transform: scale( 1.05 );
}

/* Nobody's portrait is missing on purpose; this keeps the grid even until
   HR supplies the photographs. */
.a8-person__initials {
	display: grid;
	width: 100%;
	height: 100%;
	background: var( --a8-spectrum );
	color: var( --a8-white );
	font-size: 44px;
	font-weight: var( --a8-weight-bold );
	letter-spacing: -1px;
	place-items: center;
}

/*
 * The overlay carries the introduction and, under it, whatever qualifications
 * HR has on file. Capped at two thirds of the portrait so a long list never
 * buries the face — on touch there is no hover to dismiss it with.
 */
.a8-person__reveal {
	position: absolute;
	right: 0;
	bottom: 0;
	left: 0;
	display: flex;
	flex-direction: column;
	gap: var( --a8-space-2 );
	max-height: 68%;
	overflow: hidden;
	padding: var( --a8-space-6 ) var( --a8-space-4 ) var( --a8-space-4 );
	/*
	 * Held near-opaque behind the text and faded only in the top 24%, which is
	 * padding. A straight transparent-to-.95 ramp put the first line of a long
	 * qualification list a quarter of the way up the gradient, where a bright
	 * photograph shows through it; this way every line is on at least .92 and
	 * clears 13:1 over the worst case, without a hard edge at the top.
	 */
	background: linear-gradient(
		to top,
		rgba( 4, 0, 42, .96 ) 0%,
		rgba( 4, 0, 42, .92 ) 76%,
		rgba( 4, 0, 42, 0 ) 100%
	);
	color: var( --a8-white );
	font-size: var( --a8-small );
	line-height: 1.5;
	opacity: 0;
	transform: translateY( 12px );
	transition: opacity var( --a8-transition ), transform var( --a8-transition );
}

.a8-person:hover .a8-person__reveal,
.a8-person:focus-within .a8-person__reveal {
	opacity: 1;
	transform: none;
}

@media ( hover: none ) {
	.a8-person__reveal {
		opacity: 1;
		transform: none;
	}
}

.a8-person__bio {
	display: block;
}

.a8-person__quals {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

/* A list, so it is set as one: smaller, tighter, and marked per line. */
.a8-person__qual {
	position: relative;
	display: block;
	padding-left: 13px;
	color: rgba( 255, 255, 255, .88 );
	font-size: 12px;
	line-height: 1.4;
}

.a8-person__qual::before {
	content: '';
	position: absolute;
	top: .5em;
	left: 0;
	width: 5px;
	height: 5px;
	background: var( --a8-pink-light );
	border-radius: 50%;
}

/*
 * The profile link. A 40px target in the corner of the portrait rather than a
 * linked name: it is reachable by keyboard on its own, it says where it goes,
 * and the heading stays plain text. It arrives with the overlay on a pointer,
 * and is simply always there on touch.
 */
.a8-person__linkedin {
	position: absolute;
	top: var( --a8-space-3 );
	right: var( --a8-space-3 );
	z-index: 2;
	display: grid;
	place-items: center;
	width: 40px;
	height: 40px;
	background: var( --a8-white );
	border-radius: 50%;
	box-shadow: var( --a8-shadow-sm );
	color: var( --a8-brand-ink );
	opacity: 0;
	transform: translateY( -6px ) scale( .92 );
	transition:
		opacity var( --a8-transition ),
		transform var( --a8-transition ),
		background-color var( --a8-transition ),
		color var( --a8-transition );
}

.a8-person__linkedin svg {
	width: 17px;
	height: 17px;
	fill: currentColor;
}

/*
 * `:focus-visible` on the link, not `:focus-within` on the card. Focus-within
 * matched a plain mouse click too, so clicking through to a profile left the
 * disc stuck on that card until you clicked somewhere else — the stray circle.
 * Focus-visible is keyboard focus only, which is the case that actually needs
 * the affordance revealed.
 */
.a8-person:hover .a8-person__linkedin,
.a8-person__linkedin:focus-visible {
	opacity: 1;
	transform: none;
}

/* 6.9:1 either way round. */
.a8-person__linkedin:hover,
.a8-person__linkedin:focus-visible {
	background: var( --a8-brand-ink );
	color: var( --a8-white );
}

/*
 * A touch screen has no hover to reveal it with, so there it simply stays on.
 * Narrowed with `pointer: coarse` so a touch-capable laptop — which reports
 * `hover: none` on some browsers while the user is driving a mouse — keeps the
 * hover behaviour instead of showing the disc permanently.
 */
@media ( hover: none ) and ( pointer: coarse ) {
	.a8-person__linkedin {
		opacity: 1;
		transform: none;
	}
}

@media ( prefers-reduced-motion: reduce ) {
	.a8-person__linkedin,
	.a8-person:hover .a8-person__linkedin,
	.a8-person:focus-within .a8-person__linkedin {
		transform: none;
	}
}

.a8-person__name {
	margin: 0;
	padding: var( --a8-space-5 ) var( --a8-card-pad ) 2px;
	font-size: var( --a8-h6 );
	letter-spacing: -.2px;
}

.a8-person__role {
	margin: 0;
	padding: 0 var( --a8-card-pad ) var( --a8-card-pad );
	color: var( --a8-pink-ink );
	font-size: var( --a8-small );
	font-weight: var( --a8-weight-medium );
}

/* -------------------------------------------------------- success stories */

.a8-quotes {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( 280px, 1fr ) );
	gap: var( --a8-space-5 );
	margin-top: var( --a8-space-7 );
}

.a8-quote {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: var( --a8-space-5 );
	overflow: hidden;
	isolation: isolate;
	margin: 0;
	padding: var( --a8-card-pad );
	background: var( --a8-white );
	/* The same hued edge and corner shape as the other cards; see components.css. */
	border: var( --a8-card-border-w ) solid var( --a8-tone-edge );
	border-radius: var( --a8-radius-lg );
	box-shadow: var( --a8-card-rest );
}

.a8-quote__text {
	margin: 0;
	color: var( --a8-brand );
	font-size: 18px;
	font-weight: var( --a8-weight-light );
	line-height: 1.6;
}

.a8-quote__text::before {
	content: '\201C';
	display: block;
	margin-bottom: -14px;
	color: var( --a8-tone );
	font-size: 48px;
	font-weight: var( --a8-weight-bold );
	line-height: 1;
}

.a8-quote__by {
	display: flex;
	align-items: center;
	gap: var( --a8-space-3 );
	margin-top: auto;
}

.a8-quote__avatar {
	width: 44px;
	height: 44px;
	object-fit: cover;
	border-radius: 50%;
}

.a8-quote__name {
	display: block;
	color: var( --a8-brand );
	font-size: var( --a8-small );
	font-weight: var( --a8-weight-bold );
}

.a8-quote__role {
	display: block;
	color: var( --a8-text-muted );
	font-size: 13px;
}

/* ------------------------------------------------------------------ map */

.a8-map {
	display: grid;
	grid-template-columns: minmax( 0, 7fr ) minmax( 0, 4fr );
	gap: var( --a8-space-5 );
	margin-top: var( --a8-space-7 );
	align-items: stretch;
}

@media ( max-width: 900px ) {
	.a8-map {
		grid-template-columns: 1fr;
	}
}

.a8-map__frame {
	overflow: hidden;
	padding: 3px;
	background: var( --a8-spectrum );
	border-radius: var( --a8-radius-lg );
}

/*
 * The map is a tab stop, and a cross-origin frame never matches
 * :focus-visible itself, so the ring goes on its frame while focus is inside.
 */
.a8-map__frame:focus-within {
	outline: 3px solid var( --a8-accent );
	outline-offset: 3px;
}

.a8-map__embed {
	display: block;
	width: 100%;
	height: 100%;
	min-height: 380px;
	border: 0;
	border-radius: calc( var( --a8-radius-lg ) - 3px );
	/* Google's tiles are washed out next to the brand palette. */
	filter: saturate( .9 );
}

.a8-map__card {
	display: flex;
	flex-direction: column;
	gap: var( --a8-space-4 );
	padding: var( --a8-space-6 );
	background: var( --a8-brand );
	border-radius: var( --a8-radius-lg );
	color: var( --a8-text-invert );
}

.a8-map__heading {
	margin: 0;
	color: var( --a8-text-invert );
	font-size: var( --a8-h4 );
	letter-spacing: -.4px;
}

.a8-map__address {
	margin: 0;
	color: var( --a8-text-invert );
	font-size: 18px;
	font-style: normal;
	line-height: 1.55;
}

.a8-map__facts {
	display: grid;
	gap: var( --a8-space-3 );
	margin: 0;
	padding: 0;
	list-style: none;
}

.a8-map__facts li {
	display: flex;
	align-items: center;
	gap: var( --a8-space-3 );
	color: var( --a8-text-invert-muted );
	font-size: var( --a8-small );
}

.a8-map__facts svg {
	flex: none;
	width: 18px;
	height: 18px;
	color: var( --a8-pink-light );
}

/* A 24px target on a phone; the text alone was 21px tall. */
.a8-map__facts a {
	display: inline-block;
	padding-block: 3px;
	color: var( --a8-text-invert );
	text-decoration: none;
}

.a8-map__facts a:hover,
.a8-map__facts a:focus-visible {
	text-decoration: underline;
}

.a8-map__actions {
	margin-top: auto;
}

/* The spectrum edge, the lift and the icon fill are the shared card language;
   see "The card design language" at the end of this file. */

/* ------------------------------------------------- media image treatment */

/*
 * Mission, vision, "where connections create growth" and the rest of the
 * media rows: the office photographs. The picture lifts off a spectrum plate
 * and takes a brand wash as it does. It answers to the row, so pointing at the
 * copy moves the picture too, and to focus inside the row for the same reason.
 *
 * This is the only component that uses it. Team portraits and event
 * photographs have their own treatments and are not touched by anything here.
 *
 * `isolation: isolate` is the fix for the Our Mission photograph, which had no
 * visible hover. The plate sits at `z-index: -1`, and without a stacking
 * context on this wrapper it was painted behind the nearest one up — which on
 * a grey section is behind the section's own opaque background. On a white
 * section the background is transparent, so it only ever showed there. The
 * homepage's "Services we provide" row had the same fault.
 */
.a8-media-text__media {
	position: relative;
	isolation: isolate;
}

/*
 * The treatment belongs to photographs. A vacancy puts its facts card in the
 * same column, and pointing anywhere at the job description used to slide a
 * gradient plate out from behind that card and lay a pink wash over its text.
 */
.a8-media-text__media:not( :has( img ) )::before,
.a8-media-text__media:not( :has( img ) )::after {
	content: none;
}

/*
 * No height of its own: the picture is whatever shape the `a8-feature` size
 * makes it, which is 4:3. It was 16:9, and beside a 400px column of copy that
 * is a letterbox — the office photographs are of people standing and sitting
 * around a room, and a 16:9 band through the middle of one cut the heads off
 * the back row and the table off the front.
 */
.a8-media-text__img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var( --a8-radius-lg );
	transition:
		transform var( --a8-t-image ) cubic-bezier( .2, .6, .2, 1 ),
		box-shadow var( --a8-t-image ) cubic-bezier( .2, .6, .2, 1 );
}

@media ( max-width: 860px ) {
	/*
	 * Stacked, the picture is the full column width, and 4:3 of a wide phone
	 * in landscape is a screenful of photograph before the copy starts. The
	 * cap only bites on a short, wide viewport; at every portrait width the
	 * picture is well inside it and nothing is cropped.
	 */
	.a8-media-text__img {
		max-height: 68vh;
		object-fit: cover;
		object-position: center;
	}
}

/*
 * Three parts, one timing. The picture lifts and grows (was -6px / 1.01, which
 * read as a flicker rather than a movement); the plate behind slides out from
 * under it; a brand wash settles over it. All three share the image easing and
 * duration so they move as one object.
 */
.a8-media-text:hover .a8-media-text__img,
.a8-media-text:focus-within .a8-media-text__img {
	transform: translateY( -10px ) scale( 1.03 );
	box-shadow: var( --a8-lift-strong );
}

/*
 * The plate. It used to sit already offset and only fade in; now it starts
 * directly under the picture and slides out to the corner as the picture
 * lifts, so the colour appears from behind it rather than beside it. A
 * stronger run than --a8-spectrum-soft, which at .14-.20 alpha barely told
 * against the grey sections at all.
 */
.a8-media-text__media::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: -1;
	background: linear-gradient(
		135deg,
		rgba( 0, 147, 255, .42 ) 0%,
		rgba( 123, 44, 191, .30 ) 52%,
		rgba( 242, 2, 93, .42 ) 100%
	);
	border-radius: var( --a8-radius-lg );
	opacity: 0;
	transform: translate( 0, 0 );
	transition:
		opacity var( --a8-t-image ) cubic-bezier( .2, .6, .2, 1 ),
		transform var( --a8-t-image ) cubic-bezier( .2, .6, .2, 1 );
}

.a8-media-text:hover .a8-media-text__media::before,
.a8-media-text:focus-within .a8-media-text__media::before {
	opacity: 1;
	transform: translate( 14px, 14px );
}

/*
 * The wash over the picture. Weighted to the lower corner and light at the
 * top, so faces stay clear and it reads as light falling across the photo
 * rather than a tint laid on it. It takes the picture's exact transform so it
 * travels with it; the wrapper is the picture's size, so the origins match.
 */
.a8-media-text__media::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 1;
	background: linear-gradient(
		160deg,
		rgba( 0, 147, 255, 0 ) 35%,
		rgba( 30, 10, 131, .12 ) 70%,
		rgba( 242, 2, 93, .22 ) 100%
	);
	border-radius: var( --a8-radius-lg );
	opacity: 0;
	pointer-events: none;
	transition:
		opacity var( --a8-t-image ) cubic-bezier( .2, .6, .2, 1 ),
		transform var( --a8-t-image ) cubic-bezier( .2, .6, .2, 1 );
}

.a8-media-text:hover .a8-media-text__media::after,
.a8-media-text:focus-within .a8-media-text__media::after {
	opacity: 1;
	transform: translateY( -10px ) scale( 1.03 );
}

/* Motion off: the plate and the wash still arrive, nothing travels. */
@media ( prefers-reduced-motion: reduce ) {
	.a8-media-text:hover .a8-media-text__img,
	.a8-media-text:focus-within .a8-media-text__img,
	.a8-media-text:hover .a8-media-text__media::after,
	.a8-media-text:focus-within .a8-media-text__media::after {
		transform: none;
	}

	.a8-media-text:hover .a8-media-text__media::before,
	.a8-media-text:focus-within .a8-media-text__media::before {
		/* Still offset, so it shows as a frame; it just does not slide there. */
		transform: translate( 14px, 14px );
	}
}

/*
 * A cards section with a photograph beside its heading (Explore our core
 * features) uses this same row, so it gets this same hover. It keeps its own
 * section-heading scale rather than the media row's smaller one.
 */
.a8-cards__intro .a8-heading__title {
	font-size: clamp( 28px, 3.1vw, var( --a8-h2 ) );
	line-height: 1.08;
	letter-spacing: -1.2px;
}

.a8-cards__intro + .a8-grid {
	margin-top: var( --a8-space-7 );
}

/* ------------------------------------------- the proposal form's frame */

/*
 * The pink-and-blue frame the brief asks for. Painted as a gradient on a
 * wrapper with the card inset over it: `border-image` cannot follow a
 * border-radius, and this has 28px corners. The gradient drifts slowly, which
 * is the only motion on the block.
 */
.a8-lead__frame {
	position: relative;
	padding: 3px;
	background: var( --a8-spectrum-loop );
	background-size: 260% 100%;
	border-radius: calc( var( --a8-radius-lg ) + 3px );
	animation: a8-frame-drift 14s linear infinite;
}

@keyframes a8-frame-drift {
	from { background-position: 0% 0; }
	to   { background-position: 200% 0; }
}

.a8-lead__frame .a8-lead__card {
	border: 0;
	border-radius: var( --a8-radius-lg );
	box-shadow: none;
}

/* The wrapper carries the edge now, so the card's own hairline would double it. */
.a8-lead__frame .a8-lead__card::before {
	display: none;
}

@media ( prefers-reduced-motion: reduce ) {
	.a8-lead__frame {
		animation: none;
		background-position: 25% 0;
	}
}

/* =========================================================================
 * The card design language
 *
 * One set of primitives, combined differently per section, so every grid on
 * the site is recognisably the same system without any two looking identical.
 *
 *   1. a spectrum edge that draws itself in on hover
 *   2. a lift with a navy-tinted shadow
 *   3. an icon that fills with the spectrum
 *   4. an image that eases in scale
 *   5. a reveal panel that slides up
 *
 * Timings are shared so nothing feels out of step: 420ms for edges and fills,
 * 600ms for images, one easing curve. Everything animates `transform`,
 * `opacity`, `clip-path` or `filter` only.
 *
 * Every :hover here is paired with :focus-visible or :focus-within, and every
 * reveal is unconditional under `hover: none` so a phone hides nothing.
 * ====================================================================== */

/* --- the spectrum edge ---------------------------------------------------
 *
 * A card has 28px corners, and the edge used to be a 3px bar stretched
 * `left: 0; right: 0` across the bottom of it. Three pixels up from the
 * bottom the card's own curve has already pulled in by 15px on each side, so
 * the bar hung out past both bottom corners — a straight coloured line
 * sticking out of a rounded box.
 *
 * The fix is to stop drawing a bar. The pseudo-element now covers the whole
 * card and inherits its radius, and the colour is a background stripe painted
 * along one side of it. A background is always clipped to the rounded border
 * box, so the stripe is trimmed by the card's exact curve, whatever that
 * radius happens to be — 28px here, 18px on a step, 0 on the service page
 * where the card is not drawn as a card at all.
 *
 * `clip-path` draws it in rather than `transform: scaleX()`, because scaling
 * the box would squash the inherited corner radius with it and the clipping
 * would go wrong halfway through. Same direction, same duration, same easing;
 * it is the technique `.a8-btn--outline` already uses.
 *
 * Because the effect is contained by the pseudo-element, no card needs
 * `overflow: hidden` to hold it, and the shadow stays outside where it is.
 */
/* --- the icon fill ------------------------------------------------------- */

.a8-card__icon,
.a8-band__icon,
.a8-channel__icon {
	transition:
		background var( --a8-t-edge ) var( --a8-ease-card ),
		color var( --a8-t-edge ) var( --a8-ease-card ),
		transform var( --a8-t-edge ) var( --a8-ease-card );
}

/* The tile fills with the card's own hue; white on each is 6.2:1 or better. */
.a8-card:hover .a8-card__icon,
.a8-card:focus-within .a8-card__icon {
	background: var( --a8-tone );
	color: var( --a8-white );
	transform: translateY( -2px ) rotate( -4deg );
}

/* -------------------------------------------------- applying the language */

/*
 * The card. Explore our core features is the reference, and every boxed card
 * on the site now follows it: the icon cards, service and job cards, the
 * service benefits, the numbered steps, the office blocks and the success
 * stories. One ground, one edge, one padding, one hover.
 *
 * That now includes the team and the event tiles, and nothing carries a
 * decoration of its own any more: the service card's top line, the job
 * card's side line and the success stories' vertical rule are gone. Every
 * card has one accent — the spectrum edge drawing along the bottom on hover
 * — and one border, padding, shadow, lift and timing, defined here once.
 * What differs is content only: a photograph at the top of a team card, a
 * photograph behind an event tile.
 */
:is( .a8-card, .a8-steps__item, .a8-office, .a8-quote, .a8-person, .a8-event-card ) {
	position: relative;
	transition:
		transform var( --a8-t-edge ) var( --a8-ease-card ),
		box-shadow var( --a8-t-edge ) var( --a8-ease-card ),
		border-color var( --a8-t-edge ) var( --a8-ease-card ),
		background var( --a8-t-edge ) var( --a8-ease-card );
}

/* Contained by the card's own radius — see the spectrum edge above. */
:is( .a8-card, .a8-steps__item, .a8-office, .a8-quote, .a8-person )::after {
	content: '';
	position: absolute;
	inset: 0;
	border-radius: inherit;
	background: var( --a8-spectrum ) bottom left / 100% var( --a8-card-edge ) no-repeat;
	clip-path: inset( 0 100% 0 0 );
	transition: clip-path var( --a8-t-edge ) var( --a8-ease-card );
	pointer-events: none;
}

/*
 * The border used to go transparent on hover, which took the card's outline
 * away at the exact moment it was being pointed at. The light band deepens
 * into the logo blue instead, so the hover state is a stronger edge rather
 * than no edge — the one thing that changes about the border is its colour,
 * so nothing reflows.
 */
:is( .a8-card, .a8-steps__item, .a8-office, .a8-quote, .a8-person, .a8-event-card ):is( :hover, :focus-within ) {
	transform: translateY( -4px );
	/* Each card deepens its own hue; cards without one take the logo blue. */
	border-color: var( --a8-tone-line, rgba( 0, 147, 255, .55 ) );
	box-shadow: var( --a8-lift );
}

:is( .a8-card, .a8-steps__item, .a8-office, .a8-quote, .a8-person ):is( :hover, :focus-within )::after {
	clip-path: inset( 0 0 0 0 );
}

/* The numbered disc on a step answers the hover the way a card icon does. */
.a8-steps__num {
	transition:
		background var( --a8-t-edge ) var( --a8-ease-card ),
		color var( --a8-t-edge ) var( --a8-ease-card );
}

.a8-steps__item:is( :hover, :focus-within ) .a8-steps__num {
	background: var( --a8-spectrum );
	color: var( --a8-white );
}

/* The drawn edge stays over a photo card's picture and corner shape. */
.a8-card::after {
	z-index: 1;
}

/* --- the events grid ----------------------------------------------------- */

/* Already image-led with its own reveal; it joins the system by sharing the
   easing and gaining the same spectrum edge above the copy. */
.a8-event-card::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 1;
	border-radius: inherit;
	background: var( --a8-spectrum ) bottom left / 100% var( --a8-card-edge ) no-repeat;
	clip-path: inset( 0 100% 0 0 );
	transition: clip-path var( --a8-t-edge ) var( --a8-ease-card );
	pointer-events: none;
}

.a8-event-card:hover::after,
.a8-event-card:focus-within::after {
	clip-path: inset( 0 0 0 0 );
}

/* --- headings ------------------------------------------------------------ */

/*
 * The eyebrow rule and the heading share one entrance so a section reads as
 * one unit arriving rather than three things arriving separately.
 */
.js .a8-reveal .a8-eyebrow::after {
	transform: scaleX( 0 );
	transform-origin: left;
	transition: transform 520ms var( --a8-ease-card ) 180ms;
}

.js .a8-reveal.is-visible .a8-eyebrow::after {
	transform: scaleX( 1 );
}

@media ( prefers-reduced-motion: reduce ) {
	:is( .a8-card, .a8-steps__item, .a8-office, .a8-quote, .a8-person, .a8-event-card ):is( :hover, :focus-within ),
	.a8-card:hover .a8-card__icon,
	.a8-card:focus-within .a8-card__icon {
		transform: none;
	}

	/* The edges still appear, they just stop drawing. */
	:is( .a8-card, .a8-steps__item, .a8-office, .a8-quote, .a8-person )::after,
	.a8-event-card::after,
	.js .a8-reveal .a8-eyebrow::after {
		transition: none;
	}
}

/* =========================================================================
 * Typography and the page-wide reveal
 *
 * The scale itself is unchanged; what changes is the hierarchy around it. An
 * eyebrow is a small caps label over a spectrum rule, a section title is
 * heavy and tight, a standfirst is light and long. Three clearly different
 * weights of voice instead of three sizes of the same one.
 *
 * Only ONE gradient-text treatment exists on the site — the closing word of
 * the hero statement — and it is deliberate. Everything else takes colour
 * from the palette, because gradient text cannot hold a contrast ratio and a
 * page full of it stops meaning anything.
 * ====================================================================== */

/* ------------------------------------------------------------- eyebrow */

.a8-eyebrow {
	font-size: 13px;
	font-weight: var( --a8-weight-bold );
	letter-spacing: .12em;
	text-transform: uppercase;
}

/* ------------------------------------------------------------ headings */

.a8-heading__title {
	/* Tight and heavy, the way the logo wordmark is set. */
	font-size: clamp( 28px, 3.1vw, var( --a8-h2 ) );
	line-height: 1.08;
	letter-spacing: -1.2px;
	text-wrap: balance;
}

.a8-heading__body {
	max-width: 58ch;
	color: var( --a8-text-muted );
	font-size: 17px;
	font-weight: var( --a8-weight-light );
	line-height: 1.62;
}

/* A standfirst on a dark ground needs more weight than on white. */
.a8-section--purple .a8-heading__body,
.a8-band__body {
	font-weight: var( --a8-weight-normal );
}

.a8-pagehead__title {
	font-size: clamp( 34px, 4.4vw, var( --a8-h1 ) );
	line-height: 1.05;
	letter-spacing: -1.6px;
	text-wrap: balance;
}

.a8-pagehead__intro {
	font-size: 18px;
	font-weight: var( --a8-weight-light );
	line-height: 1.6;
}

/* Card titles sit a step above body copy without competing with the section. */
.a8-card__title {
	font-size: 19px;
	line-height: 1.25;
}

.a8-card__body {
	font-size: 15px;
	line-height: 1.6;
}

/* ------------------------------------------------- the shared reveal ---
 *
 * One entrance for the whole site, driven by the IntersectionObserver that
 * was already there. Sections rise; grids stagger their children off the
 * parent's `is-visible`, so a row of cards arrives in sequence without a
 * class per card or a second observer.
 */

/*
 * An animation on `translate`, not a transition on `transform`, and that
 * difference is the whole point.
 *
 * It used to be `transform` and `transition` on `.js .a8-reveal.is-visible`,
 * a class a card keeps for the life of the page. At three classes that rule
 * outranked every card's hover, so `transform: none` won permanently: no card,
 * quote or event tile on the site ever lifted when pointed at. Its
 * `transition` shorthand also replaced each card's own, so hover borders and
 * shadows snapped instead of easing.
 *
 * `translate` is its own property and composes with `transform`, and an
 * animation leaves `transition` alone. The entrance and the hover no longer
 * touch the same property, so neither can overrule the other. Same rise, same
 * 700ms, same stagger.
 */
.js .a8-reveal:not( .is-visible ) {
	opacity: 0;
	translate: 0 22px;
}

.js .a8-reveal.is-visible {
	animation: a8-reveal-in 700ms var( --a8-ease-card ) both;
}

@keyframes a8-reveal-in {
	from {
		opacity: 0;
		translate: 0 22px;
	}

	to {
		opacity: 1;
		translate: 0 0;
	}
}

/* Grid children stagger off the grid's own reveal. */
.js .a8-grid > .a8-reveal,
.js .a8-events-grid > .a8-reveal,
.js .a8-team > .a8-reveal,
.js .a8-quotes > .a8-reveal {
	animation-delay: calc( var( --a8-i, 0 ) * 70ms );
}

@media ( prefers-reduced-motion: reduce ) {
	.js .a8-reveal:not( .is-visible ),
	.js .a8-reveal.is-visible {
		opacity: 1;
		translate: none;
		animation: none;
	}
}

@media ( prefers-reduced-motion: reduce ) {
	.a8-event-card:is( :hover, :focus-within ) .a8-event-card__more svg {
		transform: none;
	}
}
