/**
 * Newsletter V3 — layout styles.
 *
 * Loaded only on the "v3 New Newsletter Custom" page template (see
 * inc/newsletter-v3.php), and every selector is namespaced under `.nlv3`.
 * Nothing here matches the class names used by the V1/V2 newsletters
 * (.newsletter, .insights, .news-massage, .newsletter-card-layout,
 * .insight-card, .new-news-letter-insights-swiper), so the older templates are
 * unaffected whether or not this file is on the page.
 *
 * Values are transcribed from the ICIEC_ANNUAL_REPORT_2025 Figma frame
 * (node 403:6409) at a 1440px artboard: 1200px content, 120px gutters,
 * 64px section padding, 24px grid gap.
 */

/* ==========================================================================
   Tokens + root
   ========================================================================== */

.nlv3 {
	--nlv3-green-400: #056623;
	--nlv3-green-glow: rgba(7, 146, 50, 0.2);
	--nlv3-gold-300: #c08a00;
	--nlv3-gradient-top: #e6f4eb;

	--nlv3-ink-900: #000;
	--nlv3-ink-700: #1c1c1c;
	--nlv3-ink-500: #3b3b3b;
	--nlv3-ink-300: #575757;
	--nlv3-green-300: #31a555;  /* card hover label, measured from the prototype */
	--nlv3-green-500: #54a937;  /* project arrow hover fill, measured from the prototype */
	--nlv3-green-75: #99d2ab;   /* Foundation/Green/G75 - letter backing panel */
	--nlv3-neutral-100: #757575; /* Foundation/Neutral/G100 - inactive tab label */
	--nlv3-neutral-40: #dedede;  /* Foundation/Neutral/G40  - inactive tab fill  */

	--nlv3-surface: #fff;
	--nlv3-surface-muted: #f5f5f5;
	--nlv3-scrim: rgba(0, 0, 0, 0.21);
	--nlv3-frost: rgba(255, 255, 255, 0.5);

	--nlv3-radius-lg: 24px;
	--nlv3-radius-md: 12px;
	--nlv3-radius-sm: 8px;

	--nlv3-gap: 24px;
	--nlv3-content: 1200px;

	/* Fluid section rhythm: 64px at the 1440 artboard, easing to 40px on
	   phones, replacing the old hard 64->48 breakpoint jump. */
	--nlv3-section-y: clamp(40px, 4.45vw, 64px);

	/* 8.334vw resolves to exactly 120px at the 1440px artboard width. */
	--nlv3-gutter: clamp(20px, 8.334vw, 120px);

	/*
	 * Fluid type scale. Each token hits the exact Figma size at the 1440px
	 * artboard (the clamp ceiling) and eases down as the viewport narrows,
	 * so every width between the old breakpoints gets a proportionate size
	 * instead of the desktop one. Hierarchy is preserved at every width:
	 * title > name > lead > ui > body > small.
	 */
	--nlv3-fs-title: clamp(1.25rem, 1.14vw + 1rem, 2rem);             /* 20 -> 32 */
	--nlv3-fs-name: clamp(1.125rem, 0.42vw + 1.125rem, 1.5rem);       /* 18 -> 24 */
	--nlv3-fs-lead: clamp(1rem, 0.35vw + 0.9375rem, 1.25rem);         /* 16 -> 20 */
	--nlv3-fs-ui: clamp(0.875rem, 0.14vw + 0.875rem, 1rem);           /* 14 -> 16 */
	--nlv3-fs-body: clamp(0.8125rem, 0.09vw + 0.8125rem, 0.875rem);   /* 13 -> 14 */
	--nlv3-fs-small: clamp(0.75rem, 0.14vw + 0.75rem, 0.875rem);      /* 12 -> 14 */

	/* Vertical rhythm inside the letter: 24px at the artboard, 16px on
	   phones, so image/heading/quote/body tighten together on small screens. */
	--nlv3-flow: clamp(16px, 1.67vw, 24px);

	--nlv3-track: 0.072px;

	background: var(--nlv3-surface);
	color: var(--nlv3-ink-500);
	font-family: "Poppins", "Helvetica Neue", Arial, sans-serif;
	letter-spacing: var(--nlv3-track);
	overflow-x: clip;
}

[dir="rtl"] .nlv3 {
	font-family: "Almarai", "Poppins", "Helvetica Neue", Arial, sans-serif;
}

/* Defensive copy: the global .screen-reader-text lives in the bundled
   stylesheet, so this scoped duplicate keeps V3 accessible if that file is
   ever swapped out. */
.nlv3 .screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.nlv3 *,
.nlv3 *::before,
.nlv3 *::after {
	box-sizing: border-box;
}

.nlv3 img {
	max-width: 100%;
}

.nlv3 a {
	text-decoration: none;
}

/*
 * Bootstrap paints a dark UA ring via `button:focus { outline: -webkit-focus-
 * ring-color auto 5px }`, which fires on mouse clicks too — that is the black
 * outline that appeared around the carousel arrows. It is dropped only inside
 * a :focus-visible support check, so the keyboard ring below is guaranteed to
 * exist before the click ring is removed.
 */
@supports selector(:focus-visible) {
	.nlv3 a:focus,
	.nlv3 button:focus {
		outline: none;
	}
}

/*
 * Consistent, visible keyboard focus on every interactive V3 element.
 * No border-radius here on purpose: setting one would overwrite each element's
 * own radius (it squared off the 98px round nav buttons). Browsers already
 * curve the outline to match whatever radius the element has.
 */
.nlv3 a:focus-visible,
.nlv3 button:focus-visible {
	outline: 3px solid var(--nlv3-green-400);
	outline-offset: 3px;
}

