/*
 * Bohardien element and type baseline.
 *
 * Design decisions, as opposed to parent-overrides.css, which only neutralises
 * Underscores. Self-hosted fonts, the type ramp applied to real elements, the
 * section rhythm, and the layout primitives the templates build on.
 */

/* Self-hosted fonts, subsetted to latin and latin-ext as woff2.
   No Google Fonts request at runtime: a German firm cannot leak visitor IPs to
   Google without consent. unicode-range means a browser fetches only the
   subsets whose characters actually appear, so a German or English page pulls
   the latin faces alone. 266 KB on disk, ~78 KB transferred in practice.

   The weight axis is clamped to the 300-500 the design actually uses. */

/* Host Grotesk normal, latin */
@font-face {
	font-family: "Host Grotesk";
	src: url("../fonts/host-grotesk-latin.woff2") format("woff2-variations");
	font-weight: 100 900;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Host Grotesk normal, latin-ext */
@font-face {
	font-family: "Host Grotesk";
	src: url("../fonts/host-grotesk-latin-ext.woff2") format("woff2-variations");
	font-weight: 100 900;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Host Grotesk italic, latin */
@font-face {
	font-family: "Host Grotesk";
	src: url("../fonts/host-grotesk-italic-latin.woff2") format("woff2-variations");
	font-weight: 100 900;
	font-style: italic;
	font-display: swap;
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Host Grotesk italic, latin-ext */
@font-face {
	font-family: "Host Grotesk";
	src: url("../fonts/host-grotesk-italic-latin-ext.woff2") format("woff2-variations");
	font-weight: 100 900;
	font-style: italic;
	font-display: swap;
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Newsreader normal, latin */
@font-face {
	font-family: "Newsreader";
	src: url("../fonts/newsreader-latin.woff2") format("woff2-variations");
	font-weight: 200 800;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Newsreader normal, latin-ext */
@font-face {
	font-family: "Newsreader";
	src: url("../fonts/newsreader-latin-ext.woff2") format("woff2-variations");
	font-weight: 200 800;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Newsreader italic, latin */
@font-face {
	font-family: "Newsreader";
	src: url("../fonts/newsreader-italic-latin.woff2") format("woff2-variations");
	font-weight: 200 800;
	font-style: italic;
	font-display: swap;
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Newsreader italic, latin-ext */
@font-face {
	font-family: "Newsreader";
	src: url("../fonts/newsreader-italic-latin-ext.woff2") format("woff2-variations");
	font-weight: 200 800;
	font-style: italic;
	font-display: swap;
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Headings ------------------------------------------------------------- */
/*
 * CORRECTION, 11/09/2026. These were sans at weight 300 until now, which was
 * wrong on both counts and wrong on every page.
 *
 * The design carries one rule, `h1, h2, h3, h4, blockquote { font-family:
 * 'Newsreader', Georgia, serif; font-weight: 400 }`, and nothing overrides it:
 * across 23 h1, 80 h2 and 59 h3 elements there is not a single inline
 * font-family, and not one element anywhere returns to Host Grotesk. So every
 * heading in the design is the serif at 400.
 *
 * The Stage 1 reading counted font-family *declarations* and saw Host Grotesk
 * dominant. That counts declarations, not inheritance: one rule covers all 162
 * headings. The weight tally was misread the same way, because the 300s are
 * body copy while every heading carries an explicit 400.
 *
 * h5 and h6 stay sans deliberately: the design's rule stops at h4 and uses
 * neither, so they inherit the body face exactly as they would there.
 */
h1, h2, h3, h4 {
	color: var(--fg);
	font-family: var(--font-serif);
	font-weight: var(--fw-regular);
	text-wrap: balance;
	margin: 0;
}

h5, h6 {
	color: var(--fg);
	font-family: var(--font-sans);
	font-weight: var(--fw-medium);
	text-wrap: balance;
	margin: 0;
}

h1 {
	font-size: var(--fs-h1);
	line-height: var(--lh-display);
	letter-spacing: var(--ls-display);
}

.hero h1,
h1.is-display {
	font-size: var(--fs-display);
}

h2 {
	font-size: var(--fs-h2);
	line-height: var(--lh-heading);
	letter-spacing: var(--ls-heading);
}

h3 {
	font-size: var(--fs-h3);
	line-height: var(--lh-tight);
	letter-spacing: var(--ls-tight);
}

h4 {
	font-size: var(--fs-h4);
	line-height: var(--lh-snug);
	letter-spacing: var(--ls-tight);
}

h5 {
	font-size: var(--fs-h5);
	line-height: var(--lh-snug);
}

h6 {
	font-size: var(--fs-lg);
	line-height: var(--lh-ui);
}

/* Body ----------------------------------------------------------------- */
p {
	margin: 0 0 1.15em;
	max-width: var(--measure);
}

p:last-child {
	margin-bottom: 0;
}

.lede {
	font-size: var(--fs-lg);
	line-height: var(--lh-body-sm);
	color: var(--fg-2);
	max-width: var(--measure-intro);
}

.small {
	font-size: var(--fs-sm);
	line-height: var(--lh-ui);
}

/* Meta text: dates, bylines, counts.
 *
 * --ph, not --faint. --faint composites to 3.05:1 on the navy ground, which
 * fails the 4.5:1 WCAG 2.1 AA needs for text at this size. --ph gives 5.46:1
 * and is still clearly quieter than body copy, so the hierarchy survives.
 *
 * The design itself applies --faint to `color` in 30 places. Wherever those are
 * genuinely decorative, a separator glyph or a middle dot, --faint is correct
 * and stays. Wherever one of them is readable text, it is an accessibility
 * defect in the source design and needs raising with the designer rather than
 * reproducing. Flagged for the Stage 8 accessibility pass.
 */
.meta {
	font-size: var(--fs-xs);
	color: var(--ph);
}

/* Kicker: the taupe eyebrow label above most section headings ---------- */
.kicker {
	color: var(--kicker);
	font-size: var(--fs-3xs);
	font-weight: var(--fw-medium);
	letter-spacing: var(--ls-kicker-wide);
	text-transform: uppercase;
	display: block;
	margin: 0 0 var(--gap-md);
	max-width: var(--measure-label);
}

/* Serif is an editorial accent only, never body copy ------------------- */
.serif {
	font-family: var(--font-serif);
	font-weight: var(--fw-regular);
}

/* Layout primitives --------------------------------------------------- */
.section {
	padding-block: var(--section-y);
	border-top: 1px solid var(--line);
	position: relative;
}

.section--hero {
	padding-block: var(--section-y-hero) var(--section-y-hero-end);
	border-top: 0;
	overflow: hidden;
}

.section--alt {
	padding-block: var(--section-y-alt) var(--section-y-alt-end);
}

.section--panel {
	background: var(--panel);
	color: var(--panel-fg);
}

.section--lift {
	background: var(--lift);
}

/* Grids. Every grid declares a minmax() floor so card rows wrap instead of
   squeezing on a 390px viewport, per decision 3. ----------------------- */
.grid-split {
	display: grid;
	grid-template-columns: var(--split-editorial);
	gap: var(--gap-3xl);
	align-items: start;
}

.grid-even {
	display: grid;
	grid-template-columns: var(--split-even);
	gap: var(--gap-3xl);
}

.cards-2up { display: grid; grid-template-columns: var(--cards-2up); gap: var(--gap-lg); }
.cards-3up { display: grid; grid-template-columns: var(--cards-3up); gap: var(--gap-lg); }
.cards-4up { display: grid; grid-template-columns: var(--cards-4up); gap: var(--gap-lg); }

/* The two asymmetric splits are the only place a breakpoint is justified:
   below 900px they must stack, and there is no fluid equivalent. -------- */
@media (max-width: 899px) {
	.grid-split,
	.grid-even {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--gap-xl);
	}
}

/* Media --------------------------------------------------------------- */
img,
svg,
video {
	max-width: 100%;
	height: auto;
	display: block;
}

figure {
	margin: 0;
}

/* Reduced motion ------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

/* ===========================================================================
 * Arrow affordances
 *
 * The "Explore", "Read the study", "Read the article", "Apply", "Open" and
 * "Book now" links: a label followed by an arrow. On hover the arrow turns to
 * point out of the top-right corner, the direction the link is taking you, and
 * a light rule grows under the label from the leading edge.
 *
 * Defined once here rather than per component, because it is one behaviour
 * that happens to appear in six places. The label carries .cue-label so the
 * rule sits under the words alone; underlining the whole affordance would draw
 * it under the arrow as well. The arrow is matched as the sibling that follows
 * the label, so no component has to add a class to its svg.
 *
 * The rule is a pseudo-element rather than text-decoration because it has to
 * animate, and because these hosts are flex containers: text-decoration set on
 * a flex container does not reliably reach an anonymous flex item.
 *
 * Reduced motion is zeroed globally below, which leaves both as an instant
 * state change rather than a movement. That is the correct degradation.
 * ======================================================================== */
.cue-label {
	position: relative;
}

.cue-label::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	bottom: -3px;
	height: 1px;
	background: currentColor;
	opacity: 0.55;
	transform: scaleX(0);
	transform-origin: left;
	transition: transform var(--dur) var(--ease);
}

.cue-label ~ svg {
	transition: transform var(--dur) var(--ease);
}

/* The trigger is the card wherever the whole card is the link, and the link
   itself where it stands alone. :focus-within so a keyboard user gets the
   same signal without the component restating the focus ring. */
:is(
	.expertise-card,
	.case-card,
	.article-card,
	.vacancy-card,
	.search-result,
	.booking-card
):is( :hover, :focus-within ) .cue-label::after {
	transform: scaleX(1);
}

:is(
	.expertise-card,
	.case-card,
	.article-card,
	.vacancy-card,
	.search-result,
	.booking-card
):is( :hover, :focus-within ) .cue-label ~ svg {
	transform: rotate(-45deg);
}