/* ==========================================================================
   Section shell
   ========================================================================== */

.nlv3-section {
	padding: var(--nlv3-section-y) var(--nlv3-gutter);
	position: relative;
}

.nlv3-section__inner {
	max-width: var(--nlv3-content);
	margin-left: auto;
	margin-right: auto;
	width: 100%;
}

.nlv3-section__title {
	margin: 0 0 var(--nlv3-gap);
	padding: 0;
	color: var(--nlv3-ink-900);
	font-family: inherit;
	font-size: var(--nlv3-fs-title);
	font-weight: 400;

	/* Figma draws a 24px line box (0.75) on this single-line title; a unitless
	   1.2 reads the same for one line but survives multi-line translations. */
	line-height: 1.2;
	text-transform: capitalize;
	letter-spacing: var(--nlv3-track);
}

/* ==========================================================================
   Hero + edition badge
   ========================================================================== */

.nlv3-hero {
	position: relative;
	line-height: 0;
}

.nlv3-hero__media {
	display: block;
}

.nlv3-hero__image {
	display: block;
	width: 100%;
	height: auto;

	/* 1440x640 in Figma. */
	aspect-ratio: 9 / 4;
	object-fit: cover;
	object-position: center;
}

/* Green pill hanging off the bottom edge of the cover, centred. */
.nlv3-hero__edition {
	position: absolute;
	top: 100%;
	left: 50%;
	transform: translateX(-50%);
	z-index: 2;
	margin: 0;
	padding: 8px 80px;
	max-width: calc(100% - 40px);
	background: var(--nlv3-green-400);
	border-radius: 0 0 var(--nlv3-radius-lg) var(--nlv3-radius-lg);
	color: var(--nlv3-surface);
	font-size: var(--nlv3-fs-lead);
	font-weight: 400;
	line-height: 1.5;
	letter-spacing: var(--nlv3-track);
	text-align: center;
	text-transform: capitalize;
	white-space: nowrap;
}

/*
 * No banner authored: the pill normally hangs off the image's bottom edge, but
 * with no image the hero has zero height and it would land on top of the CEO
 * section. Drop it back into normal flow, still centred.
 */
.nlv3-hero--no-media {
	line-height: normal;
	text-align: center;
}

.nlv3-hero--no-media .nlv3-hero__edition {
	position: static;
	display: inline-block;
	transform: none;
}

.nlv3-hero__edition-label {
	display: block;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* ==========================================================================
   CEO letter
   ========================================================================== */

.nlv3-ceo {
	padding-bottom: 40px;
	background: linear-gradient(180deg, var(--nlv3-gradient-top) 0%, var(--nlv3-surface) 100%);
}

.nlv3-ceo__card {
	/* 48px at the 1440 artboard, easing to 24px on phones. */
	padding: clamp(24px, 3.33vw, 48px);
	background: var(--nlv3-surface);
	border-radius: var(--nlv3-radius-lg);

	/* Sits above the backing panel below. */
	position: relative;
	z-index: 1;

	/* Green lift + neutral drop, both from the Figma "Letter" node. */
	box-shadow:
		0 4px 46.6px var(--nlv3-green-glow),
		0 4px 24px rgba(0, 0, 0, 0.1);
}

/*
 * Backing panel — the Figma "Shadow" frame behind the Letter, and the same
 * device Handshake uses on its "Letter from the CEO" (an absolutely positioned
 * same-size sheet, rounded, tilted a few degrees behind the white card).
 *
 * Measured from the ICIEC prototype: at rest nothing shows (largest colour step
 * across the card's margin is 14 — a smooth glow, no edge). On hover a hard
 * edge appears (step jumps to 85) and the overhang grows linearly down the
 * right side, 2px at y=240 to 17px at y=660. Regressing that over 46 samples
 * gives 1.92deg, and the left side mirrors it at the top — i.e. the panel
 * swings counter-clockwise out from directly behind the card.
 *
 * Drawn as a pseudo-element on the inner wrapper, which boxes the card exactly,
 * so no extra markup is needed and no negative z-index is involved.
 */
.nlv3-ceo .nlv3-section__inner {
	position: relative;
}

.nlv3-ceo .nlv3-section__inner::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	border-radius: var(--nlv3-radius-lg);
	background: var(--nlv3-green-75);
	transform: rotate(0deg);
	transition: transform 0.45s ease;
	pointer-events: none;
}

/*
 * Desktop + real-hover only. The overhang scales with card height, and the
 * letter runs to ~4000px on a phone — a 2deg tilt there peeks ~70px against a
 * 32px gutter, so it would be sheared off by the section's overflow clip.
 * Touch devices have no hover to trigger it either way.
 */
@media (hover: hover) and (min-width: 992px) {
	.nlv3-ceo .nlv3-section__inner:hover::before,
	.nlv3-ceo .nlv3-section__inner:focus-within::before {
		transform: rotate(-2deg);
	}
}

/*
 * Heading row straight from the Figma node: portrait 328px | copy column, with
 * a 40px gap. Only the title, quote and opening paragraph live in the right
 * column — everything after drops to the full-width body below, which is why
 * this is a grid and not a text-wrap float.
 */
.nlv3-ceo__heading {
	display: grid;
	grid-template-columns: 328px minmax(0, 1fr);
	gap: 40px;
	align-items: start;
}

.nlv3-ceo__heading--no-portrait {
	grid-template-columns: minmax(0, 1fr);
}

/* Selector is doubled up on purpose: the `.nlv3 img` reset above scores
   (0,1,1), so a bare `.nlv3-ceo__portrait` (0,1,0) would lose out to that
   rule's `max-width: 100%`. */
.nlv3 .nlv3-ceo__portrait {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 328 / 395;
	object-fit: cover;
	object-position: top center;

	/* Centres the portrait when the heading row stacks on small screens
	   (max-width caps it below the column there); inert on desktop, where
	   the image fills its 328px grid column exactly. */
	margin: 0 auto;
}

.nlv3-ceo__heading-copy {
	min-width: 0;
}

/* The design's aside paragraph (beside the portrait) and the full-width body
   share one text style: Poppins 14/24 (1.7) on near-black. */
.nlv3-ceo__aside {
	margin-top: var(--nlv3-flow);
	color: var(--nlv3-ink-900);
	font-size: var(--nlv3-fs-body);
	font-weight: 400;
	line-height: 1.7;
	letter-spacing: var(--nlv3-track);
}

.nlv3-ceo__aside p {
	margin: 0;
	color: inherit;
	font-size: inherit;
	line-height: inherit;
	text-align: start;
}

.nlv3-ceo__title {
	margin: 0;
	padding: 0;
	color: var(--nlv3-ink-900);
	font-family: inherit;
	font-size: var(--nlv3-fs-title);
	font-weight: 400;
	line-height: 1.2;
	letter-spacing: var(--nlv3-track);
	text-transform: capitalize;
}

.nlv3-ceo__lead {
	margin: var(--nlv3-flow) 0 0;
	padding: 0 0 0 16px;
	border-left: 2px solid var(--nlv3-gold-300);
	border-radius: 1px;
}

[dir="rtl"] .nlv3-ceo__lead {
	padding: 0 16px 0 0;
	border-left: 0;
	border-right: 2px solid var(--nlv3-gold-300);
}

.nlv3-ceo__lead-text {
	margin: 0;
	color: var(--nlv3-green-400);
	font-size: var(--nlv3-fs-lead);
	font-weight: 400;
	line-height: 1.5;
	letter-spacing: var(--nlv3-track);

	/* The theme justifies blockquote/aside copy globally; in these columns
	   that opens rivers of white space, worst on phones. Ragged-right is the
	   design's alignment. text-align + logical start so RTL still mirrors. */
	text-align: start;
}

/*
 * Editors bold the whole opening paragraph in the WYSIWYG, which rendered the
 * quote at weight 700 and made the card read heavy. The design's quote is
 * regular — its emphasis comes from the green colour, larger size and gold
 * rule — so authored bolding is neutralised inside the quote only.
 */
.nlv3-ceo__lead-text strong,
.nlv3-ceo__lead-text b {
	font-weight: 400;
}

.nlv3-ceo__body {
	margin-top: var(--nlv3-flow);
	color: var(--nlv3-ink-900);
	font-size: var(--nlv3-fs-body);
	font-weight: 400;
	line-height: 1.7;
	letter-spacing: var(--nlv3-track);
}

.nlv3-ceo__body p {
	margin: 0 0 var(--nlv3-flow);
	color: inherit;
	font-size: inherit;
	line-height: inherit;
	text-align: inherit;
}

.nlv3-ceo__body p:last-child {
	margin-bottom: 0;
}

.nlv3-ceo__body a {
	color: var(--nlv3-green-400);
	text-decoration: underline;
}

.nlv3-ceo__body img {
	height: auto;
	border-radius: var(--nlv3-radius-md);
}

/*
 * Letters often close with their own authored sign-off ("Sincerely,
 * <h6>Name</h6> <small>Role</small>"). Browser defaults render that h6/small
 * pair tiny and cramped, so it is restyled to match the design's Name block —
 * the same treatment .nlv3-ceo__name/.nlv3-ceo__role give the field-driven
 * signature.
 */
.nlv3-ceo__body h6 {
	margin: var(--nlv3-flow) 0 0;
	color: var(--nlv3-ink-700);
	font-family: inherit;
	font-size: var(--nlv3-fs-name);
	font-weight: 400;
	line-height: 1.3;
	letter-spacing: var(--nlv3-track);
}

.nlv3-ceo__body small {
	display: block;
	margin-top: 8px;
	color: var(--nlv3-ink-500);
	font-size: var(--nlv3-fs-ui);
	line-height: 1.5;
	letter-spacing: var(--nlv3-track);
}

.nlv3-ceo__signature {
	margin-top: var(--nlv3-flow);
}

.nlv3-ceo__name {
	margin: 0;
	color: var(--nlv3-ink-700);
	font-size: var(--nlv3-fs-name);
	font-weight: 400;
	line-height: 1.3;
	letter-spacing: var(--nlv3-track);
}

.nlv3-ceo__role {
	margin: 8px 0 0;
	color: var(--nlv3-ink-500);
	font-size: var(--nlv3-fs-ui);
	font-weight: 400;
	line-height: 1.5;
	letter-spacing: var(--nlv3-track);
}

/* ==========================================================================
   Insights category filter tabs
   Figma node 511:16640 — 8px gap row of pills, 12px/8px padding, 8px radius.
   Selected: #056623 on white. Idle: Foundation/Neutral G40 on G100.
   ========================================================================== */

/*
 * Hidden until newsletter-v3.js adds `.nlv3-is-ready`, so the tabs are never
 * shown as controls that cannot act. Without JS every card stays visible,
 * which is the correct unfiltered view of the section.
 */
.nlv3-filters {
	display: none;
	flex-wrap: wrap;
	gap: 8px;
	margin: 0 0 var(--nlv3-gap);
}

.nlv3-filters.nlv3-is-ready {
	display: flex;
}

.nlv3-filters__tab {
	appearance: none;
	-webkit-appearance: none;
	margin: 0;
	padding: 8px 12px;
	border: 0;
	border-radius: var(--nlv3-radius-sm);
	background: var(--nlv3-neutral-40);
	color: var(--nlv3-neutral-100);
	font-family: inherit;
	font-size: var(--nlv3-fs-body);
	font-weight: 400;
	line-height: 1.5;
	letter-spacing: var(--nlv3-track);
	white-space: nowrap;
	cursor: pointer;
	transition: background-color 0.25s ease, color 0.25s ease;
}

.nlv3-filters__tab:hover {
	background: #d2d2d2;
	color: var(--nlv3-ink-500);
}

.nlv3-filters__tab.is-active,
.nlv3-filters__tab[aria-selected="true"] {
	background: var(--nlv3-green-400);
	color: var(--nlv3-surface);
}

.nlv3-filters__empty {
	margin: 0;
	padding: 8px 0;
	color: var(--nlv3-ink-300);
	font-size: var(--nlv3-fs-ui);
	line-height: 1.6;
}

/* Cards filtered out are removed from layout and from the a11y tree alike. */
.nlv3-grid__item[hidden] {
	display: none !important;
}

@media (max-width: 767.98px) {
	/*
	 * Phones: one swipeable row rather than a stack of wrapped pills, so the
	 * tabs never push the grid down the page. Scroll padding keeps the active
	 * pill clear of the edge when it is scrolled into view.
	 */
	.nlv3-filters {
		flex-wrap: nowrap;
		overflow-x: auto;
		scroll-snap-type: x proximity;
		scroll-padding-inline: 4px;
		scrollbar-width: none;
		-webkit-overflow-scrolling: touch;

		/* Bleed to the section gutters so the row reads as edge-to-edge. */
		margin-inline: calc(var(--nlv3-gutter) * -1);
		padding-inline: var(--nlv3-gutter);
	}

	.nlv3-filters::-webkit-scrollbar {
		display: none;
	}

	.nlv3-filters__tab {
		flex: 0 0 auto;
		scroll-snap-align: start;
	}
}

/* ==========================================================================
   Grids
   ========================================================================== */

.nlv3-grid {
	display: grid;
	gap: var(--nlv3-gap);
	margin: 0;
	padding: 0;
	list-style: none;
}

.nlv3-grid__item {
	display: flex;
	margin: 0;
	padding: 0;
	list-style: none;
}

.nlv3-grid__item::before,
.nlv3-grid__item::marker {
	content: none;
}

.nlv3-grid--insights {
	grid-template-columns: repeat(3, minmax(0, 1fr));

	/* 24px columns like the rest of the page; 40px between rows so a title
	   and the next row's image stay clearly separated without the old void. */
	gap: 40px 24px;
}

.nlv3-grid--news {
	grid-template-columns: repeat(4, minmax(0, 1fr));
}

/* ==========================================================================
   Cards (shared)
   ========================================================================== */

.nlv3-card {
	display: flex;
	width: 100%;
}

.nlv3-card__link {
	display: flex;
	flex-direction: column;
	width: 100%;
	color: inherit;
	text-decoration: none;
}

.nlv3-card__media {
	display: block;
	position: relative;
	width: 100%;
	overflow: hidden;
	background: var(--nlv3-surface-muted);
}

.nlv3-card__media--empty {
	background: linear-gradient(135deg, #ececec 0%, #f7f7f7 100%);
}

.nlv3-card__image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	transition: transform 0.5s ease;
}

.nlv3-card__link:hover .nlv3-card__image,
.nlv3-card__link:focus-visible .nlv3-card__image {
	transform: scale(1.04);
}

.nlv3-card__content {
	display: flex;
	flex: 1 0 auto;
	flex-direction: column;
	width: 100%;
}

.nlv3-card__title {
	margin: 0;
	padding: 0;
	color: var(--nlv3-ink-500);
	font-family: inherit;
	font-size: var(--nlv3-fs-ui);
	font-weight: 400;
	letter-spacing: var(--nlv3-track);

	/* Long headlines must not break the fixed tile height. */
	overflow-wrap: break-word;
	word-wrap: break-word;
}

.nlv3-card__link:hover .nlv3-card__title,
.nlv3-card__link:focus-visible .nlv3-card__title {
	color: var(--nlv3-green-400);
}

/* --- Insights tile -------------------------------------------------------- */

/*
 * Flush tile: media spans the full grid column and the title hangs directly
 * under it. The Figma tile wrapped both in 16px padding and reserved a 32px
 * action row plus a 160px content slot; without the action row those reserves
 * rendered as dead space between rows and doubled the visible gutters
 * (16 + 24 + 16), which made the section feel sparse. Hover feedback comes
 * from the image zoom and the green title, so no tile chrome is needed.
 */
/*
 * Hover, measured from the ICIEC prototype (file cG3yh…, Insights section):
 * a white surface fades in 16px *outward* around the card while the artwork
 * itself stays exactly where it is — image span was identical at rest and on
 * hover (136-487px both times), and 0 of 73,402 pixels inside the media box
 * changed, so the picture neither moves nor zooms.
 *
 * padding + equal negative margin is what buys that: the padding gives the
 * hover surface its 16px, the -16px margin pulls the box back so the resting
 * layout and grid rhythm are byte-identical to having no padding at all.
 */
/*
 * The hover surface is drawn by a pseudo-element rather than padding on the
 * link itself. `padding: 16px; margin: -16px` re-positioned the link correctly
 * but not its width — border-box sizing meant the padding ate into width:100%,
 * leaving the artwork 32px narrower than its grid column (most obvious on a
 * phone, where the card stopped well short of full width). An absolutely
 * positioned ::before at inset:-16px expands 16px outward for free and costs
 * the layout nothing, so the media always fills its column exactly.
 *
 * z-index:0 on the link gives the ::before a stacking context to sit inside,
 * so z-index:-1 puts it behind the card's own content without escaping behind
 * the section background.
 */
.nlv3-card--insight .nlv3-card__link {
	position: relative;
	z-index: 0;
	border-radius: var(--nlv3-radius-lg);
}

.nlv3-card--insight .nlv3-card__link::before {
	content: "";
	position: absolute;
	inset: -16px;
	z-index: -1;
	border-radius: var(--nlv3-radius-lg);
	background-color: transparent;
	transition: background-color 0.3s ease, box-shadow 0.3s ease;
	pointer-events: none;
}

.nlv3-card--insight .nlv3-card__link:hover,
.nlv3-card--insight .nlv3-card__link:focus-visible {
	/* Raise the hovered tile so its surface clears its neighbours. */
	z-index: 1;
}

.nlv3-card--insight .nlv3-card__link:hover::before,
.nlv3-card--insight .nlv3-card__link:focus-visible::before {
	background-color: var(--nlv3-surface);
	box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
}

.nlv3-card--insight .nlv3-card__link:hover .nlv3-card__title,
.nlv3-card--insight .nlv3-card__link:focus-visible .nlv3-card__title {
	color: var(--nlv3-green-300);
}

/* The prototype's insight artwork does not zoom on hover (measured above), so
   the shared card zoom is cancelled here only. */
.nlv3-card--insight .nlv3-card__link:hover .nlv3-card__image,
.nlv3-card--insight .nlv3-card__link:focus-visible .nlv3-card__image {
	transform: none;
}

.nlv3-card__media--insight {
	aspect-ratio: 588 / 370;
	border-radius: var(--nlv3-radius-md);
}

.nlv3-card--insight .nlv3-card__content {
	padding: 16px 0 0;
}

.nlv3-card--insight .nlv3-card__title {
	line-height: 1.5;
}

/*
 * Category badge pinned inside the media's top-left (Figma node 511:16640 —
 * 12px inset, same pill treatment as the active filter tab). It sits outside
 * the <img>, so the card's hover zoom scales the photo and leaves the label
 * steady. Logical inset so it mirrors to the right under RTL.
 */
.nlv3-card__badge {
	position: absolute;
	top: 12px;
	inset-inline-start: 12px;
	z-index: 2;
	max-width: calc(100% - 24px);
	padding: 8px 12px;
	border-radius: var(--nlv3-radius-sm);
	background: var(--nlv3-green-400);
	color: var(--nlv3-surface);
	font-size: var(--nlv3-fs-body);
	font-weight: 400;
	line-height: 1.5;
	letter-spacing: var(--nlv3-track);
	text-transform: capitalize;

	/* Long category names truncate rather than wrap over the artwork. */
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* --- News tile ------------------------------------------------------------ */

.nlv3-card--news .nlv3-card__link {
	border-radius: var(--nlv3-radius-sm);
	overflow: hidden;
	min-height: 320px;
}

.nlv3-card__media--news {
	height: 156px;
	flex: 0 0 156px;
	border-radius: var(--nlv3-radius-sm);
}

.nlv3-card--news .nlv3-card__content {
	justify-content: space-between;
	gap: 12px;
	padding: 16px 8px;
}

.nlv3-card--news .nlv3-card__title {
	line-height: 1.5;
}

.nlv3-card__date {
	display: block;
	color: var(--nlv3-ink-300);
	font-size: var(--nlv3-fs-small);
	line-height: 1.6;
	letter-spacing: var(--nlv3-track);
}

/* --- Project highlight card ----------------------------------------------- */

.nlv3-card--project .nlv3-card__link {
	gap: var(--nlv3-gap);
}

.nlv3-card__media--project {
	height: 427px;
	border-radius: var(--nlv3-radius-md);

	/* Lifts each card off the white section so the centred track reads as a
	   stack of distinct cards rather than a filmstrip. */
	box-shadow: 0 8px 24px rgba(0, 0, 0, 0.14);
	transition: box-shadow 0.3s ease;
}

.nlv3-card--project .nlv3-card__link:hover .nlv3-card__media--project,
.nlv3-card--project .nlv3-card__link:focus-visible .nlv3-card__media--project {
	box-shadow: 0 14px 34px rgba(0, 0, 0, 0.2);
}

.nlv3-card__arrow {
	position: absolute;
	right: 20px;
	bottom: 20px;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	border-radius: 49px;
	background: var(--nlv3-scrim);
	-webkit-backdrop-filter: blur(4px);
	backdrop-filter: blur(4px);
	transition: background-color 0.3s ease;
}

[dir="rtl"] .nlv3-card__arrow {
	right: auto;
	left: 20px;
}

[dir="rtl"] .nlv3-card__arrow img {
	transform: rotate(180deg);
}

.nlv3-card__arrow img {
	display: block;
	width: 24px;
	height: 24px;
	transition: transform 0.3s ease;
}

/*
 * Measured from the ICIEC prototype's Project Highlights card:
 * the arrow puck swaps its translucent black scrim for a solid green
 * (median #54A937 over 474 sampled pixels) and the glyph swings from
 * pointing right to pointing up-right, i.e. a 45deg counter-clockwise turn.
 * The glyph stays white throughout, and the puck keeps its 40px size and
 * bottom-right position — only the fill and the angle move.
 */
.nlv3-card__link:hover .nlv3-card__arrow,
.nlv3-card__link:focus-visible .nlv3-card__arrow {
	background: var(--nlv3-green-500);
}

.nlv3-card__link:hover .nlv3-card__arrow img,
.nlv3-card__link:focus-visible .nlv3-card__arrow img {
	transform: rotate(-45deg);
}

/* RTL rests at 180deg (pointing left), so the same 45deg turn lands at 225. */
[dir="rtl"] .nlv3-card__link:hover .nlv3-card__arrow img,
[dir="rtl"] .nlv3-card__link:focus-visible .nlv3-card__arrow img {
	transform: rotate(225deg);
}

.nlv3-card--project .nlv3-card__content {
	flex: 0 0 auto;
}

.nlv3-card--project .nlv3-card__title {
	line-height: 24px;
}

/*
 * Per-post art direction.
 * ---------------------------------------------------------------------------
 * Some project photos are framed badly by a straight `object-fit: cover` — the
 * Lagos-Calabar map, for instance, puts its subject well off to one side. Cards
 * carry their default-language slug as `data-nlv3-slug`, so a single item can
 * be re-framed here without touching PHP or the media library.
 *
 * The hover selector is repeated on purpose: the shared
 * `.nlv3-card__link:hover .nlv3-card__image` zoom scores higher than the
 * attribute selector alone would, and would otherwise snap the framing back
 * mid-hover.
 *
 * To re-frame another card, copy the block and swap the slug.
 */
.nlv3-card--project[data-nlv3-slug="iciec-lagos-calabar-coastal-highway"] .nlv3-card__image,
.nlv3-card--project[data-nlv3-slug="iciec-lagos-calabar-coastal-highway"] .nlv3-card__link:hover .nlv3-card__image,
.nlv3-card--project[data-nlv3-slug="iciec-lagos-calabar-coastal-highway"] .nlv3-card__link:focus-visible .nlv3-card__image {
	transform: scale(1.3) translateX(-37px);
}

/* ==========================================================================
   Sections: Insights / News / Projects
   ========================================================================== */

.nlv3-insights {
	/* Shares the News & Events surface so the two card sections read as one
	   continuous band rather than alternating white/grey stripes. */
	background: var(--nlv3-surface-muted);
}

.nlv3-news {
	background: var(--nlv3-surface-muted);
}

.nlv3-projects {
	background: var(--nlv3-surface);

	/* The slide track deliberately runs past the 1200px content column; this
	   clips the overhang at the viewport instead of adding a page scrollbar. */
	overflow: hidden;
}

.nlv3-projects__carousel {
	position: relative;
}

/*
 * Full-bleed track. `margin-inline: calc(50% - 50vw)` cancels both the 1200px
 * column's centring and the section gutter, expanding the swiper to the whole
 * viewport at any width. The gutter is then re-applied as padding so slide 0
 * still lines up with the section title on load — and because overflow clips at
 * the *padding* box, slides scrolled into that gutter stay visible, giving the
 * partial card at each edge the design shows.
 *
 * The carousel wrapper itself stays at column width, so the nav arrows keep
 * straddling the 1200px edges exactly as in Figma.
 */
.nlv3-projects__swiper {
	/* 50vw counts the scrollbar but the layout width does not, which drags the
	   track a few px left. --nlv3-sbw is measured in newsletter-v3.js and
	   cancels exactly that; the 0px fallback simply leaves the old drift. */
	margin-inline: calc(50% - 50vw + (var(--nlv3-sbw, 0px) / 2));
	/* Pad to wherever the 1200px content column actually starts, so the first
	   and last slides line up with the section title rather than sitting flush
	   against the viewport edge. Paired with `centeredSlidesBounds` in the JS,
	   which is what stops the bounds from being centred instead. */
	padding-inline: max(
		var(--nlv3-gutter),
		calc((100vw - var(--nlv3-sbw, 0px) - var(--nlv3-content)) / 2)
	);
	overflow: hidden;
}

.nlv3-projects__slide {
	/* 321px at the 1440 artboard (22.3vw), easing down on smaller screens and
	   capped so cards do not balloon on ultra-wide displays. */
	width: clamp(240px, 22.3vw, 340px);
	height: auto;
	flex: 0 0 auto;
}

/*
 * Progressive enhancement. Until (or unless) Swiper initialises, the track is a
 * native scroll-snap carousel: still horizontally swipeable, still a carousel.
 * Without this the section degrades into a clipped row of stacked cards with no
 * way to reach the rest whenever the Swiper CDN is blocked, slow, or reordered
 * by an optimiser plugin. `.nlv3-is-ready` is added by newsletter-v3.js the
 * moment Swiper takes over, at which point Swiper owns the scrolling.
 */
.nlv3-projects__swiper:not(.nlv3-is-ready) .swiper-wrapper {
	display: flex;
	gap: var(--nlv3-gap);
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	-webkit-overflow-scrolling: touch;

	/* Let the un-enhanced track bleed to the viewport edge like the design. */
	padding-bottom: 8px;
}

.nlv3-projects__swiper:not(.nlv3-is-ready) .swiper-wrapper::-webkit-scrollbar {
	display: none;
}

.nlv3-projects__swiper:not(.nlv3-is-ready) .nlv3-projects__slide {
	scroll-snap-align: start;
}

/*
 * Quantity query: when the track holds 4 slides or fewer they stretch to fill
 * the row rather than stopping short of the container edge. Mirrors the
 * slidesPerView cap in newsletter-v3.js so the enhanced and fallback paths
 * agree. Swiper writes inline widths once it initialises, so this only ever
 * governs the pre-init / no-JS state.
 */
.nlv3-projects__swiper:not(.nlv3-is-ready) .nlv3-projects__slide:first-child:nth-last-child(-n + 4),
.nlv3-projects__swiper:not(.nlv3-is-ready) .nlv3-projects__slide:first-child:nth-last-child(-n + 4) ~ .nlv3-projects__slide {
	width: auto;
	min-width: 0;
	flex: 1 1 0;
}

/* Arrows drive Swiper; with no Swiper there is nothing for them to drive. */
.nlv3-projects__swiper:not(.nlv3-is-ready) ~ .nlv3-projects__nav {
	display: none;
}

.nlv3-projects__nav {
	position: absolute;
	top: 213.5px; /* Vertical centre of the 427px media block. */
	z-index: 10;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 80px;
	height: 80px;
	padding: 0;
	border: 0;
	border-radius: 98px;
	background: var(--nlv3-frost);
	-webkit-backdrop-filter: blur(15.85px);
	backdrop-filter: blur(15.85px);
	color: var(--nlv3-ink-500);
	cursor: pointer;
	transform: translateY(-50%);
	transition: background-color 0.3s ease, opacity 0.3s ease;
}

.nlv3-projects__nav:hover {
	background: rgba(255, 255, 255, 0.8);
}

.nlv3-projects__nav img {
	display: block;
	width: 48px;
	height: 48px;
	pointer-events: none;
}

/* Logical offsets so the pair swaps sides automatically under RTL. */
.nlv3-projects__nav--prev {
	inset-inline-start: -40px;
}

.nlv3-projects__nav--next {
	inset-inline-end: -40px;
}

.nlv3-projects__nav--prev img {
	transform: rotate(180deg);
}

[dir="rtl"] .nlv3-projects__nav--prev img {
	transform: none;
}

[dir="rtl"] .nlv3-projects__nav--next img {
	transform: rotate(180deg);
}

/* Swiper adds this once every slide fits; hiding the controls avoids dead
   buttons on issues with only a couple of projects. */
.nlv3-projects__nav.swiper-button-disabled {
	opacity: 0.35;
	cursor: default;
	pointer-events: none;
}

.nlv3-projects__swiper.nlv3-is-locked + .nlv3-projects__nav,
.nlv3-projects__swiper.nlv3-is-locked ~ .nlv3-projects__nav {
	display: none;
}

/* Everything fits: centre the row so a short set reads as deliberate rather
   than as a track that ran out. */
.nlv3-projects__swiper.nlv3-is-locked .swiper-wrapper {
	justify-content: center;
}

/* ==========================================================================
   News PDF documents (legacy field, restyled)
   ========================================================================== */

.nlv3-news__documents {
	display: grid;
	gap: var(--nlv3-gap);
	margin-top: 40px;
}

.nlv3-document {
	padding: 24px;
	background: var(--nlv3-surface);
	border-radius: var(--nlv3-radius-md);
}

.nlv3-document__excerpt {
	color: var(--nlv3-ink-500);
	font-size: var(--nlv3-fs-ui);
	line-height: 1.6;
}

.nlv3-document__excerpt p {
	margin: 0 0 12px;
}

.nlv3-document__excerpt p:last-child {
	margin-bottom: 0;
}

.nlv3-document__link {
	display: inline-block;
	margin-top: 16px;
	color: var(--nlv3-green-400);
	font-size: var(--nlv3-fs-ui);
	font-weight: 600;
	line-height: 1.5;
}

.nlv3-document__link:hover {
	text-decoration: underline;
}

/* ==========================================================================
   Project highlights — legacy repeater fallback
   ========================================================================== */

.nlv3-projects__legacy {
	display: grid;
	gap: 40px;
}

.nlv3-legacy-highlight {
	display: grid;
	grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
	gap: var(--nlv3-gap);
	align-items: center;
}

.nlv3-legacy-highlight__media img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var(--nlv3-radius-md);
}

.nlv3-legacy-highlight__content {
	color: var(--nlv3-ink-500);
	font-size: var(--nlv3-fs-ui);
	line-height: 1.6;
}

/* ==========================================================================
   Download CTA
   ========================================================================== */

.nlv3-download {
	padding-top: 0;
	background: var(--nlv3-surface);
}

.nlv3-download__inner {
	display: flex;
	justify-content: center;
}

.nlv3-download__button {
	display: inline-flex;
	align-items: center;
	gap: 12px;
	padding: 14px 32px;
	background: var(--nlv3-green-400);
	border-radius: 999px;
	color: var(--nlv3-surface);
	font-size: var(--nlv3-fs-ui);
	font-weight: 500;
	line-height: 1.5;
	letter-spacing: var(--nlv3-track);
	transition: background-color 0.3s ease, transform 0.3s ease;
}

.nlv3-download__button:hover,
.nlv3-download__button:focus-visible {
	background: #044f1b;
	color: var(--nlv3-surface);
	transform: translateY(-2px);
}

/* Download glyph: a vertical stem plus a chevron, drawn from borders so the
   button needs no extra asset request. */
.nlv3-download__icon {
	position: relative;
	display: inline-block;
	width: 14px;
	height: 16px;
	flex: 0 0 14px;
}

.nlv3-download__icon::before {
	content: "";
	position: absolute;
	top: 0;
	left: 50%;
	width: 2px;
	height: 10px;
	background: currentColor;
	transform: translateX(-50%);
}

.nlv3-download__icon::after {
	content: "";
	position: absolute;
	top: 4px;
	left: 50%;
	width: 8px;
	height: 8px;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: translateX(-50%) rotate(45deg);
}

/* ==========================================================================
   Responsive
   ========================================================================== */

/* The site header is fixed below this width, so the hero must clear it by
   exactly its height — measured into --nlv3-header-h by newsletter-v3.js. The
   6.8rem fallback is the old V1/V2 `.make-top-spacing` value, used only if the
   script has not run. */
@media (max-width: 1200px) {
	.nlv3-hero {
		margin-top: var(--nlv3-header-h, 6.8rem);
	}
}

@media (max-width: 1199.98px) {
	/* The edition pill hangs ~41-44px below the hero while the fluid section
	   padding bottoms out at 40px, so below desktop the pill nearly touched
	   the letter card. Extra top padding on the CEO section (rather than a
	   hero margin) restores the gap while the section's green gradient keeps
	   filling the area behind the pill; at 1440 the 64px section padding
	   already leaves the design's 18px, so desktop is untouched. */
	.nlv3-hero {
		margin-bottom: 0;
	}

	.nlv3-ceo {
		padding-top: calc(var(--nlv3-section-y) + var(--nlv3-gap));
	}

	.nlv3-grid--news {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	.nlv3-projects__nav--prev {
		inset-inline-start: 0;
	}

	.nlv3-projects__nav--next {
		inset-inline-end: 0;
	}
}

@media (max-width: 991.98px) {
	/* Type sizes, section rhythm and card padding are fluid (see the clamp()
	   tokens on .nlv3), so this breakpoint only reshapes layout. */
	.nlv3-ceo__heading {
		grid-template-columns: 260px minmax(0, 1fr);
		gap: 24px;
	}

	.nlv3-ceo__heading--no-portrait {
		grid-template-columns: minmax(0, 1fr);
	}

	.nlv3-grid--insights {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.nlv3-grid--news {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.nlv3-projects__nav {
		width: 56px;
		height: 56px;
	}

	.nlv3-projects__nav img {
		width: 32px;
		height: 32px;
	}

	.nlv3-legacy-highlight {
		grid-template-columns: minmax(0, 1fr);
	}
}

@media (max-width: 767.98px) {
	/* Phone-only header offset, set explicitly rather than from the measured
	   --nlv3-header-h above. */
	.nlv3-hero {
		margin-top: 3.7rem;
	}

	.nlv3-hero__image {
		/* A squarer crop reads better than a 9:4 strip on phones — but only
		   when a dedicated mobile banner has actually been supplied. */
		aspect-ratio: 4 / 3;
	}

	/*
	 * No mobile banner set: the wide artwork is all we have, and cover-cropping
	 * it to 4:3 cuts the masthead off both edges. Dropping the forced ratio lets
	 * it render at its own proportions — shorter, but whole.
	 */
	.nlv3-hero__image--fit {
		aspect-ratio: auto;
		height: auto;
		object-fit: contain;
	}

	.nlv3-hero__edition {
		padding: 8px 32px;
	}

	/*
	 * Below this width the heading row stacks into an editorial lockup:
	 * a compact centred portrait, centred title, then the gold-ruled quote.
	 * The desktop 328/395 portrait crop is 289px tall at the 240px cap and
	 * pushed the letter a full viewport down; a square crop (object-position
	 * keeps the face) reclaims that height while the portrait stays prominent.
	 */
	.nlv3-ceo__heading {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--nlv3-flow);
	}

	.nlv3 .nlv3-ceo__portrait {
		width: min(60vw, 240px);
		aspect-ratio: 1 / 1;
		border-radius: var(--nlv3-radius-md);
	}

	.nlv3-ceo__title {
		text-align: center;
	}

	.nlv3-ceo__lead-text {
		line-height: 1.6;
	}

	.nlv3-grid--insights,
	.nlv3-grid--news {
		grid-template-columns: minmax(0, 1fr);
	}

	.nlv3-card--news .nlv3-card__link {
		min-height: 0;
	}

	.nlv3-card__media--project {
		height: 320px;
	}

	.nlv3-projects__nav {
		display: none;
	}

	.nlv3-download__button {
		width: 100%;
		justify-content: center;
	}
}

/* ==========================================================================
   Template-scoped site-chrome fixes
   Loaded only with this template; the body-class guard keeps every rule off
   the rest of the site. The theme's .navtop is already position:fixed at all
   widths (bundled styles), so no sticky restructuring is needed — but two
   things break the experience on this page:

   1. Logged-in admin bar: the theme pins `.admin-bar .navtop { top:30px }`.
      WordPress's real bar is 46px on small screens and, at <=600px, becomes
      position:absolute and scrolls away — leaving a permanent 30px band above
      the fixed header where page content shows through while scrolling.
      Visitors (no admin bar) are unaffected.

   2. The floating chat launcher (#chat-icon, 60px) crowds the reading column
      on phones.
   ========================================================================== */

@media (max-width: 782px) {
	/* WP admin bar is 46px and fixed in this range: sit flush beneath it. */
	body.admin-bar.newsletter-template-page-custom-newsletter-new-layout-v3 .navtop {
		top: 46px !important;
	}
}

@media (max-width: 600px) {
	/* WP admin bar is absolute here (scrolls away): the header owns the top.
	   At rest the bar briefly overlays the header's first 46px, which is the
	   standard WordPress trade-off for scroll-away bars. */
	body.admin-bar.newsletter-template-page-custom-newsletter-new-layout-v3 .navtop {
		top: 0 !important;
	}
}

@media (max-width: 767.98px) {
	/* Smaller, tucked-in chat launcher so it stops covering letter copy. */
	body.newsletter-template-page-custom-newsletter-new-layout-v3 #chat-icon {
		width: 48px !important;
		height: 48px !important;
		right: 12px !important;
		bottom: 12px !important;
	}

	body.newsletter-template-page-custom-newsletter-new-layout-v3 #chat-icon img,
	body.newsletter-template-page-custom-newsletter-new-layout-v3 #chat-icon svg {
		max-width: 60%;
		max-height: 60%;
	}
}

/* ==========================================================================
   Motion + print
   ========================================================================== */

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

@media print {
	.nlv3-projects__nav,
	.nlv3-download {
		display: none !important;
	}

	.nlv3-ceo__card {
		box-shadow: none;
		border: 1px solid #ddd;
	}

	.nlv3-projects__swiper {
		overflow: visible !important;
	}
}
