/* nu-bundle.css — generated by tools/build-css-bundle.sh, do not edit.
   Edit the individual sheets and rebuild. 2026-08-31 13:10 */

/* ============ nu-fonts.css ============ */
/* NÜ — polices auto-hébergées (remplace fonts.googleapis.com) */
@font-face {
  font-family: 'Spline Sans';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('../fonts/spline-sans-var-latin.woff2') format('woff2');
  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;
}
@font-face {
  font-family: 'Spline Sans';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('../fonts/spline-sans-var-latin-ext.woff2') format('woff2');
  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;
}
@font-face {
  font-family: 'Space Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/space-mono-400-latin.woff2') format('woff2');
  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;
}
@font-face {
  font-family: 'Space Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/space-mono-400-latin-ext.woff2') format('woff2');
  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;
}
@font-face {
  font-family: 'Space Mono';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/space-mono-400i-latin.woff2') format('woff2');
  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;
}
@font-face {
  font-family: 'Space Mono';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/space-mono-400i-latin-ext.woff2') format('woff2');
  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;
}
@font-face {
  font-family: 'Space Mono';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/space-mono-700-latin.woff2') format('woff2');
  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;
}
@font-face {
  font-family: 'Space Mono';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/space-mono-700-latin-ext.woff2') format('woff2');
  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;
}
@font-face {
  font-family: 'Space Mono';
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/space-mono-700i-latin.woff2') format('woff2');
  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;
}
@font-face {
  font-family: 'Space Mono';
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  src: url('../fonts/space-mono-700i-latin-ext.woff2') format('woff2');
  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;
}
/* ============ nu-section.css ============ */
/**
 * NÜ — the shared section rhythm, surfaces, and the automatic join.
 *
 * One place owns how far apart two sections sit. Every NÜ section element puts
 * `nu-section` and `nu-section--{surface}` on its root (see inc/nu-section.php),
 * and gets its vertical rhythm, its inline gutter and its surface colour from
 * here instead of restating them.
 *
 * The join: two sections in a row painted the same colour used to stack the
 * first one's bottom padding on top of the second one's top padding, so the gap
 * inside a single visual surface came out twice the size of the gap between two
 * different ones. The adjacency rules below drop the second section's top
 * padding, which leaves exactly one section's worth of space between the two
 * blocks of content. It works because every section renders as a direct sibling
 * of the next inside the Bricks content wrapper.
 *
 * Cascade notes, because they decide who wins:
 *
 *   - This sheet is a dependency of every element sheet, so it loads first and
 *     an element's own `.nu-*` rule beats it at equal specificity. An element
 *     that deviates from the rhythm declares only the variable it changes.
 *   - That also means an element-level `--nu-section-*` declaration outranks the
 *     media queries at the bottom of this file. An element that narrows its
 *     gutter on phones has to restate that inside its own breakpoint.
 *   - Bricks writes control CSS as `#brxe-{id} {…}` (1,0,0), which beats
 *     everything here — so a padding value typed in the builder wins over the
 *     automatic join, deliberately.
 *   - Defaults live in the `var(--x, fallback)` call rather than in a
 *     declaration, so nothing shadows a value set further down.
 *
 * @see inc/nu-section.php
 */

.nu-section {
	/* The rhythm. Change these two and every section moves together. */
	--nu-section-space: var(--space-3xl, 11.19rem);
	--nu-section-space-inline: var(--space-xl, 5.6rem);

	background-color: var(--nu-section-bg, transparent);

	/*
	 * --nu-section-join-pt is set only by the join rules below.
	 * --nu-section-pt / --nu-section-pb are for an element that genuinely sits
	 * on a different rhythm (a hero, a nav bar, a section designed to butt up
	 * against the one under it).
	 */
	padding-block:
		var(--nu-section-join-pt, var(--nu-section-pt, var(--nu-section-space)))
		var(--nu-section-pb, var(--nu-section-space));
	padding-inline: var(--nu-section-space-inline);
}

/* ------------------------------------------------------------- Surfaces */

/*
 * The four brand surfaces. The class is also what the join rule matches on, so
 * two sections only close up when they resolve to the same key here — a custom
 * colour set on one of them does not change the match.
 */
.nu-section--white {
	--nu-section-bg: var(--light, #fff);
}

.nu-section--purple {
	--nu-section-bg: var(--bg-surface, rgba(224, 220, 255, 0.3));
}

.nu-section--blue {
	--nu-section-bg: var(--color-4, #d7e3f5);
}

.nu-section--dark {
	--nu-section-bg: var(--color-3, #061745);
}

/*
 * Navy carrying a photograph under a flat overlay. It paints the same base as
 * `--dark` — the photo sits on top of it — but it is a separate key on purpose:
 * a picture and a flat colour do not read as one surface, so these must never
 * join with `--dark`, or with each other (two different photographs).
 *
 * That is why it is absent from the join rules below rather than listed there.
 */
.nu-section--dark-image {
	--nu-section-bg: var(--color-3, #061745);
}

/* ----------------------------------------------------------------- Join */

/*
 * Same surface as the section directly above → drop the top padding, so the two
 * read as one continuous surface with a single section's gap between them.
 *
 * Two opt-outs, both inside the selector rather than fighting it afterwards, so
 * there is no specificity race to lose:
 *
 *   .nu-section--join-never    on the second — this section keeps its padding.
 *   .nu-section--flush-bottom  on the first — that section ends with no bottom
 *                              padding of its own, so there would be no gap
 *                              left at all to inherit. The anchor-nav strip is
 *                              the one that does this.
 */
.nu-section--white:not(.nu-section--flush-bottom) + .nu-section--white:not(.nu-section--join-never),
.nu-section--purple:not(.nu-section--flush-bottom) + .nu-section--purple:not(.nu-section--join-never),
.nu-section--blue:not(.nu-section--flush-bottom) + .nu-section--blue:not(.nu-section--join-never),
.nu-section--dark:not(.nu-section--flush-bottom) + .nu-section--dark:not(.nu-section--join-never) {
	--nu-section-join-pt: 0px;
}

/*
 * Force the join on regardless of what is above — for a section that continues
 * the one before it across a surface change (a caption under a band, a list that
 * belongs to the block above it).
 */
.nu-section--join-always {
	--nu-section-join-pt: 0px;
}

/* --------------------------------------------------------------- Phones */

@media (max-width: 767px) {
	.nu-section {
		--nu-section-space-inline: var(--space-l, 3.96rem);
	}
}

/*
 * Below 478px the fluid --space-3xl has bottomed out at 39px, which is too tight
 * for a section break on a phone. --space-4xl at that width lands on 64px, and
 * the 1.2 lift takes it to ~77px — the value the most recently built sections
 * already used.
 */
@media (max-width: 478px) {
	.nu-section {
		--nu-section-space: calc(var(--space-4xl, 15.83rem) * 1.2);
	}
}

/* ============ nu-trio-1.css ============ */
/**
 * NÜ — Trio 1
 *
 * Built from the Figma "Trio-1" frame (1680 × 978).
 * All defaults use :where() so they carry zero specificity and any value set
 * through the Bricks builder (element controls, global classes, ID styles)
 * always wins.
 *
 * Figma → Core Framework token mapping (html font-size is 62.5%, so 1rem = 10px):
 *   headline   46px  → var(--text-2xl)      clamp(32px → 46px)
 *   paragraph  20px  → var(--text-m)        clamp(18px → 20px)
 *   card title 18px  → var(--text-tagline)  18px
 *   card text  16px  → var(--text-s)        clamp(14px → 16px)
 *   button     16px  → var(--text-button)   16px
 *   card radius 8px  → var(--radius-s)      clamp(6px → 8px)
 *   #0F18C6          → var(--text-title)
 *   #061745          → var(--color-3) / var(--dark)
 *   #E0DCFF          → var(--color-5)
 *   rgba(224,220,255,.3) over #FFF → var(--bg-surface)
 */

/* ---------------------------------------------------------------- Section */

:where(.nu-trio1) {
	display: flex;
	justify-content: center;
	width: 100%;
}

:where(.nu-trio1__inner) {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: clamp(3.2rem, 4.76vw, 8rem);
	width: 100%;
	max-width: 140rem;
}

/* -------------------------------------------------------------- Headlines */

:where(.nu-trio1__headlines) {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1.6rem;
	width: 100%;
}

:where(.nu-trio1__subtitle) {
	font-family: 'Inter', sans-serif;
	font-weight: 600;
	font-size: 1.4rem;
	line-height: 1.6rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	font-feature-settings: 'ss08' on;
	color: #2b2b2b;
}

:where(.nu-trio1__headline) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: var(--text-2xl, 4.6rem);
	line-height: 1.2;
	color: var(--text-title, #0f18c6);
}

:where(.nu-trio1__paragraph) {
	width: 100%;
	max-width: 92rem;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 400;
	font-size: var(--text-m, 2rem);
	line-height: 1.5;
	color: var(--color-3, #061745);
}

:where(.nu-trio1__paragraph > *:first-child) { margin-top: 0; }
:where(.nu-trio1__paragraph > *:last-child) { margin-bottom: 0; }

/* ------------------------------------------------------------------ Cards */

:where(.nu-trio1__list) {
	display: grid;
	/* Column count comes from the --nu-trio1-cols variable (set by the Columns
	   control) so the responsive rules below — which set grid-template-columns
	   directly at a higher specificity — always win on small screens, whatever
	   desktop count is chosen. */
	grid-template-columns: repeat(var(--nu-trio1-cols, 3), minmax(0, 1fr));
	gap: clamp(1.6rem, 1.9vw, 3.2rem);
	width: 100%;
}

:where(.nu-trio1__card) {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: space-between;
	gap: clamp(2.4rem, 2.38vw, 4rem);
	height: 100%;
	padding: clamp(3.2rem, 3.57vw, 6rem) clamp(2rem, 2.38vw, 4rem);
	background-color: var(--light, #fff);
	border-radius: var(--radius-s, 0.8rem);
}

:where(.nu-trio1__infos) {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 2.6rem;
	width: 100%;
}

/* ------------------------------------------------------------------- Icon */

:where(.nu-trio1__icon) {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: clamp(10rem, 8.33vw, 14rem);
	height: clamp(10rem, 8.33vw, 14rem);
	border-radius: clamp(2.8rem, 2.38vw, 4rem);
}

:where(.nu-trio1__icon--dark) {
	background-color: var(--dark, #061745);
	color: var(--color-5, #e0dcff);
}

:where(.nu-trio1__icon--light) {
	background-color: var(--color-5, #e0dcff);
	color: var(--dark, #061745);
}

:where(.nu-trio1__icon svg),
:where(.nu-trio1__icon > i) {
	width: clamp(4.4rem, 3.57vw, 6rem);
	height: clamp(4.4rem, 3.57vw, 6rem);
	font-size: clamp(4.4rem, 3.57vw, 6rem);
}

/* Recolour the Figma SVGs from the NÜ icon set. Presentation attributes such as
   fill="#061745" lose to any CSS rule, so currentColor takes over cleanly.
   Stroke is only touched where the source already declares one. */
.nu-trio1__icon svg path,
.nu-trio1__icon svg circle,
.nu-trio1__icon svg rect,
.nu-trio1__icon svg polygon {
	fill: currentColor;
}

.nu-trio1__icon svg [stroke]:not([stroke='none']) {
	stroke: currentColor;
}

/* ------------------------------------------------------------- Card texts */

:where(.nu-trio1__txt) {
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	gap: 1.6rem;
	width: 100%;
}

:where(.nu-trio1__card-title) {
	margin: 0;
	font-family: 'Space Mono', monospace;
	font-weight: 700;
	font-size: var(--text-tagline, 1.8rem);
	line-height: 1.1;
	text-align: center;
	text-transform: uppercase;
	color: var(--color-3, #061745);
}

:where(.nu-trio1__card-text) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 400;
	font-size: var(--text-s, 1.6rem);
	line-height: 1.5;
	text-align: center;
	color: var(--color-3, #061745);
}

/* ----------------------------------------------------------------- Button */

:where(.nu-trio1__button) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.8rem;
	flex: none;
	min-height: 4.8rem;
	padding: 1.2rem 2.4rem;
	border: 1px solid var(--color-3, #061745);
	border-radius: var(--radius-full, 3rem);
	font-family: 'Spline Sans', sans-serif;
	font-weight: 500;
	font-size: var(--text-button, 1.6rem);
	line-height: 2.4rem;
	text-decoration: none;
	color: var(--color-3, #061745);
	background-color: transparent;
	transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}

:where(.nu-trio1__button:hover),
:where(.nu-trio1__button:focus-visible) {
	background-color: var(--color-3, #061745);
	color: var(--light, #fff);
}

/* The label wraps to two lines on narrow cards (the French CTA is long), so
   centre it rather than letting it inherit the body's left alignment. */
:where(.nu-trio1__button-text) {
	text-align: center;
}

:where(.nu-trio1__button-icon) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 2.4rem;
	height: 2.4rem;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-trio1__button:hover .nu-trio1__button-icon,
.nu-trio1__button:focus-visible .nu-trio1__button-icon {
	transform: translateX(10px);
}

:where(.nu-trio1__button-icon svg) {
	width: 2.4rem;
	height: 2.4rem;
}

.nu-trio1__button-icon svg path,
.nu-trio1__button-icon svg circle,
.nu-trio1__button-icon svg rect,
.nu-trio1__button-icon svg polygon {
	fill: currentColor;
}

.nu-trio1__button-icon svg [stroke]:not([stroke='none']) {
	stroke: currentColor;
}

/* ------------------------------------------------------------ Breakpoints */

/* Below ~1100px a 3-up row squeezes the card narrower than its CTA, so the
   button would wrap to three lines. Two up first, one up on phones. */
@media (max-width: 1100px) {
	.nu-trio1__list {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 767px) {
	.nu-trio1__list {
		grid-template-columns: minmax(0, 1fr);
	}

	:where(.nu-trio1__card) {
		justify-content: flex-start;
	}
}

@media (max-width: 478px) {
	:where(.nu-trio1__headline),
	:where(.nu-trio1__paragraph) {
		text-align: left;
	}

	:where(.nu-trio1__button) {
		width: 100%;
	}
}

@media (prefers-reduced-motion: reduce) {
	.nu-trio1__button,
	.nu-trio1__button-icon {
		transition: none;
	}

	.nu-trio1__button:hover .nu-trio1__button-icon,
	.nu-trio1__button:focus-visible .nu-trio1__button-icon {
		transform: none;
	}
}

/* ============ nu-trio-2.css ============ */
/**
 * NÜ — Trio 2
 *
 * Sibling of Trio 1: same headline + paragraph + solution-card grid, but the
 * cards use a thick, faint blue frame instead of a solid fill and the grid
 * defaults to 5 columns. Built from the Figma "Solution Card" (5-up) frame.
 *
 * Zero-specificity :where() defaults so any builder value wins.
 *
 * Figma → Core Framework token mapping (html font-size 62.5%, 1rem = 10px):
 *   headline   46px → var(--text-2xl)
 *   paragraph  20px → var(--text-m)
 *   card title 18px → var(--text-tagline)
 *   card text  14px → var(--text-s)
 *   button     16px → var(--text-button)
 *   card radius 8px → var(--radius-s)
 *   card border    → 10px rgba(22,0,186,0.04)  (color-1 @ 4%)
 *   #0F18C6        → var(--text-title)
 *   #061745        → var(--color-3) / var(--dark)
 *   #E0DCFF        → var(--color-5)
 */

/* ---------------------------------------------------------------- Section */

:where(.nu-trio2) {
	display: flex;
	justify-content: center;
	width: 100%;
}

:where(.nu-trio2__inner) {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: clamp(3.2rem, 4.76vw, 8rem);
	width: 100%;
	max-width: 140rem;
}

/* -------------------------------------------------------------- Headlines */

:where(.nu-trio2__headlines) {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1.6rem;
	width: 100%;
}

:where(.nu-trio2__subtitle) {
	font-family: 'Inter', sans-serif;
	font-weight: 600;
	font-size: 1.4rem;
	line-height: 1.6rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	font-feature-settings: 'ss08' on;
	color: #2b2b2b;
}

:where(.nu-trio2__headline) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: var(--text-2xl, 4.6rem);
	line-height: 1.2;
	color: var(--text-title, #0f18c6);
}

:where(.nu-trio2__paragraph) {
	width: 100%;
	max-width: 92rem;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 400;
	font-size: var(--text-m, 2rem);
	line-height: 1.5;
	color: var(--color-3, #061745);
}

:where(.nu-trio2__paragraph > *:first-child) { margin-top: 0; }
:where(.nu-trio2__paragraph > *:last-child) { margin-bottom: 0; }

/* ------------------------------------------------------------------ Cards */

:where(.nu-trio2__list) {
	display: grid;
	/* Column count from --nu-trio2-cols (Columns control) so the responsive
	   rules below win on small screens at any desktop count. Defaults to 5. */
	grid-template-columns: repeat(var(--nu-trio2-cols, 5), minmax(0, 1fr));
	gap: clamp(1.6rem, 1.9vw, 3.2rem);
	width: 100%;
}

:where(.nu-trio2__card) {
	/* Named so the button can claim it back — see .nu-trio2__button. */
	--nu-trio2-card-pad-x: clamp(2rem, 2.38vw, 4rem);

	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: space-between;
	gap: clamp(2.4rem, 1.81vw, 2.6rem);
	height: 100%;
	padding: clamp(3.2rem, 3.57vw, 6rem) var(--nu-trio2-card-pad-x);
	background-color: transparent;
	/* Thick, very faint blue frame in place of a solid fill. */
	border: 1rem solid rgba(22, 0, 186, 0.04);
	border-radius: var(--radius-s, 0.8rem);
}

:where(.nu-trio2__infos) {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 2.6rem;
	width: 100%;
}

/* ------------------------------------------------------------------- Icon */

:where(.nu-trio2__icon) {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: clamp(10rem, 8.33vw, 14rem);
	height: clamp(10rem, 8.33vw, 14rem);
	border-radius: clamp(2.8rem, 2.38vw, 4rem);
}

:where(.nu-trio2__icon--dark) {
	background-color: var(--dark, #061745);
	color: var(--color-5, #e0dcff);
}

:where(.nu-trio2__icon--light) {
	background-color: var(--color-5, #e0dcff);
	color: var(--dark, #061745);
}

:where(.nu-trio2__icon svg),
:where(.nu-trio2__icon > i) {
	width: clamp(4.4rem, 3.57vw, 6rem);
	height: clamp(4.4rem, 3.57vw, 6rem);
	font-size: clamp(4.4rem, 3.57vw, 6rem);
}

.nu-trio2__icon svg path,
.nu-trio2__icon svg circle,
.nu-trio2__icon svg rect,
.nu-trio2__icon svg polygon {
	fill: currentColor;
}

.nu-trio2__icon svg [stroke]:not([stroke='none']) {
	stroke: currentColor;
}

/* ------------------------------------------------------------- Card texts */

:where(.nu-trio2__txt) {
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	gap: 1.6rem;
	width: 100%;
}

:where(.nu-trio2__card-title) {
	margin: 0;
	font-family: 'Space Mono', monospace;
	font-weight: 700;
	font-size: var(--text-tagline, 1.8rem);
	line-height: 1.1;
	text-align: center;
	text-transform: uppercase;
	color: var(--color-3, #061745);
}

:where(.nu-trio2__card-text) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 400;
	font-size: var(--text-s, 1.6rem);
	line-height: 1.5;
	text-align: center;
	color: var(--color-3, #061745);
}

/* ----------------------------------------------------------------- Button */

:where(.nu-trio2__button) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.8rem;
	flex: none;
	min-height: 4.8rem;
	padding: 1.2rem 2.4rem;
	border: 1px solid var(--color-3, #061745);
	border-radius: var(--radius-full, 3rem);
	font-family: 'Spline Sans', sans-serif;
	font-weight: 500;
	font-size: var(--text-button, 1.6rem);
	line-height: 2.4rem;
	/*
	 * The label used to be `white-space: nowrap`, on the assumption it would
	 * overhang the card padding by at most a few px. With a real CTA per card
	 * ("Renforcer l'engagement de vos audiences") it ran clear across its
	 * neighbours instead.
	 *
	 * So the button reclaims the card's horizontal padding — which is what the
	 * old overhang was really doing — and wraps only once even that is not
	 * enough. A short label like "En savoir plus" still sits on one line; a long
	 * one wraps inside the card instead of crossing into the next one.
	 */
	margin-inline: calc(var(--nu-trio2-card-pad-x, 0px) * -1);
	max-width: calc(100% + var(--nu-trio2-card-pad-x, 0px) * 2);
	text-decoration: none;
	color: var(--color-3, #061745);
	background-color: transparent;
	transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}

:where(.nu-trio2__button:hover),
:where(.nu-trio2__button:focus-visible) {
	background-color: var(--color-3, #061745);
	color: var(--light, #fff);
}

:where(.nu-trio2__button-text) {
	text-align: center;
}

:where(.nu-trio2__button-icon) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 2.4rem;
	height: 2.4rem;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-trio2__button:hover .nu-trio2__button-icon,
.nu-trio2__button:focus-visible .nu-trio2__button-icon {
	transform: translateX(10px);
}

:where(.nu-trio2__button-icon svg) {
	width: 2.4rem;
	height: 2.4rem;
}

.nu-trio2__button-icon svg path,
.nu-trio2__button-icon svg circle,
.nu-trio2__button-icon svg rect,
.nu-trio2__button-icon svg polygon {
	fill: currentColor;
}

.nu-trio2__button-icon svg [stroke]:not([stroke='none']) {
	stroke: currentColor;
}

/* ------------------------------------------------------------ Breakpoints */

/* 5-up is wide-desktop only; step down as width drops. */
@media (max-width: 1280px) {
	.nu-trio2__list {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

@media (max-width: 900px) {
	.nu-trio2__list {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 600px) {
	.nu-trio2__list {
		grid-template-columns: minmax(0, 1fr);
	}

	:where(.nu-trio2__card) {
		justify-content: flex-start;
	}
}

@media (max-width: 478px) {
	:where(.nu-trio2__headline),
	:where(.nu-trio2__paragraph) {
		text-align: left;
	}

	:where(.nu-trio2__button) {
		width: 100%;
	}
}

@media (prefers-reduced-motion: reduce) {
	.nu-trio2__button,
	.nu-trio2__button-icon {
		transition: none;
	}

	.nu-trio2__button:hover .nu-trio2__button-icon,
	.nu-trio2__button:focus-visible .nu-trio2__button-icon {
		transform: none;
	}
}

/* ============ nu-distinctions.css ============ */
/**
 * NÜ — Distinctions
 *
 * Dark section with a background video + navy overlay, a centered intro and a
 * 4-column grid of "distinction" items (orange icon + orange Space Mono tagline
 * + light centered text). The icon sits on top for odd columns and on the
 * bottom for even columns, then collapses to a single column on mobile.
 * Rebuilt for parity with the "Distinctions" Bricks template.
 *
 * Zero-specificity :where() defaults so any builder value wins. Colours that
 * must beat theme element rules use plain class selectors (0,1,0).
 *
 * Core Framework token mapping:
 *   heading  46px → var(--text-2xl)      color var(--color-5)
 *   tagline  → var(--text-l)  Space Mono 700 uppercase, color var(--color-2)
 *   text     → var(--text-m)  weight 300, color var(--color-5)
 *   overlay  → var(--color-3-90)  (navy @ 90%)
 *   button   → var(--color-2)  radius var(--radius-full)
 */

:where(.nu-distinctions) {
	position: relative;
	width: 100%;
	overflow: hidden;
	color: var(--color-5, #e0dcff);
	isolation: isolate;
}

/* Background video + overlay */
:where(.nu-distinctions__bg) {
	position: absolute;
	inset: 0;
	z-index: -2;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

:where(.nu-distinctions__overlay) {
	position: absolute;
	inset: 0;
	z-index: -1;
	background-color: var(--color-3-90, rgba(6, 23, 69, 0.9));
}

:where(.nu-distinctions__inner) {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-4xl, 15.83rem);
	width: 100%;
	max-width: 140rem;
	margin-inline: auto;
}

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

:where(.nu-distinctions__intro) {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-m, 2.8rem);
	width: 100%;
}

:where(.nu-distinctions__heading) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: var(--text-2xl, 4.6rem);
	line-height: 1.2;
	text-align: center;
	color: var(--color-5, #e0dcff);
}

:where(.nu-distinctions__text) {
	margin: 0;
	max-width: 82rem;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 400;
	font-size: var(--text-m, 2rem);
	line-height: 1.5;
	text-align: center;
	color: var(--color-5, #e0dcff);
}

:where(.nu-distinctions__text > *:first-child) { margin-top: 0; }
:where(.nu-distinctions__text > *:last-child) { margin-bottom: 0; }

/* ------------------------------------------------------------------ Grid */

:where(.nu-distinctions__grid) {
	display: grid;
	grid-template-columns: repeat(var(--nu-distinctions-cols, 4), minmax(0, 1fr));
	align-items: center;
	gap: var(--space-2xl, 7.92rem) var(--space-xl, 5.6rem);
	width: 100%;
}

:where(.nu-distinctions__item) {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-s, 1.98rem);
	width: 100%;
	text-align: center;
}

/* Icon on the bottom for even columns. */
:where(.nu-distinctions__item:nth-child(even) .nu-distinctions__item-icon) {
	order: 2;
}

:where(.nu-distinctions__item-icon) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	color: var(--color-2, #ef4400);
}

:where(.nu-distinctions__item-icon svg) {
	width: auto;
	height: clamp(3.6rem, 3.5vw, 4.4rem);
}

.nu-distinctions__item-icon svg circle,
.nu-distinctions__item-icon svg path,
.nu-distinctions__item-icon svg rect,
.nu-distinctions__item-icon svg polygon {
	fill: currentColor;
}

.nu-distinctions__item-icon svg [stroke]:not([stroke='none']) {
	stroke: currentColor;
}

:where(.nu-distinctions__item-tagline) {
	margin: 0;
	font-family: 'Space Mono', monospace;
	font-weight: 700;
	font-size: var(--text-l, 2.2rem);
	line-height: 1.2;
	text-transform: uppercase;
	text-align: center;
	color: var(--color-2, #ef4400);
}

:where(.nu-distinctions__item-text) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: var(--text-m, 2rem);
	line-height: 1.5;
	text-align: center;
	color: var(--color-5, #e0dcff);
}

/* ---------------------------------------------------------------- Button */

:where(.nu-distinctions__button) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.8rem;
	flex: none;
	min-height: 4.8rem;
	padding: 1.2rem 2.4rem;
	border: 1px solid transparent;
	border-radius: var(--radius-full, 3rem);
	font-family: 'Spline Sans', sans-serif;
	font-weight: 500;
	font-size: var(--text-button, 1.6rem);
	line-height: 2.4rem;
	white-space: nowrap;
	text-decoration: none;
	color: var(--light, #fff);
	background-color: var(--color-2, #ef4400);
	transition: background-color 0.25s ease, color 0.25s ease;
}

/* Orange goes to brand blue on hover, as the home hero does. */
:where(.nu-distinctions__button:hover),
:where(.nu-distinctions__button:focus-visible) {
	background-color: var(--color-1, #1600ba);
}

:where(.nu-distinctions__button-icon) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 2.4rem;
	height: 2.4rem;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-distinctions__button:hover .nu-distinctions__button-icon,
.nu-distinctions__button:focus-visible .nu-distinctions__button-icon {
	transform: translateX(10px);
}

:where(.nu-distinctions__button-icon svg) {
	width: 2.4rem;
	height: 2.4rem;
}

.nu-distinctions__button-icon svg path,
.nu-distinctions__button-icon svg circle,
.nu-distinctions__button-icon svg rect,
.nu-distinctions__button-icon svg polygon {
	fill: currentColor;
}

.nu-distinctions__button-icon svg [stroke]:not([stroke='none']) {
	stroke: currentColor;
}

/* --------------------------------------------- Color specificity lift ---
 * Theme styles headings at element specificity; these class rules (0,1,0)
 * beat it yet still lose to a Bricks ID-based control override. */
.nu-distinctions__heading,
.nu-distinctions__item-text {
	color: var(--color-5, #e0dcff);
}

.nu-distinctions__item-tagline {
	color: var(--color-2, #ef4400);
}

.nu-distinctions__button {
	color: var(--light, #fff);
}

/* ------------------------------------------------------------ Breakpoints */

@media (max-width: 991px) {
	:where(.nu-distinctions__grid) {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 600px) {
	:where(.nu-distinctions__grid) {
		grid-template-columns: minmax(0, 1fr);
	}

	/* Icon back on top for every card once stacked. */
	:where(.nu-distinctions__item:nth-child(even) .nu-distinctions__item-icon) {
		order: 0;
	}

	:where(.nu-distinctions__button) {
		width: 100%;
		white-space: normal;
	}
}

@media (prefers-reduced-motion: reduce) {
	.nu-distinctions__button,
	.nu-distinctions__button-icon {
		transition: none;
	}

	.nu-distinctions__button:hover .nu-distinctions__button-icon,
	.nu-distinctions__button:focus-visible .nu-distinctions__button-icon {
		transform: none;
	}
}

/* ============ nu-recompenses.css ============ */
/**
 * NÜ — Récompenses
 *
 * A left-aligned headline over a wrapping row of award cards: each card is a
 * bordered "visu" box holding a logo, with a Space Mono caption beneath.
 * Built from the Figma "Récompenses" frame (1680 × 599).
 *
 * Zero-specificity :where() defaults so any builder value wins.
 *
 * Figma → Core Framework token mapping (html font-size 62.5%, 1rem = 10px):
 *   headline 46px → var(--text-2xl)      color var(--text-title)
 *   caption  18px → var(--text-tagline)  Space Mono 700, color var(--color-3)
 *   card radius 8px → var(--radius-s)
 *   card border    → 10px rgba(15,24,198,0.04)  (text-title @ 4%)
 */

:where(.nu-recompenses) {
	display: flex;
	justify-content: center;
	width: 100%;
}

:where(.nu-recompenses__inner) {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: clamp(3.2rem, 3.5vw, 5rem);
	width: 100%;
	max-width: 140rem;
}

/* -------------------------------------------------------------- Headlines */

:where(.nu-recompenses__headlines) {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1.6rem;
	width: 100%;
}

:where(.nu-recompenses__subtitle) {
	font-family: 'Inter', sans-serif;
	font-weight: 600;
	font-size: 1.4rem;
	line-height: 1.6rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	font-feature-settings: 'ss08' on;
	color: #2b2b2b;
}

:where(.nu-recompenses__headline) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: var(--text-2xl, 4.6rem);
	line-height: 1.2;
	color: var(--text-title, #0f18c6);
}

/* ------------------------------------------------------------------ Cards */

:where(.nu-recompenses__list) {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: var(--space-2xl, 5rem) 3.2rem;
	width: 100%;
}

:where(.nu-recompenses__card) {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 3.2rem;
	flex: 0 0 auto;
	width: min(33.6rem, 100%);
}

:where(.nu-recompenses__visu) {
	box-sizing: border-box;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	min-height: 19.8rem;
	padding: 4rem;
	overflow: hidden;
	/* Thick, very faint blue frame (text-title @ 4%). */
	border: 1rem solid rgba(15, 24, 198, 0.04);
	border-radius: var(--radius-s, 0.8rem);
}

:where(.nu-recompenses__image) {
	display: block;
	width: auto;
	height: auto;
	max-width: 100%;
	max-height: 11.8rem;
	object-fit: contain;
}

:where(.nu-recompenses__visu--empty) {
	min-height: 19.8rem;
}

:where(.nu-recompenses__caption) {
	margin: 0;
	font-family: 'Space Mono', monospace;
	font-weight: 700;
	font-size: var(--text-tagline, 1.8rem);
	line-height: 1.1;
	text-align: center;
	text-transform: uppercase;
	color: var(--color-3, #061745);
}

/* ----------------------------------------------- Color specificity lift -
 * The theme styles headings (`h2{color:var(--color-1)}`) at element
 * specificity, which beats a :where() default. This class rule (0,1,0) wins
 * yet still loses to a Bricks ID-based control override. */
.nu-recompenses__headline {
	color: var(--text-title, #0f18c6);
}

.nu-recompenses__caption {
	color: var(--color-3, #061745);
}

/* ------------------------------------------------------------ Breakpoints */

@media (max-width: 767px) {
	:where(.nu-recompenses__list) {
		justify-content: center;
	}

	:where(.nu-recompenses__headline) {
		text-align: left;
	}
}

/* ============ nu-ciblages.css ============ */
/**
 * NÜ — Ciblages
 *
 * Dark section over a fixed background image + navy overlay: a centered intro,
 * a row of frosted-glass cards (icon + tagline + asterisk-separated list) and a
 * primary CTA. On phones the cards become a horizontal snap carousel.
 * Rebuilt for parity with the "Ciblages" Bricks template.
 *
 * Zero-specificity :where() defaults so any builder value wins. Colours that
 * must beat theme element rules use plain class selectors (0,1,0).
 *
 * Token mapping:
 *   heading  → var(--text-2xl)  color var(--light)
 *   intro    → var(--text-m)     color var(--light)
 *   tagline  → 2.2rem Space Mono 700 uppercase, color var(--color-5)
 *   list     → var(--text-s)     color var(--color-5)
 *   overlay  → var(--color-3-70) (navy @ 70%)
 *   card     → 1px var(--border-primary), radius-l, backdrop-blur(20px)
 *   icon/CTA → var(--color-2)
 */

:where(.nu-ciblages) {
	--nu-ciblages-overlay: var(--color-3-70, rgba(6, 23, 69, 0.7));

	position: relative;
	width: 100%;
	overflow: hidden;
	background-image: var(--nu-ciblages-image);
	background-size: cover;
	background-position: center;
	background-attachment: fixed;
	color: var(--color-5, #e0dcff);
	isolation: isolate;
}

.nu-ciblages::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: -1;
	background-color: var(--nu-ciblages-overlay);
}

:where(.nu-ciblages__inner) {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: clamp(4rem, 4.5vw, 6rem);
	width: 100%;
	max-width: 140rem;
	margin-inline: auto;
}

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

:where(.nu-ciblages__intro) {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-m, 2.8rem);
	width: 100%;
}

:where(.nu-ciblages__heading) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: var(--text-2xl, 4.6rem);
	line-height: 1.2;
	text-align: center;
	color: var(--light, #fff);
}

:where(.nu-ciblages__text) {
	margin: 0;
	max-width: 80rem;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 400;
	font-size: var(--text-m, 2rem);
	line-height: 1.5;
	text-align: center;
	color: var(--light, #fff);
}

:where(.nu-ciblages__text > *:first-child) { margin-top: 0; }
:where(.nu-ciblages__text > *:last-child) { margin-bottom: 0; }

/* ------------------------------------------------------------------ Grid */

:where(.nu-ciblages__grid) {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	align-items: stretch;
	gap: var(--space-s, 1.98rem);
	width: 100%;
}

/* Frosted-glass card */
:where(.nu-ciblages__card) {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-m, 2.8rem);
	padding: var(--space-2xl, 7.92rem) var(--space-l, 3.96rem);
	border: 1px solid var(--border-primary, rgba(224, 220, 255, 0.3));
	border-radius: var(--radius-l, 2rem);
	background-color: rgba(255, 255, 255, 0.01);
	-webkit-backdrop-filter: blur(20px);
	backdrop-filter: blur(20px);
}

:where(.nu-ciblages__icon) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	color: var(--color-2, #ef4400);
}

:where(.nu-ciblages__icon svg) {
	width: auto;
	height: clamp(5.6rem, 5vw, 6.5rem);
	max-width: 7rem;
}

.nu-ciblages__icon svg path,
.nu-ciblages__icon svg circle,
.nu-ciblages__icon svg rect,
.nu-ciblages__icon svg polygon {
	fill: currentColor;
}

.nu-ciblages__icon svg [stroke]:not([stroke='none']) {
	stroke: currentColor;
}

:where(.nu-ciblages__tagline) {
	margin: 0;
	font-family: 'Space Mono', monospace;
	font-weight: 700;
	font-size: 2.2rem;
	line-height: 1.2;
	text-transform: uppercase;
	text-align: center;
	color: var(--color-5, #e0dcff);
}

/* Asterisk-separated list */
:where(.nu-ciblages__list) {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.8rem;
	width: 100%;
	font-family: 'Spline Sans', sans-serif;
	font-size: var(--text-s, 1.6rem);
	line-height: 1.4;
	text-align: center;
	color: var(--color-5, #e0dcff);
}

:where(.nu-ciblages__sep) {
	color: var(--color-5, #e0dcff);
	opacity: 0.6;
}

/* ---------------------------------------------------------------- Button */

:where(.nu-ciblages__button) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.8rem;
	flex: none;
	min-height: 4.8rem;
	padding: 1.2rem 2.4rem;
	border: 1px solid transparent;
	border-radius: var(--radius-full, 3rem);
	font-family: 'Spline Sans', sans-serif;
	font-weight: 500;
	font-size: var(--text-button, 1.6rem);
	line-height: 2.4rem;
	white-space: nowrap;
	text-decoration: none;
	color: var(--light, #fff);
	background-color: var(--color-2, #ef4400);
	transition: background-color 0.25s ease, color 0.25s ease;
}

/* Orange goes to brand blue on hover, as the home hero does. */
:where(.nu-ciblages__button:hover),
:where(.nu-ciblages__button:focus-visible) {
	background-color: var(--color-1, #1600ba);
}

:where(.nu-ciblages__button-icon) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 2.4rem;
	height: 2.4rem;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-ciblages__button:hover .nu-ciblages__button-icon,
.nu-ciblages__button:focus-visible .nu-ciblages__button-icon {
	transform: translateX(10px);
}

:where(.nu-ciblages__button-icon svg) {
	width: 2.4rem;
	height: 2.4rem;
}

.nu-ciblages__button-icon svg path,
.nu-ciblages__button-icon svg circle,
.nu-ciblages__button-icon svg rect,
.nu-ciblages__button-icon svg polygon {
	fill: currentColor;
}

.nu-ciblages__button-icon svg [stroke]:not([stroke='none']) {
	stroke: currentColor;
}

/* --------------------------------------------- Color specificity lift ---
 * Theme styles headings at element specificity; these class rules (0,1,0)
 * beat it yet still lose to a Bricks ID-based control override. */
.nu-ciblages__heading,
.nu-ciblages__text {
	color: var(--light, #fff);
}

.nu-ciblages__tagline {
	color: var(--color-5, #e0dcff);
}

.nu-ciblages__button {
	color: var(--light, #fff);
}

/* ------------------------------------------------------------ Breakpoints */

@media (max-width: 991px) {
	:where(.nu-ciblages__grid) {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* Phones: horizontal snap carousel. */
@media (max-width: 767px) {
	:where(.nu-ciblages__grid) {
		display: flex;
		flex-wrap: nowrap;
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		gap: var(--space-m, 2.8rem);
		margin-inline: calc(clamp(2rem, 5vw, 4rem) * -1);
		padding-inline: clamp(2rem, 5vw, 4rem);
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
	}

	:where(.nu-ciblages__grid)::-webkit-scrollbar {
		display: none;
	}

	:where(.nu-ciblages__card) {
		flex: 0 0 auto;
		width: 80%;
		scroll-snap-align: center;
	}

	:where(.nu-ciblages) {
		background-attachment: scroll;
	}

	:where(.nu-ciblages__button) {
		width: 100%;
	}
}

@media (prefers-reduced-motion: reduce) {
	.nu-ciblages__button,
	.nu-ciblages__button-icon {
		transition: none;
	}

	.nu-ciblages__button:hover .nu-ciblages__button-icon,
	.nu-ciblages__button:focus-visible .nu-ciblages__button-icon {
		transform: none;
	}
}

/* ============ nu-cadre-ethique.css ============ */
/**
 * NÜ — Cadre éthique
 *
 * Dark section (solid navy / optional image + navy overlay): a centered intro
 * and a 3-column grid of items — a lavender-tinted icon box, a big orange
 * Space Mono tagline, a divider and a paragraph. Thin vertical rules sit in the
 * gaps between columns. Rebuilt for parity with the "Cadre éthique" template.
 *
 * Zero-specificity :where() defaults; colours that must beat theme element
 * rules use plain class selectors (0,1,0).
 *
 * Token mapping:
 *   heading  → var(--text-2xl)  color var(--color-5)
 *   intro    → var(--text-m)    color var(--color-5)
 *   tagline  → var(--text-xl) Space Mono 700 uppercase, color var(--color-2)
 *   text     → var(--text-m) weight 300, color var(--color-5)
 *   overlay  → var(--color-3-90) (navy @ 90%)
 *   icon box → var(--color-5-10) bg, radius-xl; icon var(--color-2)
 */

:where(.nu-cadre-ethique) {
	--nu-cadre-overlay: var(--color-3-90, rgba(6, 23, 69, 0.9));

	position: relative;
	width: 100%;
	overflow: hidden;
	background-image: var(--nu-cadre-image);
	background-size: cover;
	background-position: center;
	color: var(--color-5, #e0dcff);
	isolation: isolate;
}

/* Optional background video — sits above the image (its fallback), below the
   overlay. Same layering as nu-distinctions' video. */
:where(.nu-cadre-ethique__bg) {
	position: absolute;
	inset: 0;
	z-index: -2;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.nu-cadre-ethique::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: -1;
	background-color: var(--nu-cadre-overlay);
}

:where(.nu-cadre-ethique__inner) {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-3xl, 11.19rem);
	width: 100%;
	max-width: 140rem;
	margin-inline: auto;
}

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

:where(.nu-cadre-ethique__intro) {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-m, 2.8rem);
	width: 100%;
}

:where(.nu-cadre-ethique__heading) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: var(--text-2xl, 4.6rem);
	line-height: 1.2;
	text-align: center;
	color: var(--color-5, #e0dcff);
}

:where(.nu-cadre-ethique__text) {
	margin: 0;
	max-width: 90rem;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 400;
	font-size: var(--text-m, 2rem);
	line-height: 1.5;
	text-align: center;
	color: var(--color-5, #e0dcff);
}

:where(.nu-cadre-ethique__text > *:first-child) { margin-top: 0; }
:where(.nu-cadre-ethique__text > *:last-child) { margin-bottom: 0; }

/* ------------------------------------------------------------------ Grid */

:where(.nu-cadre-ethique__grid) {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	align-items: start;
	gap: var(--space-3xl, 11.19rem);
	width: 100%;
}

:where(.nu-cadre-ethique__item) {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-s, 1.98rem);
	width: 100%;
	text-align: center;
}

/* Thin vertical rule sitting in the gap to the right of each item. */
.nu-cadre-ethique__item:not(:last-child)::after {
	content: '';
	position: absolute;
	right: calc(var(--space-3xl, 11.19rem) * -0.5);
	top: 15rem;
	width: 1px;
	height: 6rem;
	background-color: var(--light-30, rgba(255, 255, 255, 0.3));
}

/* Icon box */
:where(.nu-cadre-ethique__icon-box) {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: clamp(11rem, 11vw, 14rem);
	height: clamp(11rem, 11vw, 14rem);
	margin-bottom: var(--space-m, 2.8rem);
	border-radius: var(--radius-xl, 3.2rem);
	background-color: var(--color-5-10, rgba(224, 220, 255, 0.1));
	color: var(--color-2, #ef4400);
}

:where(.nu-cadre-ethique__icon-box svg) {
	width: auto;
	height: clamp(5.2rem, 4.8vw, 6.4rem);
	max-width: 6.4rem;
}

.nu-cadre-ethique__icon-box svg path,
.nu-cadre-ethique__icon-box svg circle,
.nu-cadre-ethique__icon-box svg rect,
.nu-cadre-ethique__icon-box svg polygon {
	fill: currentColor;
}

.nu-cadre-ethique__icon-box svg [stroke]:not([stroke='none']) {
	stroke: currentColor;
}

:where(.nu-cadre-ethique__tagline) {
	margin: 0;
	font-family: 'Space Mono', monospace;
	font-weight: 700;
	font-size: var(--text-xl, 3.2rem);
	line-height: 1.1;
	text-transform: uppercase;
	text-align: center;
	color: var(--color-2, #ef4400);
}

/* Detail: divider + paragraph */
:where(.nu-cadre-ethique__detail) {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-l, 3.96rem);
	width: 100%;
	margin-top: var(--space-2xl, 7.92rem);
}

:where(.nu-cadre-ethique__divider) {
	width: 100%;
	height: 1px;
	margin: 0;
	border: 0;
	background-color: var(--light-30, rgba(255, 255, 255, 0.3));
}

:where(.nu-cadre-ethique__text-item) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: var(--text-m, 2rem);
	line-height: 1.5;
	text-align: center;
	color: var(--color-5, #e0dcff);
}

/* --------------------------------------------- Color specificity lift ---
 * Theme styles headings at element specificity; these class rules (0,1,0)
 * beat it yet still lose to a Bricks ID-based control override. */
.nu-cadre-ethique__heading,
.nu-cadre-ethique__text,
.nu-cadre-ethique__text-item {
	color: var(--color-5, #e0dcff);
}

.nu-cadre-ethique__tagline {
	color: var(--color-2, #ef4400);
}

/* ------------------------------------------------------------ Breakpoints */

/* Text-heavy items read better stacked; drop the vertical rules too. */
@media (max-width: 991px) {
	:where(.nu-cadre-ethique__grid) {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--space-2xl, 7.92rem);
		max-width: 52rem;
		margin-inline: auto;
	}

	.nu-cadre-ethique__item:not(:last-child)::after {
		display: none;
	}

	:where(.nu-cadre-ethique__detail) {
		margin-top: var(--space-l, 3.96rem);
	}
}

/* ============ nu-overview.css ============ */
/**
 * NÜ — Overview
 *
 * Full-bleed banner: a background image under a flat dark tint, with a centred
 * column holding a headline, a paragraph and one primary CTA. Built from the
 * Figma "Overview" frame (1680 × 517).
 *
 * No :where() on the defaults — it is zero-specificity, so the headline would
 * lose to Bricks' bare h1–h6 theme styles.
 *
 * Figma → Core Framework token mapping (html font-size 62.5%, 1rem = 10px):
 *   section padding   120px    → var(--space-3xl) / clamp down on small screens
 *   content width     790px    → 79rem
 *   copy gap          24px     → var(--space-m)
 *   content ↔ button  60px     → clamp(3.2rem → 6rem)
 *   headline   46px/120%       → var(--text-2xl)   clamp(32px → 46px)
 *   paragraph  20px/150%       → var(--text-m)     clamp(18px → 20px)
 *   button     16px/24px       → var(--text-button)
 *   #061745 @ 70%              → var(--color-3) / var(--dark)
 *   button orange              → var(--color-2)   (Figma #EE5101)
 */

/* --------------------------------------------------------------- Section */

.nu-overview {
	/* Default background — shipped theme asset, resolved relative to this file.
	   The render layer overrides this variable when an image is chosen. */
	--nu-overview-image: url('../img/nu-overview-bg.webp');
	/* Flat tint over the whole image, not a gradient: the copy is centred, so
	   every part of the frame sits under text. */
	--nu-overview-overlay-color: rgba(6, 23, 69, 0.7);

	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	width: 100%;
	/* Its own fluid gutter: the copy is centred on the photo, not lined up
	   with the text column of the sections around it. */
	--nu-section-space-inline: clamp(2.4rem, 7.14vw, 12rem);
	overflow: hidden;
	background-image: var(--nu-overview-image);
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
	isolation: isolate;
}

/* Tint: above the image, below the content. */
.nu-overview::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: -1;
	background-color: var(--nu-overview-overlay-color);
}

/* ------------------------------------------------------------------ Inner */

.nu-overview__inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: clamp(3.2rem, 4.17vw, 6rem);
	width: 100%;
	max-width: 79rem;
}

.nu-overview__txt {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-m, 2.4rem);
	width: 100%;
	text-align: center;
}

/* --------------------------------------------------------------- Content */

.nu-overview__headline {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: var(--text-2xl, 4.6rem);
	line-height: 1.2;
	color: var(--light, #fff);
}

.nu-overview__paragraph {
	margin: 0;
	font-family: 'Inter', sans-serif;
	font-weight: 400;
	font-size: var(--text-m, 2rem);
	line-height: 1.5;
	color: var(--light, #fff);
}

.nu-overview__paragraph > *:first-child { margin-top: 0; }
.nu-overview__paragraph > *:last-child { margin-bottom: 0; }

/* ---------------------------------------------------------------- Button */

.nu-overview__button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.8rem;
	flex: none;
	min-height: 4.8rem;
	padding: 1.2rem 2.4rem;
	border: 1px solid transparent;
	border-radius: var(--radius-full, 3rem);
	font-family: 'Spline Sans', sans-serif;
	font-weight: 500;
	font-size: var(--text-button, 1.6rem);
	line-height: 2.4rem;
	text-decoration: none;
	color: var(--light, #fff);
	background-color: var(--color-2, #ee5101);
	transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}

/* Orange goes to brand blue on hover, as the home hero does. */
.nu-overview__button:hover,
.nu-overview__button:focus-visible {
	background-color: var(--color-1, #1600ba);
}

.nu-overview__button-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 2.4rem;
	height: 2.4rem;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-overview__button:hover .nu-overview__button-icon,
.nu-overview__button:focus-visible .nu-overview__button-icon {
	transform: translateX(10px);
}

.nu-overview__button-icon svg {
	width: 2.4rem;
	height: 2.4rem;
}

/* Recolour the arrow SVG to the button text colour. Presentation fills such as
   fill="#061745" lose to any CSS rule, so currentColor takes over cleanly. */
.nu-overview__button-icon svg path,
.nu-overview__button-icon svg circle,
.nu-overview__button-icon svg rect,
.nu-overview__button-icon svg polygon {
	fill: currentColor;
}

.nu-overview__button-icon svg [stroke]:not([stroke='none']) {
	stroke: currentColor;
}

/* ------------------------------------------------------------ Breakpoints */

@media (max-width: 767px) {
	.nu-overview__button {
		width: 100%;
	}
}

@media (prefers-reduced-motion: reduce) {
	.nu-overview__button,
	.nu-overview__button-icon {
		transition: none;
	}

	.nu-overview__button:hover .nu-overview__button-icon,
	.nu-overview__button:focus-visible .nu-overview__button-icon {
		transform: none;
	}
}

/* ============ nu-banner.css ============ */
/**
 * NÜ — Banner
 *
 * Full-width banner: a background image with a dark left-to-right gradient
 * overlay, and a frosted-glass card holding a subtitle, headline, paragraph
 * and primary CTA. Built from the Figma "Overview" frame (1440 × 634), and
 * renamed to Banner on 2026-08-06 when "Overview" was reassigned.
 *
 * Zero-specificity :where() defaults so any builder value wins.
 *
 * Figma → Core Framework token mapping (html font-size 62.5%, 1rem = 10px):
 *   headline    46px → var(--text-2xl)   clamp(32px → 46px)
 *   paragraph   20px → var(--text-m)     clamp(18px → 20px)
 *   subtitle    18px → var(--text-tagline) 18px
 *   button      16px → var(--text-button)  16px
 *   section radius 8px  → var(--radius-s)
 *   bloc radius   20px  → var(--radius-l)
 *   #061745            → var(--color-3) / var(--dark)
 *   button orange      → var(--color-2)  (site brand primary; Figma #EE5101)
 */

/* --------------------------------------------------------------- Section */

:where(.nu-banner) {
	/* Default background — shipped theme asset, resolved relative to this file.
	   The render layer overrides this variable when an image is chosen. */
	--nu-banner-image: url('../img/nu-wave-bg.webp');
	/* Dark tint that fades out toward the right, over the image. The base color
	   is a control; the direction and stops match the Figma frame. */
	--nu-banner-overlay-color: rgba(6, 23, 69, 0.8);

	position: relative;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	width: 100%;
	overflow: hidden;
	border-radius: var(--radius-s, 0.8rem);
	background-image: var(--nu-banner-image);
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
	isolation: isolate;
}

/*
 * No inner wrapper here, so the gutter caps the content at the 140rem site
 * container. Plain class on purpose: the base .nu-section declares the same
 * variable at class specificity, so a :where() default loses to it and the cap
 * never applies. Out-ranking the base also out-ranks its phone breakpoint —
 * the phone gutter is restated in the 767px block below.
 */
.nu-banner {
	--nu-section-space-inline: max(var(--space-xl, 5.6rem), (100% - 140rem) / 2);
}

/* Gradient overlay: above the image, below the content. */
.nu-banner::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: -1;
	background-image: linear-gradient(
		90deg,
		var(--nu-banner-overlay-color) 42.26%,
		transparent 81.72%
	);
}

/* ------------------------------------------------------------------ Bloc */

:where(.nu-banner__bloc) {
	/* Horizontal inset of the frosted card; cancelled by the negative start
	   margin below so the text lands on the page content line (pin 54,
	   2026-08-31). */
	--nu-banner-bloc-px: clamp(2.4rem, 2.78vw, 4rem);

	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: clamp(2.4rem, 2.78vw, 4rem);
	width: min(64rem, 100% + var(--nu-banner-bloc-px));
	max-width: calc(100% + var(--nu-banner-bloc-px));
	/* Taller than the Figma card on purpose — the client found the mockup's
	   own proportions cramped (note, 2026-08-12). */
	padding: clamp(3.2rem, 4.17vw, 6rem) var(--nu-banner-bloc-px);
	/* The card is pulled left by exactly its own inset, so the text sits on
	   the page content line while the banner background stays full-bleed and
	   the card keeps its internal proportions (pin 54, 2026-08-31). */
	margin-inline-start: calc(-1 * var(--nu-banner-bloc-px));
	border-radius: var(--radius-l, 2rem);
	background: rgba(255, 255, 255, 0.01);
	-webkit-backdrop-filter: blur(10px);
	backdrop-filter: blur(10px);
}

:where(.nu-banner__txt) {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 2rem;
	width: 100%;
}

/* --------------------------------------------------------------- Content */

:where(.nu-banner__subtitle) {
	font-family: 'Space Mono', monospace;
	font-weight: 700;
	font-size: var(--text-tagline, 1.8rem);
	line-height: 1.1;
	text-transform: uppercase;
	color: var(--light, #fff);
}

:where(.nu-banner__headline) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: var(--text-2xl, 4.6rem);
	line-height: 1.2;
	color: var(--light, #fff);
}

:where(.nu-banner__paragraph) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: var(--text-m, 2rem);
	line-height: 1.2;
	color: var(--light, #fff);
}

:where(.nu-banner__paragraph > *:first-child) { margin-top: 0; }
:where(.nu-banner__paragraph > *:last-child) { margin-bottom: 0; }

/* ---------------------------------------------------------------- Button */

:where(.nu-banner__button) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.8rem;
	flex: none;
	min-height: 4.8rem;
	padding: 1.2rem 2.4rem;
	border: 1px solid transparent;
	border-radius: var(--radius-full, 3rem);
	font-family: 'Spline Sans', sans-serif;
	font-weight: 500;
	font-size: var(--text-button, 1.6rem);
	line-height: 2.4rem;
	text-decoration: none;
	color: var(--light, #fff);
	background-color: var(--color-2, #ee5101);
	transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}

/* Orange goes to brand blue on hover, as the home hero does. */
:where(.nu-banner__button:hover),
:where(.nu-banner__button:focus-visible) {
	background-color: var(--color-1, #1600ba);
}

:where(.nu-banner__button-icon) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 2.4rem;
	height: 2.4rem;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-banner__button:hover .nu-banner__button-icon,
.nu-banner__button:focus-visible .nu-banner__button-icon {
	transform: translateX(10px);
}

:where(.nu-banner__button-icon svg) {
	width: 2.4rem;
	height: 2.4rem;
}

/* Recolour the arrow SVG to the button text colour. Presentation fills such as
   fill="#061745" lose to any CSS rule, so currentColor takes over cleanly. */
.nu-banner__button-icon svg path,
.nu-banner__button-icon svg circle,
.nu-banner__button-icon svg rect,
.nu-banner__button-icon svg polygon {
	fill: currentColor;
}

.nu-banner__button-icon svg [stroke]:not([stroke='none']) {
	stroke: currentColor;
}

/* ------------------------------------------------------------ Breakpoints */

@media (max-width: 767px) {
	/* The plain-class gutter above out-ranks nu-section.css's own phone rule. */
	.nu-banner {
		--nu-section-space-inline: var(--space-l, 3.96rem);
	}

	:where(.nu-banner__bloc) {
		/* 100% + the inset the negative start margin eats, so the right edge
		   still reaches the content column's right rail. */
		width: calc(100% + var(--nu-banner-bloc-px));
	}

	:where(.nu-banner__button) {
		width: 100%;
	}
}

@media (prefers-reduced-motion: reduce) {
	.nu-banner__button,
	.nu-banner__button-icon {
		transition: none;
	}

	.nu-banner__button:hover .nu-banner__button-icon,
	.nu-banner__button:focus-visible .nu-banner__button-icon {
		transform: none;
	}
}

/* ============ nu-agency.css ============ */
/**
 * NÜ — Agency
 *
 * A section title + secondary link, above one or more column cards. Each card
 * holds an icon tile, headline, paragraph, an arrow bullet-list and a CTA, and
 * carries a per-card accent (blue or lavender) for its tile + CTA.
 *
 * Two section variants:
 *   --dark   image background + navy overlay, frosted-glass cards, light text
 *   --light  solid lavender-tint background, white cards, navy text
 *
 * Built from the Figma "Agency-1.1 / 1.2" frames.
 *
 * Zero-specificity :where() defaults so any builder value wins.
 *
 * Figma → Core Framework token mapping (html font-size 62.5%, 1rem = 10px):
 *   headline / title 46px → var(--text-2xl)
 *   paragraph / list 20px → var(--text-m)
 *   button           16px → var(--text-button)
 *   card radius 8px       → var(--radius-s)
 *   #0F18C6 (blue tile/CTA)  → var(--text-title)
 *   #E0DCFF (lavender)       → var(--color-5)
 *   #061745 (navy text)      → var(--color-3) / var(--dark)
 *   #EE5101 (arrows)         → var(--color-2)   (site brand orange)
 */

/* --------------------------------------------------------------- Section */

:where(.nu-agency) {
	--nu-agency-image: url('../img/nu-overview-bg.webp');
	--nu-agency-overlay-color: rgba(6, 23, 69, 0.8);
	/* Foreground text + secondary-button line; overridden per variant. */
	--nu-agency-fg: var(--color-5, #e0dcff);
	--nu-agency-line: var(--light, #fff);

	position: relative;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	width: 100%;
	gap: clamp(3.2rem, 2.86vw, 4.8rem);
	overflow: hidden;
	isolation: isolate;
}

/*
 * No inner wrapper here, so the gutter caps the content at the 140rem site
 * container. Plain class on purpose: the base .nu-section declares the same
 * variable at class specificity, so a :where() default loses to it and the cap
 * never applies. Out-ranking the base also out-ranks its phone breakpoint —
 * the phone gutter is restated in the 767px block below.
 */
.nu-agency {
	--nu-section-space-inline: max(var(--space-xl, 5.6rem), (100% - 140rem) / 2);
}

/* Dark variant: background image with a flat navy overlay. */
:where(.nu-agency--dark) {
	--nu-agency-fg: var(--color-5, #e0dcff);
	--nu-agency-line: var(--light, #fff);
	background-image: var(--nu-agency-image);
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
}

.nu-agency--dark::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: -1;
	background-color: var(--nu-agency-overlay-color);
}

/*
 * Light variant: dark text on the lavender wash. The wash itself is the shared
 * `nu-section--purple` surface — it used to be painted here as a gradient over
 * white, which is the same colour, but stating it twice would tint it twice now
 * that the base paints it.
 */
:where(.nu-agency--light) {
	--nu-agency-fg: var(--color-3, #061745);
	--nu-agency-line: var(--color-3, #061745);
	--nu-agency-image: none;
}

/* ------------------------------------------------------------------ Head */

:where(.nu-agency__head) {
	display: flex;
	flex-direction: row;
	align-items: flex-end;
	justify-content: space-between;
	gap: clamp(2.4rem, 3.33vw, 4rem);
	width: 100%;
}

:where(.nu-agency__title) {
	margin: 0;
	flex: 1 1 auto;
	max-width: 112rem;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: var(--text-2xl, 4.6rem);
	line-height: 1.2;
	color: var(--nu-agency-fg);
}

/* --------------------------------------------------------------- Columns */

:where(.nu-agency__cols) {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 34rem), 1fr));
	gap: clamp(1.6rem, 2.14vw, 3.2rem);
	width: 100%;
}

/* ------------------------------------------------------------------ Card */

:where(.nu-agency__card) {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: clamp(2.4rem, 2.78vw, 4rem);
	height: 100%;
	padding: clamp(3.2rem, 3.33vw, 6rem);
	border: 1px solid rgba(224, 220, 255, 0.3);
	border-radius: var(--radius-s, 0.8rem);
}

:where(.nu-agency--dark .nu-agency__card) {
	background: rgba(224, 220, 255, 0.02);
	-webkit-backdrop-filter: blur(20px);
	backdrop-filter: blur(20px);
}

:where(.nu-agency--light .nu-agency__card) {
	background: var(--light, #fff);
}

/*
 * A lone full-width card — the "Vous êtes un annonceur / une agence ?"
 * cross-link on the annonceurs and agences pages — reads as page content,
 * not as one tile in a grid: its icon, title, list and CTA line up with the
 * page content column. Only the horizontal inset goes; the card surface
 * keeps its footprint and its vertical padding (pin 56, 2026-08-31).
 * Scoped to the light variant so a dark frosted card in a grid is never
 * affected; :only-child keeps every multi-card grid untouched, including
 * when it stacks to one column on tablets. Plain classes (0,4,0): beats the
 * :where() default, still loses to a builder #brxe override.
 */
.nu-agency--light .nu-agency__cols > .nu-agency__card:only-child {
	padding-inline: 0;
}

/* Icon tile — colours set by the card accent. */
:where(.nu-agency__icon) {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: clamp(10rem, 8.33vw, 14rem);
	height: clamp(10rem, 8.33vw, 14rem);
	border-radius: clamp(2.8rem, 2.38vw, 4rem);
}

:where(.nu-agency__card--blue .nu-agency__icon) {
	background-color: var(--text-title, #0f18c6);
	color: var(--color-5, #e0dcff);
}

:where(.nu-agency__card--light .nu-agency__icon) {
	background-color: var(--color-5, #e0dcff);
	color: var(--color-3, #061745);
}

:where(.nu-agency__icon svg),
:where(.nu-agency__icon > i) {
	width: clamp(5.2rem, 4.17vw, 7rem);
	height: clamp(5.2rem, 4.17vw, 7rem);
	font-size: clamp(5.2rem, 4.17vw, 7rem);
}

/* Direct children only: some glyphs carry a <mask> whose inner <path fill="white">
   must keep its colour, or the mask inverts and the icon disappears. */
.nu-agency__icon svg > path,
.nu-agency__icon svg > g path,
.nu-agency__icon svg > circle,
.nu-agency__icon svg > rect,
.nu-agency__icon svg > polygon {
	fill: currentColor;
}

.nu-agency__icon svg > [stroke]:not([stroke='none']),
.nu-agency__icon svg > g [stroke]:not([stroke='none']) {
	stroke: currentColor;
}

/* Body: content + CTA, CTA pinned to the card bottom. */
:where(.nu-agency__body) {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	justify-content: space-between;
	gap: clamp(3.2rem, 3.33vw, 4.8rem);
	width: 100%;
	flex: 1 1 auto;
}

:where(.nu-agency__content) {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: clamp(2.4rem, 2.5vw, 3.6rem);
	width: 100%;
}

:where(.nu-agency__copy) {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1.6rem;
	width: 100%;
}

:where(.nu-agency__headline) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: var(--text-2xl, 4.6rem);
	line-height: 1.2;
	color: var(--nu-agency-fg);
}

:where(.nu-agency__paragraph) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 400;
	font-size: var(--text-m, 2rem);
	line-height: 1.5;
	color: var(--nu-agency-fg);
}

:where(.nu-agency__paragraph > *:first-child) { margin-top: 0; }
:where(.nu-agency__paragraph > *:last-child) { margin-bottom: 0; }

/* ------------------------------------------------------------------ List */

:where(.nu-agency__list) {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1.6rem;
	width: 100%;
	margin: 0;
	padding: 0;
	list-style: none;
}

:where(.nu-agency__item) {
	display: flex;
	flex-direction: row;
	align-items: flex-start;
	gap: 1rem;
	width: 100%;
}

:where(.nu-agency__item-icon) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: clamp(2.4rem, 2.5vw, 3rem);
	height: calc(var(--text-m, 2rem) * 1.2); /* align arrow to first text line */
	color: var(--color-2, #ee5101);
}

:where(.nu-agency__item-icon svg) {
	width: clamp(2.4rem, 2.5vw, 3rem);
	height: clamp(2.4rem, 2.5vw, 3rem);
}

.nu-agency__item-icon svg path,
.nu-agency__item-icon svg circle,
.nu-agency__item-icon svg rect,
.nu-agency__item-icon svg polygon {
	fill: currentColor;
}

.nu-agency__item-icon svg [stroke]:not([stroke='none']) {
	stroke: currentColor;
}

:where(.nu-agency__item-text) {
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: var(--text-m, 2rem);
	line-height: 1.2;
	color: var(--nu-agency-fg);
}

/* A linked list item keeps the plain item's look; the underline is the cue. */
.nu-agency__item-link {
	text-decoration: none;
}

.nu-agency__item-link:hover .nu-agency__item-text,
.nu-agency__item-link:focus-visible .nu-agency__item-text {
	text-decoration: underline;
	text-underline-offset: 0.3em;
}

/* --------------------------------------------------------------- Buttons */

:where(.nu-agency__button) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.8rem;
	flex: none;
	min-height: 4.8rem;
	padding: 1.2rem 2.4rem;
	border: 1px solid transparent;
	border-radius: var(--radius-full, 3rem);
	font-family: 'Spline Sans', sans-serif;
	font-weight: 500;
	font-size: var(--text-button, 1.6rem);
	line-height: 2.4rem;
	text-decoration: none;
	transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}

/* Top secondary button: outline in the variant's line colour. */
:where(.nu-agency__button--secondary) {
	color: var(--nu-agency-line);
	border-color: var(--nu-agency-line);
	background-color: transparent;
}

:where(.nu-agency--dark .nu-agency__button--secondary:hover),
:where(.nu-agency--dark .nu-agency__button--secondary:focus-visible) {
	background-color: var(--light, #fff);
	color: var(--color-3, #061745);
}

:where(.nu-agency--light .nu-agency__button--secondary:hover),
:where(.nu-agency--light .nu-agency__button--secondary:focus-visible) {
	background-color: var(--color-3, #061745);
	color: var(--light, #fff);
}

/* Card CTA — colours set by the card accent. */
:where(.nu-agency__card--blue .nu-agency__cta) {
	color: var(--light, #fff);
	background-color: var(--text-title, #0f18c6);
}

/* The blue CTA is the mirror of the orange pill: it goes to brand orange. */
:where(.nu-agency__card--blue .nu-agency__cta:hover),
:where(.nu-agency__card--blue .nu-agency__cta:focus-visible) {
	background-color: var(--color-2, #ef4400);
}

:where(.nu-agency__card--light .nu-agency__cta) {
	color: var(--color-3, #061745);
	background-color: var(--color-5, #e0dcff);
}

:where(.nu-agency__card--light .nu-agency__cta:hover),
:where(.nu-agency__card--light .nu-agency__cta:focus-visible) {
	background-color: var(--color-3, #061745);
	color: var(--light, #fff);
}

:where(.nu-agency__button-icon) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 2.4rem;
	height: 2.4rem;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-agency__button:hover .nu-agency__button-icon,
.nu-agency__button:focus-visible .nu-agency__button-icon {
	transform: translateX(10px);
}

:where(.nu-agency__button-icon svg) {
	width: 2.4rem;
	height: 2.4rem;
}

.nu-agency__button-icon svg path,
.nu-agency__button-icon svg circle,
.nu-agency__button-icon svg rect,
.nu-agency__button-icon svg polygon {
	fill: currentColor;
}

.nu-agency__button-icon svg [stroke]:not([stroke='none']) {
	stroke: currentColor;
}

/* ----------------------------------------------- Color specificity lift -
 * The theme styles headings (`h2{color:var(--color-1)}`) and links at element
 * specificity, which beats a :where() default. These plain class rules (0,1,0)
 * win over the theme yet still lose to a Bricks ID-based control override, so
 * builder colours keep working. Card CTA text colour is accent-driven, so its
 * lift is scoped per accent. */
.nu-agency__title,
.nu-agency__headline,
.nu-agency__paragraph,
.nu-agency__item-text {
	color: var(--nu-agency-fg);
}

.nu-agency__button--secondary {
	color: var(--nu-agency-line);
}

.nu-agency__card--blue .nu-agency__cta {
	color: var(--light, #fff);
}

.nu-agency__card--light .nu-agency__cta {
	color: var(--color-3, #061745);
}

/* The lifts above out-rank the :where() hover states, so each lifted colour
 * needs its hover restated at the same (0,2,0)+ specificity — without these the
 * light card's CTA hovers navy-on-navy and disappears. */
.nu-agency--dark .nu-agency__button--secondary:hover,
.nu-agency--dark .nu-agency__button--secondary:focus-visible {
	color: var(--color-3, #061745);
}

.nu-agency--light .nu-agency__button--secondary:hover,
.nu-agency--light .nu-agency__button--secondary:focus-visible {
	color: var(--light, #fff);
}

.nu-agency__card--light .nu-agency__cta:hover,
.nu-agency__card--light .nu-agency__cta:focus-visible {
	color: var(--light, #fff);
}

/* ------------------------------------------------------------ Breakpoints */

/* Stack columns on tablets and below. */
@media (max-width: 991px) {
	:where(.nu-agency__cols) {
		grid-template-columns: minmax(0, 1fr);
	}
}

@media (max-width: 767px) {
	/* The plain-class gutter above out-ranks nu-section.css's own phone rule. */
	.nu-agency {
		--nu-section-space-inline: var(--space-l, 3.96rem);
	}

	:where(.nu-agency__head) {
		flex-direction: column;
		align-items: flex-start;
		gap: 2.4rem;
	}

	:where(.nu-agency__button) {
		width: 100%;
	}
}

@media (prefers-reduced-motion: reduce) {
	.nu-agency__button,
	.nu-agency__button-icon {
		transition: none;
	}

	.nu-agency__button:hover .nu-agency__button-icon,
	.nu-agency__button:focus-visible .nu-agency__button-icon {
		transform: none;
	}
}

/* ============ nu-section-split-accordion.css ============ */
/**
 * NÜ — Section split
 *
 * Two-column split: image on one side, content on the other (heading, intro
 * text, a numbered accordion and a primary CTA). Rebuilt for parity with the
 * "Section split" Bricks template.
 *
 * The accordion is a self-contained, accessible disclosure list (button +
 * region) with a CSS grid-rows height animation and single-open behaviour,
 * driven by assets/js/nu-section-split.js.
 *
 * Zero-specificity :where() defaults so any builder value wins. Colours that
 * must beat theme element rules use plain class selectors (0,1,0).
 *
 * Core Framework tokens (html font-size 62.5%, 1rem = 10px):
 *   heading  → theme h2 (var(--color-1))
 *   title    → var(--text-l)     closed #6b6b6b, open var(--color-1)
 *   text     → var(--text-s/m)
 *   bar      → var(--color-4) closed, var(--color-1) open
 *   button   → var(--color-2)   radius var(--radius-full)
 *   image    → var(--radius-s)
 */

:where(.nu-section-split) {
	width: 100%;
}

:where(.nu-section-split__inner) {
	max-width: 140rem;
	margin-inline: auto;
}

:where(.nu-section-split__grid) {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--space-2xl, 5.6rem);
	align-items: center;
}

/* Image on the right instead of the left. */
:where(.nu-section-split--image-right .nu-section-split__media) {
	order: 2;
}

/* ----------------------------------------------------------------- Media */

:where(.nu-section-split__media) {
	display: flex;
	overflow: hidden;
	border-radius: var(--radius-s, 0.8rem);
}

:where(.nu-section-split__image) {
	display: block;
	width: 100%;
	height: auto;
	min-width: 100%;
	object-fit: cover;
}

/* --------------------------------------------------------------- Content */

:where(.nu-section-split__content) {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-l, 3.96rem);
}

:where(.nu-section-split__heading) {
	margin: 0;
}

:where(.nu-section-split__text) {
	font-family: 'Spline Sans', sans-serif;
	font-size: var(--text-m, 2rem);
	line-height: 1.5;
	color: var(--text-body, #061745);
}

/* Intro rich-text flourishes carried over from the template. */
.nu-section-split__text strong {
	color: var(--color-2, #ef4400);
	font-size: 2.2rem;
}

.nu-section-split__text ul {
	padding-left: 1.55rem;
	margin-block-start: 0;
}

:where(.nu-section-split__text > *:first-child) { margin-top: 0; }
:where(.nu-section-split__text > *:last-child) { margin-bottom: 0; }

/* ------------------------------------------------------------- Accordion */

:where(.nu-section-split__accordion) {
	counter-reset: nuss-acc;
	display: flex;
	flex-direction: column;
	gap: var(--space-m, 2.8rem);
	width: 100%;
}

:where(.nu-section-split__item) {
	position: relative;
	padding-left: var(--space-m, 2.8rem);
}

/* Left rail: thin light bar, thick blue when open. */
.nu-section-split__item::before {
	content: '';
	position: absolute;
	left: -2px;
	top: 0;
	width: 2px;
	height: 100%;
	background-color: var(--color-4, #d7e3f5);
	transition: background-color 0.3s ease, width 0.3s ease;
}

.nu-section-split__item.is-open::before {
	width: 4px;
	background-color: var(--color-1, #1600ba);
}

:where(.nu-section-split__summary) {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-s, 1.98rem);
	width: 100%;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
	text-align: left;
	color: inherit;
	font: inherit;
}

:where(.nu-section-split__title) {
	position: relative;
	margin: 0;
	padding-inline-start: 2.2ch;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: var(--text-l, 2.2rem);
	line-height: 1.4;
	color: #6b6b6b;
	font-variant-numeric: tabular-nums;
	transition: color 0.3s ease;
}

/* Number prefix. */
.nu-section-split__title::before {
	counter-increment: nuss-acc;
	content: counter(nuss-acc) '. ';
	position: absolute;
	inset-inline-start: 0;
	top: 0;
	line-height: 1.4;
}

.nu-section-split__item.is-open .nu-section-split__title,
.nu-section-split__summary:hover .nu-section-split__title,
.nu-section-split__summary:focus-visible .nu-section-split__title {
	color: var(--color-1, #1600ba);
}

/* Animated panel: 0fr → 1fr grid row. */
:where(.nu-section-split__panel) {
	display: grid;
	grid-template-rows: 0fr;
	transition: grid-template-rows 0.3s ease;
}

.nu-section-split__item.is-open .nu-section-split__panel {
	grid-template-rows: 1fr;
}

:where(.nu-section-split__panel-inner) {
	overflow: hidden;
}

:where(.nu-section-split__panel-text) {
	padding-top: var(--space-s, 1.98rem);
	font-family: 'Spline Sans', sans-serif;
	font-size: var(--text-s, 1.6rem);
	line-height: 1.5;
	color: var(--text-body, #061745);
}

:where(.nu-section-split__panel-text > *:first-child) { margin-top: 0; }
:where(.nu-section-split__panel-text > *:last-child) { margin-bottom: 0; }

/* ---------------------------------------------------------------- Button */

:where(.nu-section-split__button) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.8rem;
	flex: none;
	min-height: 4.8rem;
	margin-top: var(--space-s, 1.98rem);
	padding: 1.2rem 2.4rem;
	border: 1px solid transparent;
	border-radius: var(--radius-full, 3rem);
	font-family: 'Spline Sans', sans-serif;
	font-weight: 500;
	font-size: var(--text-button, 1.6rem);
	line-height: 2.4rem;
	text-decoration: none;
	color: var(--light, #fff);
	background-color: var(--color-2, #ef4400);
	transition: background-color 0.25s ease, color 0.25s ease;
}

/* Orange goes to brand blue on hover, as the home hero does. */
:where(.nu-section-split__button:hover),
:where(.nu-section-split__button:focus-visible) {
	background-color: var(--color-1, #1600ba);
}

:where(.nu-section-split__button-icon) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 2.4rem;
	height: 2.4rem;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-section-split__button:hover .nu-section-split__button-icon,
.nu-section-split__button:focus-visible .nu-section-split__button-icon {
	transform: translateX(10px);
}

:where(.nu-section-split__button-icon svg) {
	width: 2.4rem;
	height: 2.4rem;
}

.nu-section-split__button-icon svg path,
.nu-section-split__button-icon svg circle,
.nu-section-split__button-icon svg rect,
.nu-section-split__button-icon svg polygon {
	fill: currentColor;
}

.nu-section-split__button-icon svg [stroke]:not([stroke='none']) {
	stroke: currentColor;
}

/* ----------------------------------------------- Color specificity lift -
 * Theme styles titles/links at element specificity; these class rules (0,1,0)
 * win yet still lose to a Bricks ID-based control override. */
.nu-section-split__title {
	color: #6b6b6b;
}

.nu-section-split__button {
	color: var(--light, #fff);
}

/* ------------------------------------------------------------ Breakpoints */

@media (max-width: 767px) {
	:where(.nu-section-split__grid) {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--space-xl, 5.6rem);
	}

	/* Image always leads on mobile, whatever the desktop order. */
	:where(.nu-section-split--image-right .nu-section-split__media) {
		order: 0;
	}

	:where(.nu-section-split__button) {
		width: 100%;
	}

	/* Pin 52 — on mobile --text-l bottoms out at 1.8rem, the same as body
	   text (--text-m), so the numbered titles lost their heading weight.
	   Lift them one step to the --text-xl mobile floor (2rem = 20px);
	   the ::before number prefix inherits and scales along. */
	.nu-section-split__title {
		font-size: 2rem;
	}
}

@media (prefers-reduced-motion: reduce) {
	.nu-section-split__button,
	.nu-section-split__button-icon {
		transition: none;
	}

	.nu-section-split__button:hover .nu-section-split__button-icon,
	.nu-section-split__button:focus-visible .nu-section-split__button-icon {
		transform: none;
	}
}

/* The accordion heading now wraps the toggle button (disclosure pattern);
   it must add no box of its own — the button carries all the styling. */
.nu-section-split__title-heading {
	margin: 0;
	font-size: inherit;
	line-height: inherit;
	font-weight: inherit;
}

.nu-section-split__title-heading .nu-section-split__summary {
	width: 100%;
}

/* ============ nu-megamenu.css ============ */
/**
 * NÜ megamenu
 *
 * Colors fall back to the site's Core Framework tokens, so the element follows
 * the global palette unless overridden per instance in the builder.
 */

.nu-megamenu {
	--nu-mm-surface: var(--light, #fff);
	--nu-mm-card: var(--color-5, #e0dcff);
	--nu-mm-card-soft: color-mix(in srgb, var(--nu-mm-card) 30%, transparent);
	--nu-mm-card-hover: color-mix(in srgb, var(--nu-mm-card) 80%, var(--nu-mm-ink) 20%);
	--nu-mm-ink: var(--color-3, #061745);
	--nu-mm-accent: var(--color-2, #ee5101);
	--nu-mm-cta-bg: var(--color-3, #061745);
	--nu-mm-cta-ink: var(--color-5, #e0dcff);
	--nu-mm-bar-active: var(--color-2, #ee5101);
	--nu-mm-glass: rgba(246, 245, 255, 0.6);
	--nu-mm-radius: var(--radius-s, 8px);
	--nu-mm-pill: var(--radius-full, 999rem);
	--nu-mm-panel-width: 1440px;
	--nu-mm-panel-offset: 30px;
	--nu-mm-font-display: "Space Mono", ui-monospace, monospace;
	--nu-mm-font-body: "Spline Sans", system-ui, sans-serif;
	--nu-mm-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
	/* Mobile drawer (Figma "00.2/00.3-Navigation - mobile"). */
	--nu-mm-brand: var(--color-1, #0f18c6);
	--nu-mm-drawer-bg: #f6f6f6;
	--nu-mm-drawer-rule: rgb(6 23 69 / 0.1);
	--nu-mm-drawer-top: 130px;

	position: relative;
	color: var(--nu-mm-ink);
	font-family: var(--nu-mm-font-body);
}

/* Older browsers without color-mix keep a solid, still-readable card. */
@supports not (color: color-mix(in srgb, red 30%, transparent)) {
	.nu-megamenu {
		--nu-mm-card-soft: #f3f1ff;
		--nu-mm-card-hover: #b4b5da;
	}
}

.nu-megamenu ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

/* ---------------------------------------------------------------- bar ---- */

.nu-megamenu__bar {
	display: flex;
	align-items: center;
	gap: var(--space-l, 32px);
}

.nu-megamenu__trigger,
.nu-megamenu__link {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 0;
	border: 0;
	background: none;
	color: inherit;
	font: inherit;
	text-decoration: none;
	cursor: pointer;
	border-bottom: 1px solid transparent;
	transition: color 0.25s var(--nu-mm-ease), border-color 0.25s var(--nu-mm-ease);
}

/* Figma: Spline Sans, 15px, medium. In px so it ignores the theme's root size. */
.nu-megamenu__label {
	font-family: var(--nu-mm-font-body);
	font-size: 15px;
	font-weight: 500;
	line-height: 1.5;
}

.nu-megamenu__trigger:hover,
.nu-megamenu__link:hover,
.nu-megamenu__item.is-current > * {
	border-bottom-color: currentColor;
}

.nu-megamenu__trigger[aria-expanded="true"] {
	color: var(--nu-mm-bar-active);
	border-bottom-color: currentColor;
}

.nu-megamenu__chevron {
	flex: none;
	transition: transform 0.25s var(--nu-mm-ease);
}

.nu-megamenu__trigger[aria-expanded="true"] .nu-megamenu__chevron {
	transform: rotate(180deg);
}

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

.nu-megamenu__panel {
	position: fixed;
	top: calc(var(--nu-mm-top, 100%) + var(--nu-mm-panel-offset));
	left: var(--nu-mm-left, 50%);
	z-index: 9990;
	/* JS sets --nu-mm-width to the header bar's width; the min() is the fallback. */
	width: var(--nu-mm-width, min(calc(100vw - 32px), var(--nu-mm-panel-width)));
	/* Frosted-glass layer behind the white menu + CTA (Figma "Solutions-Megamenu-1"). */
	padding: 40px 56px;
	background: var(--nu-mm-glass);
	-webkit-backdrop-filter: blur(10px);
	backdrop-filter: blur(10px);
	border-radius: var(--nu-mm-radius);
	box-shadow: 0 24px 60px rgb(6 23 69 / 0.12);
	opacity: 0;
	/* --nu-mm-x is 0px once JS pins the exact left; -50% is the centered fallback. */
	transform: translateX(var(--nu-mm-x, -50%)) translateY(-8px);
	transition: opacity 0.22s var(--nu-mm-ease), transform 0.22s var(--nu-mm-ease);
	pointer-events: none;
}

.nu-megamenu__panel[hidden] {
	display: none;
}

.nu-megamenu__panel.is-open {
	opacity: 1;
	transform: translateX(var(--nu-mm-x, -50%)) translateY(0);
	pointer-events: auto;
}

.nu-megamenu__panel-inner {
	display: flex;
	align-items: stretch;
	gap: 24px;
}

.nu-megamenu__menu {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: 20px;
	min-width: 0;
	padding: 20px;
	background: var(--nu-mm-surface);
	border-radius: var(--nu-mm-radius);
}

.nu-megamenu__panel-title {
	display: inline-flex;
	align-items: center;
	align-self: flex-start;
	gap: 12px;
	padding: 10px 0;
	color: var(--nu-mm-ink);
	font-family: var(--nu-mm-font-display);
	font-size: 24px;
	font-weight: 700;
	line-height: 1.2;
	text-decoration: none;
	text-transform: uppercase;
}

.nu-megamenu__content {
	display: flex;
	flex: 1;
	gap: 10px;
	min-height: 0;
}

/* ------------------------------------------------------------- arrows ---- */

.nu-megamenu__arrow {
	display: inline-flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	border-radius: var(--nu-mm-pill);
	color: var(--nu-mm-ink);
	transition: transform 0.25s var(--nu-mm-ease), background-color 0.25s var(--nu-mm-ease),
		color 0.25s var(--nu-mm-ease);
}

.nu-megamenu__arrow--lav {
	background: var(--nu-mm-card);
}

.nu-megamenu__arrow--white {
	background: var(--nu-mm-surface);
}

.nu-megamenu__arrow--bare {
	width: 30px;
	height: 30px;
	color: var(--nu-mm-accent);
}

/* Pin 44: the panel title's circle flips to the menu's interactive orange —
   the same accent as the open trigger — with the arrow in white. */
.nu-megamenu__panel-title:hover .nu-megamenu__arrow--lav,
.nu-megamenu__panel-title:focus-visible .nu-megamenu__arrow--lav {
	background: var(--nu-mm-accent);
	color: #fff;
}

@media (prefers-reduced-motion: no-preference) {
	.nu-megamenu__panel-title:hover .nu-megamenu__arrow,
	.nu-megamenu__group:hover .nu-megamenu__arrow,
	.nu-megamenu__feature:hover .nu-megamenu__arrow,
	.nu-megamenu__card:hover .nu-megamenu__arrow,
	.nu-megamenu__cta-button:hover .nu-megamenu__arrow {
		transform: translateX(3px);
	}
}

/* ------------------------------------------------------- split layout ---- */

.nu-megamenu__groups,
.nu-megamenu__panes {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: 10px;
	min-width: 0;
}

.nu-megamenu__group {
	display: flex;
	align-items: center;
	gap: 24px;
	padding: 20px;
	background: var(--nu-mm-card);
	border-radius: var(--nu-mm-radius);
	color: var(--nu-mm-ink);
	text-decoration: none;
	transition: background-color 0.25s var(--nu-mm-ease);
}

.nu-megamenu__group[data-active="true"],
.nu-megamenu__group:hover,
.nu-megamenu__group.is-current {
	background: var(--nu-mm-card-hover);
}

.nu-megamenu__group-body {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: 16px;
	min-width: 0;
}

.nu-megamenu__group-title {
	font-family: var(--nu-mm-font-display);
	font-size: 20px;
	font-weight: 700;
	line-height: 1.2;
	text-transform: uppercase;
}

.nu-megamenu__group-text {
	font-family: var(--nu-mm-font-body);
	font-size: 14px;
	font-weight: 400;
	line-height: 1.5;
}

.nu-megamenu__panes > .nu-megamenu__cards[hidden] {
	display: none;
}

/* ------------------------------------------------------- cards layout ---- */

.nu-megamenu__features {
	display: grid;
	flex: 1;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 10px;
}

.nu-megamenu__feature {
	display: flex;
	flex-direction: column;
	gap: 16px;
	height: 100%;
	padding: 20px;
	background: var(--nu-mm-card);
	border-radius: var(--nu-mm-radius);
	color: var(--nu-mm-ink);
	text-decoration: none;
	transition: background-color 0.25s var(--nu-mm-ease);
}

.nu-megamenu__feature:hover,
.nu-megamenu__feature.is-current {
	background: var(--nu-mm-card-hover);
}

.nu-megamenu__feature-head {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 16px;
}

.nu-megamenu__feature-title {
	/* Every two-word title breaks the same way ("INVENTAIRES / MÉDIA" like
	   "L'INTELLIGENCE / MÉDIA") instead of one sitting on a single line. The
	   font is monospace, so `ch` counts characters exactly: the cap sits
	   between the longest first word that has to stay whole ("INVENTAIRES",
	   11) and the shortest whole title that has to break ("FOR AGENCIES", 12,
	   which fitted 12ch to the pixel and so held one line among its wrapped
	   siblings). */
	max-width: 11.5ch;
	font-family: var(--nu-mm-font-display);
	font-size: 20px;
	font-weight: 700;
	line-height: 1.2;
	text-transform: uppercase;
}

.nu-megamenu__feature-text {
	font-family: var(--nu-mm-font-body);
	font-size: 14px;
	font-weight: 400;
	line-height: 1.5;
}

/* --------------------------------------------------- compact icon row ---- */

.nu-megamenu__cards {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

/* Balanced column-major fill, matching the two-column channel list. */
.nu-megamenu__cards--grid {
	display: block;
	flex: 1;
	columns: 2;
	column-gap: 10px;
}

.nu-megamenu__cards--grid > li {
	break-inside: avoid;
}

.nu-megamenu__cards--grid > li + li {
	margin-top: 10px;
}

.nu-megamenu__card {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	min-height: 42px;
	padding: 6px 6px 6px 12px;
	background: var(--nu-mm-card-soft);
	border-radius: var(--nu-mm-radius);
	color: var(--nu-mm-ink);
	text-decoration: none;
	transition: background-color 0.25s var(--nu-mm-ease);
}

.nu-megamenu__card:hover,
.nu-megamenu__card.is-current {
	background: var(--nu-mm-card);
}

.nu-megamenu__card-body {
	display: flex;
	flex: 1;
	align-items: center;
	gap: 8px;
	min-width: 0;
}

.nu-megamenu__card-icon-wrap {
	display: inline-flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
}

.nu-megamenu__card-icon {
	width: 100%;
	height: 100%;
}

/* NÜ set icons are solid shapes with a baked-in fill; recolor to the card ink. */
.nu-megamenu__card-icon path,
.nu-megamenu__card-icon circle,
.nu-megamenu__card-icon rect,
.nu-megamenu__card-icon polygon {
	fill: currentColor;
}

.nu-megamenu__card-title {
	font-family: var(--nu-mm-font-display);
	font-size: 13px;
	font-weight: 700;
	line-height: 1.1;
	text-transform: uppercase;
}

/* ----------------------------------------------------------- cta card ---- */

/* Wide enough for "Planifier une consultation gratuite" to hold one line in
   the panel — the client flagged the wrapped button. The drawer keeps the
   Figma two-line button, so the compact arrow below is panel-scoped. */
.nu-megamenu__cta {
	display: flex;
	flex: none;
	align-self: flex-start;
	flex-direction: column;
	justify-content: space-between;
	gap: 24px;
	width: 360px;
	min-height: 280px;
	padding: 36px 20px;
	background: var(--nu-mm-cta-bg);
	border-radius: var(--nu-mm-radius);
	color: var(--nu-mm-cta-ink);
}

.nu-megamenu__cta-body {
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.nu-megamenu__cta-title {
	margin: 0;
	font-family: var(--nu-mm-font-body);
	font-size: 24px;
	font-weight: 300;
	line-height: 1.2;
}

.nu-megamenu__cta-text {
	margin: 0;
	font-family: var(--nu-mm-font-body);
	font-size: 14px;
	font-weight: 400;
	line-height: 1.5;
}

.nu-megamenu__cta-button {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	padding: 12px 12px 12px 24px;
	background: var(--nu-mm-accent);
	border-radius: var(--nu-mm-pill);
	color: #fff;
	font-family: var(--nu-mm-font-body);
	font-size: 14px;
	font-weight: 700;
	line-height: 1.29;
	text-decoration: none;
	transition: filter 0.25s var(--nu-mm-ease);
}

.nu-megamenu__cta-button:hover {
	filter: brightness(1.08);
}

/* In the panel the label stays on one line; a smaller arrow leaves it room. */
.nu-megamenu__panel .nu-megamenu__cta-button {
	padding: 8px 8px 8px 16px;
	white-space: nowrap;
}

.nu-megamenu__panel .nu-megamenu__cta-button .nu-megamenu__arrow {
	width: 36px;
	height: 36px;
}

/* ------------------------------------------------------ mobile drawer ---- */

/*
 * Figma "00.2-Navigation - mobile" / "00.3-Navigation-open - mobile", 390px
 * frame. Sizes are px because the drawer is a fixed-canvas design that should
 * not follow the theme's root font size.
 */

.nu-megamenu__burger {
	display: none;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 50px;
	height: 50px;
	padding: 0;
	border: 0;
	background: var(--nu-mm-surface);
	border-radius: var(--nu-mm-pill);
	color: var(--nu-mm-ink);
	cursor: pointer;
}

.nu-megamenu__burger-box {
	position: relative;
	display: block;
	width: 28px;
	height: 28px;
}

.nu-megamenu__burger-bar {
	position: absolute;
	left: 50%;
	top: 50%;
	width: 20px;
	height: 1.5px;
	margin: -0.75px 0 0 -10px;
	background: currentColor;
	border-radius: 1px;
	transition: transform 0.22s var(--nu-mm-ease), opacity 0.12s var(--nu-mm-ease),
		width 0.22s var(--nu-mm-ease), margin 0.22s var(--nu-mm-ease);
}

.nu-megamenu__burger-bar:nth-child(1) {
	transform: translateY(-7px);
}

.nu-megamenu__burger-bar:nth-child(3) {
	transform: translateY(7px);
}

/* Open: the Figma cross — two 19.8px arms at ±45°, 1.5px, round caps. */
.nu-megamenu__burger[aria-expanded="true"] .nu-megamenu__burger-bar {
	width: 19.8px;
	margin-left: -9.9px;
	border-radius: 0.75px;
}

.nu-megamenu__burger[aria-expanded="true"] .nu-megamenu__burger-bar:nth-child(1) {
	transform: rotate(45deg);
}

.nu-megamenu__burger[aria-expanded="true"] .nu-megamenu__burger-bar:nth-child(2) {
	opacity: 0;
}

.nu-megamenu__burger[aria-expanded="true"] .nu-megamenu__burger-bar:nth-child(3) {
	transform: rotate(-45deg);
}

/* Sits under the Bricks sticky header (z-index 998) so the bar stays reachable. */
.nu-megamenu__drawer {
	position: fixed;
	inset: 0;
	z-index: 990;
	display: flex;
	flex-direction: column;
	background: var(--nu-mm-drawer-bg);
	opacity: 0;
	transition: opacity 0.22s var(--nu-mm-ease);
}

.nu-megamenu__drawer[hidden] {
	display: none;
}

.nu-megamenu__drawer.is-open {
	opacity: 1;
}

.nu-megamenu__drawer-scroll {
	display: flex;
	flex-direction: column;
	flex: 1;
	min-height: 0;
	padding: var(--nu-mm-drawer-top) 24px 40px;
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
}

.nu-megamenu__view {
	display: none;
	flex-direction: column;
	/* Figma: 40px between the list and the footer on the root screen, 20px
	   between "Retour", the heading and the list on a sub screen. */
	gap: 40px;
}

.nu-megamenu__view:not([data-view="root"]) {
	gap: 20px;
}

/*
 * The active view fills the drawer, and the last block (the root footer, a sub
 * view's CTA card — an <li> at the end of the view list) is pinned to the
 * bottom of the screen — a short menu used to end mid-screen with a slab of
 * empty drawer below it.
 */
.nu-megamenu__view.is-active {
	display: flex;
	flex: 1;
}

.nu-megamenu__view .nu-megamenu__drawer-foot {
	margin-top: auto;
}

.nu-megamenu__view.is-active .nu-megamenu__view-list {
	flex: 1;
}

.nu-megamenu__view-list > li:has(> .nu-megamenu__cta--drawer) {
	margin-top: auto;
}

/* ---- root screen */

.nu-megamenu__row {
	box-sizing: border-box;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	width: 100%;
	height: 80px;
	padding: 20px 0;
	border: 0;
	border-bottom: 1px solid var(--nu-mm-drawer-rule);
	background: none;
	color: var(--nu-mm-brand);
	font-family: var(--nu-mm-font-body);
	font-size: 24px;
	font-weight: 300;
	line-height: 1.2;
	text-align: left;
	text-decoration: none;
	cursor: pointer;
}

.nu-megamenu__row-icon {
	display: inline-flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	color: var(--nu-mm-accent);
	transition: transform 0.25s var(--nu-mm-ease);
}

.nu-megamenu__row:hover .nu-megamenu__row-icon {
	transform: translateX(3px);
}

.nu-megamenu__drawer-foot {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 12px;
}

.nu-megamenu__langs {
	display: flex;
	gap: 8px;
}

.nu-megamenu__lang {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	height: 40px;
	padding: 0 12px;
	border: 1px solid rgb(6 23 69 / 0.3);
	border-radius: 30px;
	color: var(--nu-mm-ink);
	font-family: var(--nu-mm-font-body);
	font-size: 16px;
	font-weight: 500;
	line-height: 20px;
	text-decoration: none;
}

.nu-megamenu__lang-caret {
	flex: none;
}

.nu-megamenu__drawer-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	padding: 8px 24px;
	background: var(--nu-mm-brand);
	border-radius: 30px;
	color: #fff;
	font-family: var(--nu-mm-font-body);
	font-size: 14px;
	font-weight: 500;
	line-height: 24px;
	text-decoration: none;
	transition: filter 0.25s var(--nu-mm-ease);
}

.nu-megamenu__drawer-button:hover {
	filter: brightness(1.12);
}

/* ---- sub screen */

.nu-megamenu__back {
	display: inline-flex;
	align-self: flex-start;
	align-items: center;
	gap: 8px;
	padding: 0;
	border: 0;
	background: none;
	color: var(--nu-mm-ink);
	font-family: var(--nu-mm-font-body);
	font-size: 16px;
	font-weight: 600;
	line-height: 24px;
	cursor: pointer;
}

.nu-megamenu__view-title {
	display: flex;
	align-self: flex-start;
	align-items: center;
	gap: 12px;
	padding: 10px 0;
	color: var(--nu-mm-ink);
	font-family: var(--nu-mm-font-display);
	font-size: 22px;
	font-weight: 700;
	line-height: 1.2;
	text-decoration: none;
	text-transform: uppercase;
}

.nu-megamenu__view-title:hover .nu-megamenu__arrow,
.nu-megamenu__view-link:hover .nu-megamenu__arrow {
	transform: translateX(3px);
}

.nu-megamenu ul.nu-megamenu__view-list {
	display: flex;
	flex-direction: column;
	gap: 10px;
	/* The view's own 20px gap is the Figma spacing — extra padding here is what
	   opened the hole between the title and the list. */
	padding: 0;
}

.nu-megamenu__view-link {
	display: flex;
	align-items: center;
	gap: 24px;
	min-height: 64px;
	padding: 10px 20px;
	background: var(--nu-mm-card);
	border-radius: var(--nu-mm-radius);
	color: var(--nu-mm-ink);
	text-decoration: none;
	transition: background-color 0.25s var(--nu-mm-ease);
}

.nu-megamenu__view-link:hover,
.nu-megamenu__view-link.is-current {
	background: var(--nu-mm-card-hover);
}

.nu-megamenu__view-link-title {
	flex: 1;
	font-family: var(--nu-mm-font-display);
	font-size: 16px;
	font-weight: 700;
	line-height: 1.2;
	text-transform: uppercase;
}

/* The card is the last row of the list rather than a column of its own. */
.nu-megamenu__cta--drawer {
	align-self: stretch;
	width: auto;
	min-height: 0;
	padding: 36px 20px;
}

/* --------------------------------------------------------------- misc ---- */

.nu-megamenu :focus-visible {
	outline: 2px solid var(--nu-mm-accent);
	outline-offset: 3px;
}

@media (max-width: 1200px) {
	.nu-megamenu__content {
		flex-direction: column;
	}

	.nu-megamenu__panel-inner {
		flex-direction: column;
	}

	.nu-megamenu__cta {
		align-self: stretch;
		width: auto;
		min-height: 0;
		padding: 20px;
	}

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

	.nu-megamenu__panel {
		padding: 20px;
		max-height: calc(100vh - var(--nu-mm-top, 0px) - var(--nu-mm-panel-offset) - 16px);
		overflow-y: auto;
	}
}

@media (max-width: 720px) {
	.nu-megamenu__features,
	.nu-megamenu__cards--grid {
		grid-template-columns: minmax(0, 1fr);
		columns: 1;
	}
}

/*
 * The bar and the drawer swap at Bricks' mobile_landscape breakpoint, the same
 * one the header's other elements switch on.
 */
@media (max-width: 767px) {
	.nu-megamenu__bar {
		display: none;
	}

	.nu-megamenu__burger {
		display: inline-flex;
	}
}

@media (min-width: 768px) {
	.nu-megamenu__drawer {
		display: none;
	}
}

/* The drawer owns the viewport while open. */
html.nu-mm-drawer-open,
html.nu-mm-drawer-open body {
	overflow: hidden;
}

/*
 * The header is sticky "on scroll": Bricks only brings it back when the user
 * scrolls up, and the element itself is zero-height here (the bar overflows a
 * section with a negative bottom margin), so mid-page it is simply gone.
 * Scrolling is locked while the drawer is open, so it has to be pinned to the
 * top for the duration — otherwise the drawer opens with no close button.
 */
html.nu-mm-drawer-open #brx-header {
	position: fixed;
	top: 0;
	right: 0;
	left: 0;
	z-index: 998;
	transform: none;
}

@media (prefers-reduced-motion: reduce) {
	.nu-megamenu * {
		transition-duration: 0.01ms !important;
	}
}

/* ============ nu-feature-grid.css ============ */
/**
 * NÜ — Bloc 4 features.
 *
 * Row of glass cards read as an equation: "+" sits in the gutter between cards,
 * "=" before the last one, which is the filled "result" card.
 *
 * The source block was authored to sit inside a dark section (video background
 * under a --color-3-80 overlay), so its tagline and separators are light. This
 * element carries that dark background itself — at zero specificity, so the
 * Background control can clear it when the element is dropped into a section
 * that already provides one.
 *
 * Zero-specificity :where() defaults so any builder value wins. Colours that
 * must beat theme element rules use plain class selectors (0,1,0).
 *
 * Core Framework tokens (html font-size 62.5%, 1rem = 10px):
 *   card      → 1px var(--border-primary), radius-l, backdrop blur
 *   tagline   → Space Mono 700 2.2rem, var(--color-5)
 *   text      → var(--text-s)
 *   highlight → var(--color-2) fill
 */

:where(.nu-feature-grid) {
	width: 100%;
}

:where(.nu-feature-grid__inner) {
	max-width: 140rem;
	margin-inline: auto;
}

:where(.nu-feature-grid__grid) {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--space-2xl, 7.92rem);
}

/* ----------------------------------------------------------------- Card */

:where(.nu-feature-grid__card) {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: var(--space-m, 2.8rem);
	padding: var(--space-2xl, 7.92rem) var(--space-l, 3.96rem);
	border: 1px solid var(--border-primary, rgba(224, 220, 255, 0.3));
	border-radius: var(--radius-l, 2rem);
	backdrop-filter: blur(20px);
	-webkit-backdrop-filter: blur(20px);
	font-size: var(--text-s, 1.6rem);
	color: var(--light, #fff);
}

:where(.nu-feature-grid__card.is-highlight) {
	background-color: var(--color-2, #ef4400);
	color: var(--color-5, #e0dcff);
}

:where(.nu-feature-grid__icon) {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: none;
	color: var(--color-2, #ef4400);
}

:where(.nu-feature-grid__icon svg) {
	display: block;
	width: auto;
	max-width: 70px;
	height: 80px;
}

.nu-feature-grid__icon svg path,
.nu-feature-grid__icon svg circle,
.nu-feature-grid__icon svg rect,
.nu-feature-grid__icon svg polygon {
	fill: currentColor;
}

/* The filled card inverts: its icon reads against the orange fill. */
:where(.nu-feature-grid__card.is-highlight .nu-feature-grid__icon) {
	color: var(--color-5, #e0dcff);
}

:where(.nu-feature-grid__tagline) {
	margin: 0;
	font-family: 'Space Mono', monospace;
	font-weight: 700;
	font-size: 2.2rem;
	line-height: 1.2;
	text-transform: uppercase;
	text-align: center;
}

.nu-feature-grid__tagline {
	color: var(--color-5, #e0dcff);
}

.nu-feature-grid__card.is-highlight .nu-feature-grid__tagline {
	color: var(--color-5, #e0dcff);
}

:where(.nu-feature-grid__text) {
	font-family: 'Spline Sans', sans-serif;
	font-size: var(--text-s, 1.6rem);
	line-height: 1.5;
	text-align: center;
}

:where(.nu-feature-grid__text > *:first-child) { margin-top: 0; }
:where(.nu-feature-grid__text > *:last-child) { margin-bottom: 0; }

/* ----------------------------------------------------------- Separators */

/* The sign sits in the grid gutter to the right of the card it follows. */
.nu-feature-grid__card[data-separator='plus']::after,
.nu-feature-grid__card[data-separator='equals']::after {
	position: absolute;
	top: 50%;
	right: calc(var(--space-2xl, 7.92rem) * -1);
	width: var(--space-2xl, 7.92rem);
	transform: translateY(-50%);
	font-size: var(--text-2xl, 4.6rem);
	font-weight: 700;
	line-height: 1em;
	text-align: center;
	color: var(--color-5, #e0dcff);
	pointer-events: none;
}

.nu-feature-grid__card[data-separator='plus']::after   { content: '+'; }
.nu-feature-grid__card[data-separator='equals']::after { content: '='; }

/* ------------------------------------------------------------ Breakpoints */

@media (max-width: 991px) {
	:where(.nu-feature-grid__grid) {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* Phones swipe the cards sideways instead of stacking them. */
@media (max-width: 767px) {
	/* The cards become a full-bleed sideways scroller, so the section gives up
	   its gutter entirely. A plain class so it outranks nu-section.css. */
	.nu-feature-grid {
		--nu-section-space-inline: 0px;
	}

	:where(.nu-feature-grid__grid) {
		display: flex;
		flex-direction: row;
		flex-wrap: nowrap;
		overflow-x: auto;
		overflow-y: hidden;
		padding: var(--space-xl, 5.6rem);
		scroll-snap-type: x mandatory;
		-webkit-overflow-scrolling: touch;
	}

	:where(.nu-feature-grid__card) {
		min-width: 70%;
		padding: var(--space-4xl, 15.83rem) var(--space-xl, 5.6rem);
		scroll-snap-align: center;
	}

	/* No room for the signs in a scroller. */
	.nu-feature-grid__card[data-separator='plus']::after,
	.nu-feature-grid__card[data-separator='equals']::after {
		content: none;
	}
}

/* ============ nu-logo-marquee.css ============ */
/**
 * NÜ — Marquee logos.
 *
 * Two identical tracks sit side by side in a nowrap flex row; the pair slides
 * left by exactly one track width, so the second lands where the first started
 * and the loop is invisible. A mask fades both edges.
 *
 * Shared by the standalone Marquee element and by Section Confiance. The
 * heading / copy / button that wrap the band belong to the standalone element
 * only, so they hang off .nu-logo-marquee-wrap rather than the band itself.
 *
 * Zero-specificity :where() defaults so any builder value wins.
 *
 * Custom properties, set per instance by PHP:
 *   --nu-marquee-duration     one full loop (longer is slower)
 *   --nu-marquee-fade         width of the transparent edge on each side
 *   --nu-marquee-slot-width   the box every logo is fitted into
 *   --nu-marquee-slot-height  ditto
 *   --nu-marquee-logo-scale   per-logo optical nudge, set on the <li>
 *
 * Sizing: the marks range from 6:1 to 1:1, so nothing is sized by one axis —
 * each is fitted into a fixed slot with object-fit, which bounds the width and
 * the height at once. Sizing by height alone (what this used to do) turned the
 * 130×21 mark into a ~400px band that ran over its neighbours.
 */

:where(.nu-logo-marquee) {
	--nu-marquee-duration: 35s;
	--nu-marquee-fade: 200px;
	--nu-marquee-slot-width: 160px;
	--nu-marquee-slot-height: 64px;

	width: 100%;
	padding-block: var(--space-l, 3.96rem);
	overflow: hidden;
	border-radius: var(--radius-s, 0.8rem);
}

:where(.nu-logo-marquee__viewport) {
	display: flex;
	flex-direction: row;
	flex-wrap: nowrap;
	width: 100%;
	white-space: nowrap;

	-webkit-mask-image: linear-gradient(
		to right,
		transparent,
		#000 var(--nu-marquee-fade),
		#000 calc(100% - var(--nu-marquee-fade)),
		transparent
	);
	mask-image: linear-gradient(
		to right,
		transparent,
		#000 var(--nu-marquee-fade),
		#000 calc(100% - var(--nu-marquee-fade)),
		transparent
	);
}

:where(.nu-logo-marquee__track) {
	display: flex;
	flex-direction: row;
	flex-wrap: nowrap;
	flex-shrink: 0;
	align-items: center;
	width: max-content;
	max-width: max-content;
	margin: 0;
	padding: 0;
	list-style: none;
	white-space: nowrap;
	animation: nu-marquee-rtl var(--nu-marquee-duration) linear infinite;
}

/*
 * The item hugs its logo instead of padding it out to a fixed slot — a square
 * mark used to float in a 160px box, which read as random extra spacing around
 * the narrow logos (client note, 2026-08-12). The margins are what keep the
 * rhythm; the slot dimensions only bound the artwork.
 */
:where(.nu-logo-marquee__item) {
	display: flex;
	flex-shrink: 0;
	flex-wrap: nowrap;
	justify-content: center;
	align-items: center;
	height: var(--nu-marquee-slot-height);
	margin-inline: var(--space-m, 2.8rem);
}

:where(.nu-logo-marquee__link) {
	display: flex;
	align-items: center;
	justify-content: center;
	height: 100%;
}

/*
 * The artwork is bound by the slot on both axes — a wide mark ends up limited
 * by the width, a square one by the height, so none can outgrow its
 * neighbours whatever its aspect ratio — but the box collapses to the visible
 * mark, so the gap between two logos is always the margins above.
 */
:where(.nu-logo-marquee__logo) {
	display: block;
	width: auto;
	height: calc(var(--nu-marquee-slot-height) * var(--nu-marquee-logo-scale, 1));
	max-width: calc(var(--nu-marquee-slot-width) * var(--nu-marquee-logo-scale, 1));
	object-fit: contain;
	object-position: center;
	opacity: 0.8;
	transition: opacity 0.2s ease;
}

:where(.nu-logo-marquee__logo:hover) {
	opacity: 1;
}

.nu-logo-marquee--pausable:hover .nu-logo-marquee__track {
	animation-play-state: paused;
}

@keyframes nu-marquee-rtl {
	from { transform: translateX(0); }
	to   { transform: translateX(-100%); }
}

/* Respect a reduced-motion preference: hold the band still and let it scroll. */
@media (prefers-reduced-motion: reduce) {
	:where(.nu-logo-marquee__track) {
		animation: none;
	}

	:where(.nu-logo-marquee__viewport) {
		overflow-x: auto;
	}

	:where(.nu-logo-marquee__track[aria-hidden='true']) {
		display: none;
	}

	.nu-logo-marquee__button,
	.nu-logo-marquee__button-icon {
		transition: none;
	}

	.nu-logo-marquee__button:hover .nu-logo-marquee__button-icon,
	.nu-logo-marquee__button:focus-visible .nu-logo-marquee__button-icon {
		transform: none;
	}
}

@media (max-width: 767px) {
	:where(.nu-logo-marquee) {
		--nu-marquee-fade: 100px;

		padding-inline: var(--space-xl, 5.6rem);
	}
}


/* ------------------------------------------------- section around the band ---- */

/*
 * From the "Inventaires" export: a heading and copy above the band, which sits
 * on a white card, and a primary CTA below. The section shares the surface tint
 * with the channels grid above it, and carries no top padding — the two are
 * meant to read as one block.
 */
.nu-logo-marquee-wrap {
	--nu-marquee-max-width: 1400px;
	--nu-marquee-block-gap: 40px;
	--nu-marquee-card-padding: 40px;

	display: block;
	/*
	 * The export has no top padding (0 / 120 / 112) because in the design this
	 * band sat directly under another block inside the same tinted surface. It
	 * now takes the shared section rhythm instead, and the automatic join in
	 * nu-section.css restores the original look whenever the section above it is
	 * on the same surface — which is the case the export was drawn from.
	 */
}

.nu-logo-marquee-wrap__inner {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--nu-marquee-block-gap);
	width: 100%;
	max-width: var(--nu-marquee-max-width);
	margin-inline: auto;
}

.nu-logo-marquee__headings {
	display: flex;
	flex-direction: column;
	gap: 16px;
	width: 100%;
}

.nu-logo-marquee__heading {
	margin: 0;
	color: var(--text-title, #0f18c6);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: 46px;
	font-weight: 300;
	line-height: 1.2;
}

.nu-logo-marquee__subheading {
	margin: 0;
	color: var(--color-3, #061745);
	font-family: "Space Mono", ui-monospace, monospace;
	font-size: 18px;
	font-weight: 700;
	line-height: 1.1;
	text-transform: uppercase;
}

.nu-logo-marquee__text {
	max-width: 1220px;
	margin: 0;
	color: var(--color-3, #061745);
	font-size: 32px;
	font-weight: 300;
	line-height: 1.5;
}

/* The band becomes a card in this composition. */
.nu-logo-marquee-wrap .nu-logo-marquee {
	padding: var(--nu-marquee-card-padding);
	border-radius: 8px;
	background-color: var(--light, #fff);
}

.nu-logo-marquee__button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	padding: 12px 24px;
	border-radius: var(--radius-full, 30px);
	background-color: var(--color-2, #ee5101);
	color: var(--light, #fff);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: 16px;
	font-weight: 500;
	line-height: 24px;
	text-decoration: none;
	transition: background-color 0.25s ease;
}

/* Orange goes to brand blue on hover, as the home hero does. */
.nu-logo-marquee__button:hover,
.nu-logo-marquee__button:focus-visible {
	background-color: var(--color-1, #1600ba);
	color: var(--light, #fff);
}

.nu-logo-marquee__button-icon {
	display: inline-flex;
	flex: none;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-logo-marquee__button:hover .nu-logo-marquee__button-icon,
.nu-logo-marquee__button:focus-visible .nu-logo-marquee__button-icon {
	transform: translateX(10px);
}

.nu-logo-marquee__button-icon svg {
	display: block;
	width: 24px;
	height: 24px;
}

/* The shipped arrow carries a dark fill meant for light backgrounds. */
.nu-logo-marquee__button-icon svg path {
	fill: currentColor;
}

@media (max-width: 1279px) {
	.nu-logo-marquee__heading {
		font-size: 38px;
	}

	.nu-logo-marquee__text {
		font-size: 24px;
	}
}

@media (max-width: 767px) {
	.nu-logo-marquee-wrap {
		--nu-marquee-block-gap: 28px;
		--nu-marquee-card-padding: var(--space-m, 2.8rem);
	}

	.nu-logo-marquee__heading {
		font-size: 32px;
	}

	.nu-logo-marquee__text {
		font-size: 20px;
	}
}

/* ============ nu-cta.css ============ */
/**
 * NÜ — Section CTA (pre-footer).
 *
 * Two equal panels inside one rounded, clipped frame: orange copy on one side,
 * a photograph carrying the NÜ mark on the other. On phones the frame becomes a
 * column and the copy panel leads.
 *
 * Zero-specificity :where() defaults so any builder value wins. Colours that
 * must beat theme element rules use plain class selectors (0,1,0).
 *
 * Core Framework tokens (html font-size 62.5%, 1rem = 10px):
 *   frame   → var(--radius-m)
 *   panel   → var(--color-2) fill, var(--color-5) text
 *   button  → var(--color-5) fill, var(--color-3) text, radius-full
 */

:where(.nu-cta) {
	width: 100%;
}

:where(.nu-cta__inner) {
	max-width: 140rem;
	margin-inline: auto;
}

:where(.nu-cta__grid) {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 0;
	overflow: hidden;
	border-radius: var(--radius-m, 1.2rem);
}

/* Media on the left instead of the right. */
:where(.nu-cta--media-left .nu-cta__media) {
	order: -1;
}

/* ---------------------------------------------------------- Copy panel */

:where(.nu-cta__content) {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	justify-content: center;
	gap: var(--space-m, 2.8rem);
	padding: var(--space-3xl, 11.19rem) var(--space-2xl, 7.92rem);
	background-color: var(--color-2, #ef4400);
	color: var(--color-5, #e0dcff);
}

:where(.nu-cta__heading) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	text-align: left;
}

/* Theme styles colour headings; a class rule (0,1,0) beats them and still loses
 * to a Bricks control override. */
.nu-cta__heading,
.nu-cta__tagline {
	color: var(--color-5, #e0dcff);
	text-align: left;
}

:where(.nu-cta__tagline) {
	font-family: 'Space Mono', monospace;
	font-weight: 700;
	font-size: var(--text-tagline, 1.8rem);
	line-height: 1.3;
	text-transform: uppercase;
}

:where(.nu-cta__text) {
	font-family: 'Spline Sans', sans-serif;
	font-size: var(--text-m, 2rem);
	line-height: 1.5;
}

:where(.nu-cta__text > *:first-child) { margin-top: 0; }
:where(.nu-cta__text > *:last-child) { margin-bottom: 0; }

/* -------------------------------------------------------------- Button */

:where(.nu-cta__button) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.8rem;
	flex: none;
	min-height: 4.8rem;
	margin-top: var(--space-s, 1.98rem);
	padding: 1.2rem 2.4rem;
	border: 1px solid transparent;
	border-radius: var(--radius-full, 999rem);
	font-family: 'Spline Sans', sans-serif;
	font-weight: 500;
	font-size: var(--text-button, 1.6rem);
	line-height: 2.4rem;
	text-decoration: none;
	background-color: var(--color-5, #e0dcff);
	transition: background-color 0.25s ease, color 0.25s ease;
}

.nu-cta__button {
	color: var(--color-3, #061745);
}

:where(.nu-cta__button:hover),
:where(.nu-cta__button:focus-visible) {
	background-color: var(--light, #fff);
}

:where(.nu-cta__button-icon) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 2.4rem;
	height: 2.4rem;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-cta__button:hover .nu-cta__button-icon,
.nu-cta__button:focus-visible .nu-cta__button-icon {
	transform: translateX(10px);
}

:where(.nu-cta__button-icon svg) {
	width: 100%;
	height: 100%;
}

.nu-cta__button-icon svg path,
.nu-cta__button-icon svg circle,
.nu-cta__button-icon svg rect,
.nu-cta__button-icon svg polygon {
	fill: currentColor;
}

/* --------------------------------------------------------- Media panel */

:where(.nu-cta__media) {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 100%;
	padding: var(--space-2xl, 7.92rem);
	background-color: var(--color-3, #061745);
	background-position: center center;
	background-size: cover;
	background-repeat: no-repeat;
}

:where(.nu-cta__mark) {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	max-width: 32rem;
}

:where(.nu-cta__mark svg) {
	width: 100%;
	height: auto;
}

/* ------------------------------------------------------------ Breakpoints */

@media (max-width: 767px) {
	/*
	 * Tighter than the shared gutter: the frame inside is already rounded and
	 * inset, so the standard --space-l leaves it looking stranded on a phone.
	 * A plain class, not :where() — it has to outrank nu-section.css.
	 */
	.nu-cta {
		--nu-section-space-inline: var(--space-m, 2.8rem);
	}

	:where(.nu-cta__grid) {
		display: flex;
		flex-direction: column;
	}

	/* Copy leads on phones, whatever the desktop order. */
	:where(.nu-cta--media-left .nu-cta__media) {
		order: 0;
	}

	:where(.nu-cta__media) {
		height: 300px;
		min-height: 300px;
	}

	:where(.nu-cta__tagline) {
		line-height: 1.2em;
	}

	:where(.nu-cta__button) {
		width: 100%;
	}
}

@media (prefers-reduced-motion: reduce) {
	.nu-cta__button,
	.nu-cta__button-icon {
		transition: none;
	}

	.nu-cta__button:hover .nu-cta__button-icon,
	.nu-cta__button:focus-visible .nu-cta__button-icon {
		transform: none;
	}
}

/* ============ nu-confiance.css ============ */
/**
 * NÜ — Section Confiance.
 *
 * Testimonials on a fixed photographic background: heading, a carousel of glass
 * quote cards, then the client logo band. The Splide shell (edge bleed, arrows,
 * pagination bars) lives in nu-slider.css; the band in nu-logo-marquee.css.
 *
 * The background is attachment: fixed on desktop and scroll on phones — iOS
 * cannot composite a fixed background inside a transformed ancestor, and the
 * carousel transforms.
 *
 * Zero-specificity :where() defaults so any builder value wins. Colours that
 * must beat theme element rules use plain class selectors (0,1,0).
 *
 * Core Framework tokens (html font-size 62.5%, 1rem = 10px):
 *   card  → 1px var(--border-primary), radius-l, backdrop blur
 *   quote → 2rem / 300
 *   name  → Space Mono 700 1.6rem
 */

:where(.nu-confiance) {
	position: relative;
	width: 100%;
	overflow: hidden;
	background-position: center center;
	background-size: cover;
	background-repeat: no-repeat;
	background-attachment: fixed;
	color: var(--light, #fff);
}

/* Placeholder layer for the Background overlay control. */
:where(.nu-confiance__overlay) {
	position: absolute;
	inset: 0;
	pointer-events: none;
}

:where(.nu-confiance__inner) {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: var(--space-2xs, 0.99rem);
	max-width: 140rem;
	margin-inline: auto;
	z-index: 1;
}

:where(.nu-confiance__heading) {
	margin: 0 0 var(--space-xl, 5.6rem);
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
}

.nu-confiance__heading {
	color: var(--light, #fff);
}

/* --------------------------------------------------------------- Slider */

:where(.nu-confiance__slider) {
	--nu-slider-arrow-top: 180px;

	/* The pagination bars live in nu-slider.css and default to --dark-*,
	   all but invisible on the navy photo. Match the card borders instead
	   so the track reads clearly under the orange fill (QA pin 49). */
	--nu-slider-pagination-bar: var(--border-primary, rgba(224, 220, 255, 0.3));
	--nu-slider-pagination-bar-hover: rgba(224, 220, 255, 0.5);

	margin-bottom: var(--space-3xl, 11.19rem);
}

:where(.nu-confiance__slide) {
	display: flex;
	justify-content: flex-start;
	height: auto;
}

/* ----------------------------------------------------------- Quote card */

:where(.nu-confiance__card) {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: var(--space-m, 2.8rem);
	width: 100%;
	margin: 0;
	padding: var(--space-l, 3.96rem);
	border: 1px solid var(--border-primary, rgba(224, 220, 255, 0.3));
	border-radius: var(--radius-l, 2rem);
	backdrop-filter: blur(20px);
	-webkit-backdrop-filter: blur(20px);
	font-size: var(--text-s, 1.6rem);
}

:where(.nu-confiance__quote) {
	margin: 0;
	padding: 0;
	border: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: 2rem;
	line-height: 1.5;
}

:where(.nu-confiance__quote > *:first-child) { margin-top: 0; }
:where(.nu-confiance__quote > *:last-child) { margin-bottom: 0; }

/* The attribution hangs off the same left edge as the quote above it. */
:where(.nu-confiance__client) {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0;
	width: 100%;
	margin-top: auto;
	text-align: left;
}

:where(.nu-confiance__name) {
	font-family: 'Space Mono', monospace;
	font-weight: 700;
	font-size: 1.6rem;
	line-height: 1.4;
}

:where(.nu-confiance__role) {
	font-family: 'Spline Sans', sans-serif;
	font-size: 1.6rem;
	line-height: 1.4;
}

.nu-confiance__quote,
.nu-confiance__name,
.nu-confiance__role {
	color: var(--light, #fff);
}

/* ------------------------------------------------------------ Logo band */

:where(.nu-confiance__logos) {
	padding-block: var(--space-l, 3.96rem);
}

/* ------------------------------------------------------------ Breakpoints */

@media (max-width: 767px) {
	:where(.nu-confiance) {
		background-attachment: scroll;
	}

	/* Tighter gutter than the shared one; a plain class so it outranks
	   nu-section.css, which :where() would not. */
	.nu-confiance {
		--nu-section-space-inline: var(--space-m, 2.8rem);
	}

	:where(.nu-confiance__slider) {
		--nu-slider-arrow-top: 45%;

		margin-bottom: var(--space-2xl, 7.92rem);
	}
}

/* ============ nu-contact.css ============ */
/**
 * NÜ — Section Contact.
 *
 * Centred intro over two columns: the NÜ card on the left, a glass panel holding
 * the WS Form contact form on the right. Everything sits on the dark bg_3 photo,
 * so all copy is light.
 *
 * The form markup belongs to WS Form; only the few overrides the template
 * carried are repeated here (legend spacing, checkbox weight/size, and inputs
 * readable on a dark panel).
 *
 * Zero-specificity :where() defaults so any builder value wins. Colours that
 * must beat theme element rules use plain class selectors (0,1,0).
 *
 * Core Framework tokens (html font-size 62.5%, 1rem = 10px):
 *   panel   → 1px var(--border-primary), radius-l, backdrop blur
 *   pill    → var(--light-10) fill, radius-full
 *   primary → var(--color-2) fill
 */

:where(.nu-contact) {
	width: 100%;
	background-position: center center;
	background-size: cover;
	background-repeat: no-repeat;
	color: var(--light, #fff);
}

:where(.nu-contact__inner) {
	display: flex;
	flex-direction: column;
	gap: var(--space-xl, 5.6rem);
	max-width: 140rem;
	margin-inline: auto;
}

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

:where(.nu-contact__intro) {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-m, 2.8rem);
}

:where(.nu-contact__heading) {
	max-width: 60ch;
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	text-align: center;
}

:where(.nu-contact__text) {
	max-width: 80ch;
	font-family: 'Spline Sans', sans-serif;
	font-size: var(--text-m, 2rem);
	line-height: 1.5;
	text-align: center;
}

:where(.nu-contact__text > *:first-child) { margin-top: 0; }
:where(.nu-contact__text > *:last-child) { margin-bottom: 0; }

.nu-contact__heading,
.nu-contact__text,
.nu-contact__slogan,
.nu-contact__tagline,
.nu-contact__social-label {
	color: var(--light, #fff);
}

/* ---------------------------------------------------------------- Grid */

:where(.nu-contact__grid) {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--space-2xl, 7.92rem);
	align-items: start;
}

/* ------------------------------------------------------------- NÜ card */

:where(.nu-contact__info) {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-m, 2.8rem);
}

:where(.nu-contact__logo) {
	display: block;
	width: 100%;
	max-width: 200px;
	height: auto;
}

:where(.nu-contact__slogan) {
	max-width: 40ch;
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: var(--text-l, 2.2rem);
	line-height: 1.35;
}

:where(.nu-contact__tagline) {
	font-family: 'Space Mono', monospace;
	font-weight: 700;
	font-size: var(--text-s, 1.6rem);
	line-height: 1.4;
	text-transform: uppercase;
}

/* Contact pills */

/* The address line is long: the pill has to be allowed to wrap rather than run
 * past a narrow viewport, so it caps at the column and its text may shrink. */
:where(.nu-contact__link) {
	display: inline-flex;
	align-items: center;
	gap: 0.8rem;
	max-width: 100%;
	text-align: left;
	padding: var(--space-xs, 1.4rem) var(--space-s, 1.98rem);
	border: 1px solid var(--light-30, rgba(255, 255, 255, 0.3));
	border-radius: var(--radius-full, 999rem);
	background-color: var(--light-10, rgba(255, 255, 255, 0.1));
	font-family: 'Spline Sans', sans-serif;
	font-weight: 500;
	font-size: var(--text-button, 1.6rem);
	line-height: 2.4rem;
	text-decoration: none;
	transition: background-color 0.25s ease;
}

.nu-contact__link {
	color: var(--light, #fff);
}

:where(.nu-contact__link:hover),
:where(.nu-contact__link:focus-visible) {
	background-color: var(--light-20, rgba(255, 255, 255, 0.2));
}

:where(.nu-contact__link-icon) {
	display: inline-flex;
	flex: none;
	width: 2rem;
	height: 2rem;
}

/* Flex items refuse to shrink below their content width without this. */
:where(.nu-contact__link-text),
:where(.nu-contact__button-text) {
	min-width: 0;
}

:where(.nu-contact__link-icon svg) {
	width: 100%;
	height: 100%;
}

/* Primary button */

:where(.nu-contact__button) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.8rem;
	max-width: 100%;
	min-height: 4.8rem;
	padding: 1.2rem 2.4rem;
	border: 1px solid transparent;
	border-radius: var(--radius-full, 999rem);
	background-color: var(--color-2, #ef4400);
	font-family: 'Spline Sans', sans-serif;
	font-weight: 500;
	font-size: var(--text-button, 1.6rem);
	line-height: 2.4rem;
	text-decoration: none;
	transition: background-color 0.25s ease;
}

.nu-contact__button {
	color: var(--light, #fff);
}

/* Orange goes to brand blue on hover, as the home hero does. */
:where(.nu-contact__button:hover),
:where(.nu-contact__button:focus-visible) {
	background-color: var(--color-1, #1600ba);
}

:where(.nu-contact__button-icon) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 2rem;
	height: 2rem;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-contact__button:hover .nu-contact__button-icon,
.nu-contact__button:focus-visible .nu-contact__button-icon {
	transform: translateX(10px);
}

:where(.nu-contact__button-icon svg) {
	width: 100%;
	height: 100%;
}

.nu-contact__link-icon svg path,
.nu-contact__button-icon svg path,
.nu-contact__link-icon svg circle,
.nu-contact__button-icon svg circle {
	fill: currentColor;
}

.nu-contact__link-icon svg [stroke]:not([stroke='none']),
.nu-contact__button-icon svg [stroke]:not([stroke='none']) {
	stroke: currentColor;
}

/* Social */

:where(.nu-contact__social) {
	display: flex;
	flex-direction: column;
	gap: var(--space-3xs, 0.7rem);
}

:where(.nu-contact__social-label) {
	font-family: 'Spline Sans', sans-serif;
	font-weight: 600;
	font-size: var(--text-s, 1.6rem);
}

:where(.nu-contact__social-list) {
	display: flex;
	flex-direction: row;
	gap: var(--space-3xs, 0.7rem);
	margin: 0;
	padding: 0;
	list-style: none;
}

:where(.nu-contact__social-link) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 45px;
	height: 45px;
	border: 1px solid var(--light-30, rgba(255, 255, 255, 0.3));
	border-radius: var(--radius-full, 999rem);
	font-size: 19px;
	line-height: 1em;
	text-decoration: none;
	transition: background-color 0.25s ease;
}

.nu-contact__social-link {
	color: var(--light, #fff);
}

:where(.nu-contact__social-link:hover),
:where(.nu-contact__social-link:focus-visible) {
	background-color: var(--light-20, rgba(255, 255, 255, 0.2));
}

:where(.nu-contact__social-link svg) {
	width: 19px;
	height: 19px;
	fill: currentColor;
}

/* ---------------------------------------------------------- Form panel */

:where(.nu-contact__form) {
	display: flex;
	flex-direction: column;
	gap: var(--space-m, 2.8rem);
	padding: var(--space-l, 3.96rem);
	border: 1px solid var(--border-primary, rgba(224, 220, 255, 0.3));
	border-radius: var(--radius-l, 2rem);
	backdrop-filter: blur(20px);
	-webkit-backdrop-filter: blur(20px);
	font-size: var(--text-s, 1.6rem);
}

/* WS Form overrides carried over from the template. */
.nu-contact__form .form_required-legend {
	margin-bottom: var(--space-m, 2.8rem);
}

.nu-contact__form .wsf-form input[type='checkbox'].wsf-field:checked::after {
	background: none;
	border-color: var(--color-1, #1600ba);
}

.nu-contact__form .wsf-form input[type='checkbox'].wsf-field + label.wsf-label {
	font-weight: 400;
	font-size: var(--text-s, 1.6rem);
}

/* Labels and help text have to read on the dark panel. */
.nu-contact__form .wsf-form,
.nu-contact__form .wsf-form label,
.nu-contact__form .wsf-form legend {
	color: var(--light, #fff);
}

/* ------------------------------------------------------------ Breakpoints */

@media (max-width: 991px) {
	:where(.nu-contact__grid) {
		gap: var(--space-xl, 5.6rem);
	}
}

@media (max-width: 767px) {
	/* Tighter gutter than the shared one; a plain class so it outranks
	   nu-section.css, which :where() would not. Top padding is floored at the
	   mobile header bar's ~130px so the intro can't slide under the menu —
	   same guard as nu-hero-inner. */
	.nu-contact {
		--nu-section-space-inline: var(--space-m, 2.8rem);
		--nu-section-pt: max(var(--nu-section-space, 11.19rem), 17rem);
	}

	:where(.nu-contact__inner) {
		gap: var(--space-l, 3.96rem);
	}

	:where(.nu-contact__grid) {
		display: flex;
		flex-direction: column;
	}

	/* The form leads on phones; the card follows. */
	:where(.nu-contact__info) {
		order: 2;
		align-items: center;
		text-align: center;
	}

	:where(.nu-contact__form) {
		order: 1;
	}

	:where(.nu-contact__logo) {
		max-width: 108px;
	}

	:where(.nu-contact__slogan),
	:where(.nu-contact__tagline) {
		max-width: 100%;
		text-align: center;
	}

	:where(.nu-contact__tagline) {
		max-width: 320px;
		line-height: 1.2em;
	}

	:where(.nu-contact__social) {
		flex-direction: row;
		align-items: center;
		justify-content: center;
		gap: var(--space-s, 1.98rem);
	}
}

@media (prefers-reduced-motion: reduce) {
	.nu-contact__button,
	.nu-contact__button-icon {
		transition: none;
	}

	.nu-contact__button:hover .nu-contact__button-icon,
	.nu-contact__button:focus-visible .nu-contact__button-icon {
		transform: none;
	}
}

/* ============ nu-footer.css ============ */
/**
 * NÜ footer
 *
 * Rebuilt for parity with the Figma "Footer" frame (1680×959 canvas, 1440
 * content). The px values below are the export's, kept in px rather than rem so
 * the composition ignores the theme's 62.5% root size — the same choice the
 * other NÜ elements make.
 *
 * Vertical spine, measured off the export and reproduced exactly:
 *   70   padding top
 *   580  column grid (the "Canaux média" column is what sets this)
 *   112  gap to the bottom bar
 *   40   bottom bar
 *   52   gap to the partner row
 *   45   partner row
 *   60   padding bottom       = 959
 *
 * Link rhythm is normalised to a 24px line box + 16px gap (40px pitch). The
 * export mixes 120% and 150% line heights between columns — and even within the
 * "Solutions" column — while "Canaux média" is internally consistent at 150%.
 * That is the one the 580px height depends on, so it wins.
 *
 * Selectors here stay plain classes. Bricks writes a control's CSS as
 * "#brxe-{id} .selector", which outranks a class on its own — so nothing needs
 * :where() to stay overridable, and :where() would in fact sink these defaults
 * below the theme's global h1-h6 rules, which is where the headings live.
 *
 * @see elements/nu-footer.php
 */

.nu-footer {
	--nu-ft-bg: #171717;
	--nu-ft-ink: var(--light, #fff);
	--nu-ft-muted: #767676;
	--nu-ft-field-border: #c2c2c2;
	--nu-ft-hairline: var(--light-30, rgba(255, 255, 255, 0.3));
	--nu-ft-pill-border: var(--light-20, rgba(255, 255, 255, 0.2));
	--nu-ft-divider: rgba(255, 255, 255, 0.15);

	--nu-ft-font-body: "Spline Sans", system-ui, sans-serif;
	--nu-ft-font-display: "Space Mono", ui-monospace, monospace;

	--nu-ft-max-width: 1400px;
	--nu-ft-brand-width: 300px;
	--nu-ft-col-width: 180px;
	--nu-ft-col-offset: 97px;
	--nu-ft-logo-width: 80px;

	--nu-ft-pad-block-start: 70px;
	--nu-ft-pad-block-end: 60px;
	--nu-ft-pad-inline: 16px;
	--nu-ft-gap-section: 52px;
	--nu-ft-gap-content: 112px;
	--nu-ft-gap-row: 16px;
	--nu-ft-gap-text: 21px;
	--nu-ft-gap-group: 30px;

	--nu-ft-partner-height: 45px;
	--nu-ft-partner-gap: 70px;

	--nu-ft-watermark-width: 656px;
	--nu-ft-watermark-height: 485px;
	--nu-ft-watermark-image: none;
}

.nu-footer {
	position: relative;
	isolation: isolate;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--nu-ft-gap-section);
	padding: var(--nu-ft-pad-block-start) var(--nu-ft-pad-inline) var(--nu-ft-pad-block-end);
	background-color: var(--nu-ft-bg);
	color: var(--nu-ft-ink);
	font-family: var(--nu-ft-font-body);
	overflow: hidden;
}

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

.nu-footer ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

.nu-footer p {
	margin: 0;
}

.nu-footer a {
	color: inherit;
	text-decoration: none;
}

/* ------------------------------------------------------------- watermark ---- */

/*
 * Three 656×485 outlines side by side with the middle one centred on the
 * canvas, per the export. repeat-x from a centred position reproduces that at
 * any width. The source file already carries the 3% opacity, so nothing here
 * dims it a second time.
 */
.nu-footer__watermark {
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	background-image: var(--nu-ft-watermark-image);
	background-repeat: repeat-x;
	background-position: 50% 50%;
	background-size: var(--nu-ft-watermark-width) var(--nu-ft-watermark-height);
}

/* --------------------------------------------------------------- content ---- */

.nu-footer__inner,
.nu-footer__partners {
	position: relative;
	z-index: 1;
	width: 100%;
}

.nu-footer__inner {
	display: flex;
	flex-direction: column;
	gap: var(--nu-ft-gap-content);
	max-width: var(--nu-ft-max-width);
}

/*
 * 300 + 4×180 = 1020 in a 1440 track, distributed — the export's 105px gutters
 * fall out of space-between rather than being hard-coded. --nu-ft-cols is
 * written inline by the element, since only it knows how many columns rendered.
 */
.nu-footer__main {
	display: grid;
	grid-template-columns: var(--nu-ft-brand-width) repeat(var(--nu-ft-cols, 4), var(--nu-ft-col-width));
	justify-content: space-between;
	align-items: start;
	column-gap: var(--nu-ft-gap-row);
	row-gap: var(--nu-ft-gap-section);
}

/* ----------------------------------------------------------------- brand ---- */

.nu-footer__brand {
	display: flex;
	flex-direction: column;
	gap: var(--nu-ft-gap-group);
}

.nu-footer__logo {
	display: block;
	width: var(--nu-ft-logo-width);
}

.nu-footer__logo svg,
.nu-footer__logo img {
	display: block;
	width: 100%;
	height: auto;
}

/* The mark ships with its own fill; follow the footer's ink colour instead. */
.nu-footer__logo svg path {
	fill: currentColor;
}

.nu-footer__intro {
	display: flex;
	flex-direction: column;
	gap: var(--nu-ft-gap-group);
}

.nu-footer__pitch {
	display: flex;
	flex-direction: column;
	gap: var(--nu-ft-gap-text);
}

.nu-footer__headline {
	margin: 0;
	font-size: 20px;
	font-weight: 400;
	line-height: 1.5;
	letter-spacing: 0.02em;
}

.nu-footer__tagline {
	font-size: 14px;
	line-height: 1.5;
	letter-spacing: 0.02em;
}

/* ------------------------------------------------------------ newsletter ---- */

.nu-footer__newsletter {
	display: flex;
	flex-direction: column;
	gap: var(--nu-ft-gap-row);
}

.nu-footer__newsletter-head {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

/* The headings are h2s, so they inherit the theme's global heading styles —
   size, weight, line-height and the title colour all have to be restated. */
.nu-footer__newsletter-title {
	margin: 0;
	color: inherit;
	font-family: var(--nu-ft-font-display);
	font-size: 16px;
	font-weight: 700;
	line-height: 1.2;
	text-transform: uppercase;
}

.nu-footer__newsletter-text {
	font-size: 14px;
	line-height: 1.5;
}

/*
 * The field frame is drawn here, not by the form plugin: WS Form's own chrome is
 * reset below so its input sits transparent inside this box. That keeps the
 * submissions, validation and notifications in WS Form while the appearance
 * stays with the design.
 */
.nu-footer__form {
	display: flex;
	align-items: center;
	gap: var(--nu-ft-gap-row);
	height: 48px;
	padding: 0 16px;
	border: 1px solid var(--nu-ft-field-border);
	border-radius: 4px;
}

.nu-footer__form:focus-within {
	border-color: var(--nu-ft-ink);
}

/* --------------------------------------------------------------- columns ---- */

.nu-footer__col {
	display: flex;
	flex-direction: column;
	gap: var(--nu-ft-gap-row);
	/* Aligns the column headings with the brand headline, not with the logo. */
	padding-top: var(--nu-ft-col-offset);
}

.nu-footer__col-title {
	margin: 0;
	color: inherit;
	font-family: var(--nu-ft-font-display);
	font-size: 16px;
	font-weight: 700;
	line-height: 1.2;
	text-transform: uppercase;
}

/*
 * The heading is always a button so the accordion needs no DOM surgery on
 * resize; above the breakpoint the script disables it, which also drops it out
 * of the tab order. `display: contents` is not an option — the spec makes it
 * compute to `inline` on form controls, and the UA's centred text then shifts
 * the label off the column's left edge.
 */
.nu-footer__col-toggle {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	width: 100%;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	color: inherit;
	font: inherit;
	letter-spacing: inherit;
	text-align: left;
	text-transform: inherit;
}

.nu-footer__col-toggle:disabled {
	cursor: default;
	opacity: 1;
	color: inherit;
}

.nu-footer__col-chevron {
	display: none;
}

/*
 * The type is restated on the list, not just on the link: each <li> is a flex
 * item whose height comes from its own line box, and the theme's inherited
 * 20px/34px would make that box 34px tall regardless of the 24px link inside —
 * turning the design's 40px rhythm into 50px.
 */
.nu-footer__links {
	display: flex;
	flex-direction: column;
	gap: var(--nu-ft-gap-row);
	font-size: 16px;
	line-height: 1.5;
}

.nu-footer__link {
	display: inline-block;
	font-size: 16px;
	line-height: 1.5;
	transition: opacity 0.25s ease;
}

.nu-footer__link:hover,
.nu-footer__link:focus-visible {
	opacity: 0.7;
	text-decoration: underline;
	text-underline-offset: 3px;
}

.nu-footer__link[aria-current="page"] {
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* --------------------------------------------------------------- contact ---- */

.nu-footer__contact {
	display: flex;
	flex-direction: column;
	gap: var(--nu-ft-gap-text);
}

.nu-footer__contact-item {
	font-size: 14px;
	line-height: 1.5;
}

a.nu-footer__contact-item:hover,
a.nu-footer__contact-item:focus-visible {
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* 24px line box + 8px block padding = the export's 40px pill. */
.nu-footer__button {
	display: inline-flex;
	align-self: flex-start;
	align-items: center;
	justify-content: center;
	gap: 8px;
	min-height: 40px;
	padding: 8px 24px;
	border: 1px solid currentColor;
	border-radius: 30px;
	font-size: 14px;
	font-weight: 500;
	line-height: 24px;
	white-space: nowrap;
	transition: background-color 0.25s ease, color 0.25s ease;
}

.nu-footer__button:hover,
.nu-footer__button:focus-visible {
	background-color: var(--nu-ft-ink);
	color: var(--nu-ft-bg);
}

.nu-footer__button-icon {
	display: inline-flex;
	flex: none;
}

.nu-footer__button-icon svg {
	display: block;
	width: 24px;
	height: 24px;
}

/* The shipped arrow carries a dark fill meant for light backgrounds. */
.nu-footer__button-icon svg path {
	fill: currentColor;
}

.nu-footer__social {
	display: flex;
	flex-direction: column;
	gap: 14px;
	margin-top: var(--nu-ft-gap-group);
}

.nu-footer__social-list {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.nu-footer__social-link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 50px;
	height: 40px;
	border: 1px solid var(--nu-ft-hairline);
	border-radius: var(--radius-full, 40px);
	font-size: 19px;
	line-height: 1em;
	transition: border-color 0.25s ease, background-color 0.25s ease;
}

.nu-footer__social-link:hover,
.nu-footer__social-link:focus-visible {
	border-color: var(--nu-ft-ink);
	background-color: var(--light-10, rgba(255, 255, 255, 0.1));
}

.nu-footer__social-link svg {
	display: block;
	width: 22px;
	height: 22px;
	fill: currentColor;
}

/* An uploaded mark may carry its own fill; follow the footer's ink instead. */
.nu-footer__social-link svg path {
	fill: currentColor;
}

/* ------------------------------------------------------------ bottom bar ---- */

.nu-footer__bottom {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 32px;
	min-height: 40px;
}

.nu-footer__copyright,
.nu-footer__legal-link {
	font-size: 14px;
	line-height: 1.6;
}

.nu-footer__legal-link:hover,
.nu-footer__legal-link:focus-visible {
	text-decoration: underline;
	text-underline-offset: 3px;
}

.nu-footer__lang {
	position: relative;
}

.nu-footer__lang-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	height: 40px;
	padding: 0 16px;
	border: 1px solid var(--nu-ft-pill-border);
	border-radius: 30px;
	background: none;
	color: inherit;
	font-family: inherit;
	font-size: 16px;
	font-weight: 600;
	line-height: 20px;
	cursor: pointer;
	transition: border-color 0.25s ease;
}

.nu-footer__lang-toggle:hover,
.nu-footer__lang-toggle:focus-visible {
	border-color: var(--nu-ft-ink);
}

.nu-footer__lang-chevron {
	display: block;
	flex: none;
	width: 10px;
	height: 10px;
	transition: transform 0.25s ease;
}

.nu-footer__lang[data-open="true"] .nu-footer__lang-chevron {
	transform: rotate(180deg);
}

/* Opens upwards: the switcher sits at the bottom of the page. */
.nu-footer__lang-menu {
	position: absolute;
	bottom: calc(100% + 8px);
	left: 0;
	z-index: 2;
	min-width: 100%;
	padding: 6px;
	border: 1px solid var(--nu-ft-pill-border);
	border-radius: 12px;
	background-color: var(--nu-ft-bg);
}

.nu-footer__lang[data-open="false"] .nu-footer__lang-menu {
	display: none;
}

.nu-footer__lang-link {
	display: block;
	padding: 6px 10px;
	border-radius: 8px;
	font-size: 14px;
	font-weight: 600;
	white-space: nowrap;
}

.nu-footer__lang-link:hover,
.nu-footer__lang-link:focus-visible {
	background-color: var(--light-10, rgba(255, 255, 255, 0.1));
}

/* -------------------------------------------------------------- partners ---- */

/*
 * The nine logos plus eight 70px gaps come to exactly the export's 1400px row,
 * so centring reproduces it edge to edge at full width — and keeps the row
 * centred once it wraps, which space-between would not.
 */
.nu-footer__partners {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 24px var(--nu-ft-partner-gap);
	max-width: var(--nu-ft-max-width);
	min-height: var(--nu-ft-partner-height);
}

.nu-footer__partner {
	display: flex;
	flex: none;
	align-items: center;
	justify-content: center;
}

.nu-footer__partner img,
.nu-footer__partner svg {
	display: block;
	width: auto;
	max-width: 100%;
	max-height: var(--nu-ft-partner-height);
	object-fit: contain;
}

/* ------------------------------------------------------------- WS Form ---- */

/*
 * The newsletter form keeps living in WS Form; only its chrome is reset so its
 * input sits inside .nu-footer__form's frame. Everything is scoped to that
 * wrapper, so no other form on the site is touched.
 *
 * Two things to know before editing this block:
 *
 *  - WS Form renders client-side. The shortcode outputs an empty <form> and the
 *    plugin's JS builds the fields on DOM-ready, so nothing here can rely on
 *    server markup — and the frame is visible for a beat before the input lands
 *    inside it. That is why the frame is drawn on our wrapper, not on the form.
 *  - The plugin's stylesheets load *after* this file, and its own field and
 *    button rules reach three classes themselves (`.wsf-form
 *    input[type=email].wsf-field`, `.wsf-form button.wsf-button.wsf-button-primary`)
 *    — a tie loses on order, so the field and button resets sit at *four*
 *    classes (`.wsf-fields` is always in the chain). The `wsf-N-…` ids are
 *    numbered by form instance on the page, not by form ID — never key off
 *    them.
 *
 * WS Form's styler already paints a 1px #C2C2C2 4px-radius frame on the <form>
 * itself. It is zeroed below so the design lives in one place and survives the
 * form being swapped for another.
 */
.nu-footer__form .wsf-form {
	display: flex;
	flex: 1;
	align-items: center;
	min-width: 0;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
	font-family: inherit;
}

.nu-footer__form .wsf-form .wsf-sections,
.nu-footer__form .wsf-form .wsf-section,
.nu-footer__form .wsf-form .wsf-fields {
	display: flex;
	flex-wrap: nowrap;
	align-items: center;
	/* The section is a <fieldset>; without this it refuses to shrink. */
	min-width: 0;
	min-inline-size: 0;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
}

/*
 * WS Form's responsive grid ships `.wsf-extra-small-12 { flex: 0 0 100%;
 * max-width: 100% !important }`, which every wrapper in this form carries. Both
 * declarations are !important, so laying the field and its submit out on one
 * row needs !important back — on these two properties only, and only inside the
 * footer's field.
 */
.nu-footer__form .wsf-form .wsf-sections,
.nu-footer__form .wsf-form .wsf-section,
.nu-footer__form .wsf-form .wsf-fields,
.nu-footer__form .wsf-form .wsf-field-wrapper {
	flex: 1 1 0% !important;
	max-width: none !important;
}

/* The form's submit field carries WS Form's "vertical align: bottom" utility
   (`.wsf-bottom { align-self: flex-end !important }`), which sank the arrow
   below the input's midline; !important against !important, higher specificity
   wins. */
.nu-footer__form .wsf-form .wsf-field-wrapper[data-type="submit"] {
	flex: 0 0 auto !important;
	align-self: center !important;
}

.nu-footer__form .wsf-form .wsf-fields {
	gap: var(--nu-ft-gap-row);
}

/* Static, so the absolutely-positioned validation message below anchors to the
   frame rather than to the field's own wrapper. */
.nu-footer__form .wsf-form .wsf-field-wrapper {
	position: static;
	display: flex;
	align-items: center;
	min-width: 0;
	margin: 0;
	padding: 0;
}

.nu-footer__form .wsf-form .wsf-field-wrapper[data-type="submit"] {
	width: 16px;
}

.nu-footer__form .wsf-form .wsf-fields input.wsf-field {
	flex: 1;
	width: 100%;
	min-width: 0;
	height: auto;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
	box-shadow: none;
	color: var(--nu-ft-ink);
	font-family: inherit;
	font-size: 16px;
	line-height: 1.5;
}

.nu-footer__form .wsf-form .wsf-fields input.wsf-field::placeholder {
	color: var(--nu-ft-muted);
	opacity: 1;
}

.nu-footer__form .wsf-form .wsf-fields input.wsf-field:focus {
	outline: none;
	box-shadow: none;
}

/* The placeholder carries the field's meaning; a visible label would not fit. */
.nu-footer__form .wsf-form label.wsf-label,
.nu-footer__form .wsf-form legend {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* The submit collapses to the bare arrow the design calls for. */
.nu-footer__form .wsf-form .wsf-fields .wsf-button {
	display: flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: 16px;
	height: 24px;
	min-height: 0;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
	box-shadow: none;
	color: transparent;
	font-size: 0;
	cursor: pointer;
}

/* The plugin re-skins .wsf-button-primary on hover/focus/active; keep the
   button bare in every state. */
.nu-footer__form .wsf-form .wsf-fields .wsf-button:hover,
.nu-footer__form .wsf-form .wsf-fields .wsf-button:focus,
.nu-footer__form .wsf-form .wsf-fields .wsf-button:active {
	border: 0;
	background: none;
	box-shadow: none;
}

/* Masked rather than inlined, so it follows --nu-ft-ink like everything else. */
.nu-footer__form .wsf-form .wsf-fields .wsf-button::after {
	content: "";
	display: block;
	width: 12px;
	height: 11px;
	background-color: var(--nu-ft-ink);
	-webkit-mask: var(--nu-ft-arrow) no-repeat center / contain;
	mask: var(--nu-ft-arrow) no-repeat center / contain;
	transition: transform 0.3s;
}

/* The NÜ arrow nudge — same motion as the hero CTA. */
.nu-footer__form .wsf-form .wsf-fields .wsf-button:hover::after,
.nu-footer__form .wsf-form .wsf-fields .wsf-button:focus-visible::after {
	transform: translateX(10px);
}

@media (prefers-reduced-motion: reduce) {
	.nu-footer__form .wsf-form .wsf-fields .wsf-button::after {
		transition: none;
	}

	.nu-footer__form .wsf-form .wsf-fields .wsf-button:hover::after,
	.nu-footer__form .wsf-form .wsf-fields .wsf-button:focus-visible::after {
		transform: none;
	}
}

.nu-footer__form {
	position: relative;
	--nu-ft-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='11' viewBox='0 0 12 11'%3E%3Cpath d='M6.90891 10.1818L6.03391 9.31818L9.63619 5.71591H0.306641V4.46591H9.63619L6.03391 0.875L6.90891 0L11.9998 5.09091L6.90891 10.1818Z' fill='%23fff'/%3E%3C/svg%3E");
}

/* Validation sits outside the 48px frame so it never pushes the layout. */
.nu-footer__form .wsf-form .wsf-invalid-feedback {
	position: absolute;
	top: calc(100% + 4px);
	left: 0;
	font-size: 12px;
	line-height: 1.4;
}

/* ------------------------------------------------------------ responsive ---- */

@media (max-width: 1280px) {
	.nu-footer {
		--nu-ft-brand-width: 280px;
		--nu-ft-col-width: 160px;
		--nu-ft-gap-content: 80px;
	}
}

@media (max-width: 1100px) {
	.nu-footer__main {
		grid-template-columns: minmax(260px, 1fr) repeat(2, minmax(0, 1fr));
		justify-content: start;
		column-gap: var(--nu-ft-gap-section);
	}

	.nu-footer__brand {
		grid-column: 1 / -1;
		max-width: var(--nu-ft-brand-width);
	}

	.nu-footer__col {
		padding-top: 0;
	}
}

@media (max-width: 991px) {
	.nu-footer {
		--nu-ft-gap-content: 64px;
		--nu-ft-col-offset: 0px;
	}

	.nu-footer__main {
		grid-template-columns: minmax(0, 1fr);
		row-gap: 0;
	}

	.nu-footer__brand {
		max-width: none;
		margin-bottom: var(--nu-ft-gap-section);
	}

	.nu-footer__form {
		max-width: 360px;
	}

	/* Collapsed columns: the heading is the toggle and the body folds away. */
	.nu-footer__col {
		gap: 0;
		padding: 0;
		border-bottom: 1px solid var(--nu-ft-divider);
	}

	.nu-footer__col-toggle {
		padding: 16px 0;
		cursor: pointer;
	}

	.nu-footer__col-chevron {
		display: block;
		flex: none;
		width: 14px;
		height: 9px;
		transition: transform 0.25s ease;
	}

	.nu-footer__col[data-open="true"] .nu-footer__col-chevron {
		transform: rotate(180deg);
	}

	/* Only the script sets data-open, so with no JS every column stays open. */
	.nu-footer__col[data-open="false"] .nu-footer__body {
		display: none;
	}

	.nu-footer__body {
		padding-bottom: 20px;
	}

	.nu-footer__social {
		margin-top: 24px;
	}

	.nu-footer__partners {
		gap: 24px 40px;
	}
}

@media (max-width: 767px) {
	.nu-footer {
		--nu-ft-pad-block-start: 48px;
		--nu-ft-pad-block-end: 40px;
		--nu-ft-gap-section: 40px;
		--nu-ft-gap-content: 48px;
		--nu-ft-partner-height: 34px;
	}

	.nu-footer__bottom {
		gap: 16px 24px;
	}

	.nu-footer__partners {
		gap: 20px 32px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.nu-footer *,
	.nu-footer *::before,
	.nu-footer *::after {
		transition: none !important;
	}
}

/* ============ nu-intro.css ============ */
/**
 * NÜ — Section Intro
 *
 * Ported from the "intro-text" export, whose styling lived entirely in the
 * global classes `intro` / `intro__container` / `tagline` / `intro__tagline` /
 * `text-intro`. The section and container paddings come from Bricks' theme
 * styles for `.brxe-section` / `.brxe-container`, which a custom element does
 * not inherit — so they are restated here.
 *
 * One deliberate difference: `.tagline` sets `text-align: center`, but in the
 * export the heading is a shrink-to-fit flex item, so it reads as left-aligned.
 * Left alignment is stated directly rather than reproducing that side effect.
 *
 * @see elements/nu-intro.php
 */

.nu-intro {
	--nu-intro-max-width: 1400px;
	--nu-intro-gap: var(--space-s, 1.98rem);
	--nu-intro-text-max-width: 80%;

	/* Re-pointed per theme below, never restyled part by part — a colour
	   control on any single part still wins over the theme it sits in. The
	   surface itself comes from nu-section.css. */
	--nu-intro-tagline-color: var(--color-1, #1600ba);
	--nu-intro-ink: var(--color-3, #061745);
	--nu-intro-button-bg: var(--color-2, #ee5101);
	--nu-intro-button-bg-hover: var(--color-1, #1600ba);
	--nu-intro-button-ink: var(--light, #fff);

	color: var(--nu-intro-ink);

	/* `section_scroll` in the export: keeps a wide child from adding a scrollbar. */
	overflow: hidden;
}

.nu-intro__inner {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--nu-intro-gap);
	width: 100%;
	max-width: var(--nu-intro-max-width);
	margin-inline: auto;
}

.nu-intro__tagline {
	margin: 0;
	color: var(--nu-intro-tagline-color);
	font-family: "Space Mono", ui-monospace, monospace;
	font-size: var(--text-tagline, 1.8rem);
	font-weight: 700;
	line-height: 1.1;
	text-transform: uppercase;
}

.nu-intro__text {
	max-width: var(--nu-intro-text-max-width);
	margin: 0;
	font-size: var(--text-xl, 3.2rem);
	font-weight: 300;
	line-height: 1.7;
}

/*
 * Multi-paragraph copy. The paragraphs are their own block rather than flex
 * children of the section, so they sit a paragraph apart instead of a section
 * gap apart. One line-height of space reads as a paragraph break at this size.
 */
.nu-intro__text--stacked {
	display: flex;
	flex-direction: column;
	gap: 1.7em;
}

.nu-intro__text--stacked p {
	margin: 0;
	font: inherit;
}

@media (max-width: 478px) {
	.nu-intro__text {
		max-width: 100%;
	}
}


/* ---------------------------------------------------------------- themes ---- */

/*
 * Only the ink. The surfaces themselves are `.nu-section--{key}` in
 * nu-section.css, so every section painting "light purple" paints exactly the
 * same colour — which is what lets the automatic join trust the class.
 *
 * On the dark surface the tagline cannot stay in color-1 — it disappears into
 * the background — so it takes the pale tint the rest of the site uses for
 * accents on dark.
 */
.nu-intro--dark {
	--nu-intro-ink: var(--light, #fff);
	--nu-intro-tagline-color: var(--color-5, #e0dcff);
}

/* ---------------------------------------------------------------- button ---- */

.nu-intro__button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	margin-top: var(--space-xs, 1.4rem);
	padding: 12px 24px;
	border-radius: var(--radius-full, 999rem);
	background-color: var(--nu-intro-button-bg);
	color: var(--nu-intro-button-ink);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: 16px;
	font-weight: 500;
	line-height: 24px;
	text-decoration: none;
	transition: background-color 0.25s ease;
}

/* Orange goes to brand blue on hover, as the home hero does. */
.nu-intro__button:hover,
.nu-intro__button:focus-visible {
	background-color: var(--nu-intro-button-bg-hover);
	color: var(--nu-intro-button-ink);
}

.nu-intro__button-icon {
	display: inline-flex;
	flex: none;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-intro__button:hover .nu-intro__button-icon,
.nu-intro__button:focus-visible .nu-intro__button-icon {
	transform: translateX(10px);
}

.nu-intro__button-icon svg {
	display: block;
	width: 24px;
	height: 24px;
}

/* The shipped arrow carries a dark fill meant for light backgrounds. */
.nu-intro__button-icon svg path {
	fill: currentColor;
}

@media (prefers-reduced-motion: reduce) {
	.nu-intro__button,
	.nu-intro__button-icon {
		transition: none;
	}

	.nu-intro__button:hover .nu-intro__button-icon,
	.nu-intro__button:focus-visible .nu-intro__button-icon {
		transform: none;
	}
}

/* ============ nu-hero-inner.css ============ */
/**
 * NÜ — Hero (page interne)
 *
 * Ported from the "hero-inner-solid" export. The section paints the photo, an
 * ::after tint sits over it, and the copy panel is pinned to the bottom — the
 * export gets that from `justify-content: flex-end` on the section, which is a
 * flex column by Bricks' theme styles.
 *
 * The source pages put *two* navy layers over the photo — a `color-3-40`
 * gradient overlay on the section, plus the `hero-inner` class's own scrim,
 * which the site's GSAP intro settles at 0.3. Both are the same colour, so one
 * layer at 1 - (1 - 0.4)(1 - 0.3) = 0.58 renders identically and leaves a
 * single knob to turn. Keeping it a separate layer rather than folding it into
 * the background image means the opacity stays animatable.
 *
 * @see elements/nu-hero-inner.php
 */

.nu-hero-inner {
	--nu-hero-max-width: 1400px;
	--nu-hero-panel-width: 110rem;
	--nu-hero-panel-blur: 20px;
	--nu-hero-overlay-color: var(--color-3, #061745);
	--nu-hero-overlay-opacity: 0.58;
	--nu-hero-image: none;
	--nu-hero-image-position: center center;
	--nu-hero-ink: var(--light, #fff);
	--nu-hero-inner-button-bg: var(--color-2, #ef4400);
	--nu-hero-inner-button-bg-hover: var(--color-1, #1600ba);

	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	overflow: hidden;
	/* A page hero opens with more air above it than a normal section. */
	--nu-section-pt: calc(var(--space-4xl, 15.83rem) * 1.5);
	background-color: var(--color-3, #061745);
	background-image: var(--nu-hero-image);
	background-position: var(--nu-hero-image-position);
	background-repeat: no-repeat;
	background-size: cover;
	row-gap: var(--space-3xl, 11.19rem);
	color: var(--nu-hero-ink);
}

.nu-hero-inner::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	background-color: var(--nu-hero-overlay-color);
	opacity: var(--nu-hero-overlay-opacity);
}

.nu-hero-inner__inner {
	position: relative;
	/* Above the tint. */
	z-index: 2;
	width: 100%;
	max-width: var(--nu-hero-max-width);
	margin-inline: auto;
}

.nu-hero-inner__panel {
	display: flex;
	flex-direction: column;
	gap: 3rem;
	max-width: var(--nu-hero-panel-width);
	padding: var(--space-l, 3.96rem);
	border-radius: var(--radius-l, 2rem);
	color: var(--nu-hero-ink);
	-webkit-backdrop-filter: blur(var(--nu-hero-panel-blur));
	backdrop-filter: blur(var(--nu-hero-panel-blur));
}

.nu-hero-inner__heading {
	margin: 0;
	color: inherit;
}

.nu-hero-inner__text {
	margin: 0;
	color: inherit;
	font-size: var(--text-l, 2.2rem);
	font-weight: 300;
	line-height: 1.7;
}

/*
 * Optional CTA. Same pill as every other NÜ section — including the arrow's
 * `height: auto`, which is what makes it 45px rather than 44 (the shipped
 * Arrow-right.svg is 24×25).
 */
.nu-hero-inner__button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	width: fit-content;
	padding: var(--space-2xs, 0.99rem) var(--space-m, 2.8rem);
	border: 0;
	border-radius: var(--radius-full, 999rem);
	background-color: var(--nu-hero-inner-button-bg);
	color: var(--light, #fff);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-button, 1.6rem);
	font-weight: 500;
	line-height: 1.4;
	text-align: center;
	text-decoration: none;
	transition: background-color 0.3s;
}

.nu-hero-inner__button:hover,
.nu-hero-inner__button:focus-visible {
	background-color: var(--nu-hero-inner-button-bg-hover);
	color: var(--light, #fff);
}

.nu-hero-inner__button-icon {
	display: inline-flex;
	flex: none;
	transition: transform 0.3s;
}

.nu-hero-inner__button-icon svg {
	display: block;
	width: 24px;
	height: auto;
}

.nu-hero-inner__button-icon svg path {
	fill: currentColor;
}

.nu-hero-inner__button:hover .nu-hero-inner__button-icon,
.nu-hero-inner__button:focus-visible .nu-hero-inner__button-icon {
	transform: translateX(10px);
}

/*
 * The mobile header bar overlays the page (~130px tall, see --nu-mm-drawer-top)
 * and the fluid padding bottoms out below it, so the panel's copy slid under
 * the menu. Floor the hero's top padding at bar height + breathing room for the
 * whole burger-bar range.
 */
@media (max-width: 767px) {
	.nu-hero-inner {
		--nu-section-pt: max(calc(var(--space-4xl, 15.83rem) * 1.5), 17rem);
	}
}

@media (max-width: 478px) {
	.nu-hero-inner {
		min-height: 75vh;
	}

	.nu-hero-inner__panel {
		gap: var(--space-s, 1.98rem);
		padding: var(--space-m, 2.8rem);
	}
}

@media (prefers-reduced-motion: reduce) {
	.nu-hero-inner__button,
	.nu-hero-inner__button-icon {
		transition: none;
	}

	.nu-hero-inner__button:hover .nu-hero-inner__button-icon,
	.nu-hero-inner__button:focus-visible .nu-hero-inner__button-icon {
		transform: none;
	}
}

/*
 * Breadcrumb (pin 40). Rank Math markup, called by the element with a custom
 * wrapper (`.nu-breadcrumb`), styled as the site's mono uppercase eyebrow line
 * at the top of the copy panel. White on the navy hero; `.separator` is Rank
 * Math's chevron wrapper and `.last` the current page, which stays plain text.
 * The panel's own 3rem flex gap spaces it from the heading.
 */
.nu-hero-inner .nu-breadcrumb p {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	column-gap: 1.2rem;
	row-gap: 0.6rem;
	margin: 0;
	color: var(--nu-hero-ink);
	font-family: "Space Mono", ui-monospace, monospace;
	font-size: var(--text-xs, 1.4rem);
	font-weight: 700;
	line-height: 1.4;
	letter-spacing: 0.05em;
	text-transform: uppercase;
}

.nu-hero-inner .nu-breadcrumb a {
	color: inherit;
	opacity: 0.75;
	text-decoration: none;
	transition: opacity 0.2s;
}

.nu-hero-inner .nu-breadcrumb a:hover,
.nu-hero-inner .nu-breadcrumb a:focus-visible {
	opacity: 1;
	text-decoration: underline;
	text-underline-offset: 0.3em;
}

.nu-hero-inner .nu-breadcrumb .separator {
	opacity: 0.5;
}

@media (prefers-reduced-motion: reduce) {
	.nu-hero-inner .nu-breadcrumb a {
		transition: none;
	}
}

/* ============ nu-content-text.css ============ */
/**
 * NÜ — Section texte
 *
 * Ported from the "content-text-light" / "content-text-dark" exports. Both are
 * the same section; the dark one only adds the `bg-color-3` and `text-color-5`
 * utilities and a button, so the two collapse into one element with a theme
 * modifier.
 *
 * The 3fr/4fr grid carries no column gap on purpose: the heading column is
 * wider than the heading, so the whitespace between the two is the leftover
 * track, exactly as in the export.
 *
 * @see elements/nu-content-text.php
 */

.nu-content-text {
	--nu-ct-max-width: 1400px;
	--nu-ct-columns: minmax(0, 3fr) minmax(0, 4fr);
	--nu-ct-gap: 0px;
	--nu-ct-accent: var(--color-2, #ef4400);

	/* `section_scroll` in the export. */
	overflow: hidden;
}

.nu-content-text__inner {
	display: grid;
	grid-template-columns: var(--nu-ct-columns);
	align-items: start;
	gap: var(--nu-ct-gap);
	width: 100%;
	max-width: var(--nu-ct-max-width);
	margin-inline: auto;
}

.nu-content-text__aside {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
}

.nu-content-text__heading {
	margin: 0;
}

.nu-content-text__body {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
}

.nu-content-text__text > :first-child {
	margin-top: 0;
}

.nu-content-text__text > :last-child {
	margin-bottom: 0;
}

/* The export lifts <strong> into an accent-coloured lead-in rather than bold. */
.nu-content-text__text strong {
	color: var(--nu-ct-accent);
	font-size: 2.2rem;
}

.nu-content-text__text ul {
	margin-block-start: 0;
	padding-left: 1.55rem;
}

/* ------------------------------------------------------------------ dark ---- */

.nu-content-text--dark {
	--nu-ct-accent: var(--color-5, #e0dcff);
}

.nu-content-text--dark .nu-content-text__heading {
	color: var(--light, #fff);
}

.nu-content-text--dark .nu-content-text__text {
	color: var(--color-5, #e0dcff);
}

/* ---------------------------------------------------------------- button ---- */

.nu-content-text__button {
	display: inline-flex;
	align-items: center;
	gap: var(--space-3xs, 0.7rem);
	margin-top: var(--space-m, 2.8rem);
	padding: var(--space-2xs, 0.99rem) var(--space-m, 2.8rem);
	border-radius: var(--radius-full, 999rem);
	background-color: var(--color-2, #ef4400);
	color: var(--light, #fff);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-button, 1.6rem);
	font-weight: 500;
	line-height: 1.4;
	text-decoration: none;
	transition: background-color 0.25s ease;
}

/* Orange goes to brand blue on hover, as the home hero does. */
.nu-content-text__button:hover,
.nu-content-text__button:focus-visible {
	background-color: var(--color-1, #1600ba);
	color: var(--light, #fff);
}

.nu-content-text__button-icon {
	display: inline-flex;
	flex: none;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-content-text__button:hover .nu-content-text__button-icon,
.nu-content-text__button:focus-visible .nu-content-text__button-icon {
	transform: translateX(10px);
}

.nu-content-text__button-icon svg {
	display: block;
	width: 20px;
	height: 20px;
}

/* The shipped arrow carries a dark fill meant for light backgrounds. */
.nu-content-text__button-icon svg path {
	fill: currentColor;
}

/* ------------------------------------------------------------ responsive ---- */

@media (max-width: 767px) {
	.nu-content-text {
		--nu-ct-columns: minmax(0, 1fr);
		--nu-ct-gap: var(--space-m, 2.8rem);
	}
}


@media (prefers-reduced-motion: reduce) {
	.nu-content-text__button,
	.nu-content-text__button-icon {
		transition: none;
	}

	.nu-content-text__button:hover .nu-content-text__button-icon,
	.nu-content-text__button:focus-visible .nu-content-text__button-icon {
		transform: none;
	}
}

/* ============ nu-text-image.css ============ */
/**
 * NÜ — Section texte + image
 *
 * Ported from the "text-image-split" / "text-image-split-reverse" exports.
 * Content is always first in the markup so the reading order stays right; the
 * image is moved with grid `order`, which is also what lets the mobile stack
 * put the image on top in both directions — the export achieved that with a
 * per-breakpoint order override on the content wrapper.
 *
 * @see elements/nu-text-image.php
 */

.nu-text-image {
	--nu-ti-max-width: 1400px;
	--nu-ti-gap: var(--space-2xl, 7.92rem);
	--nu-ti-align: center;
	--nu-ti-accent: var(--color-2, #ef4400);
	--nu-ti-radius: var(--radius-s, 0.8rem);

	/* `section_scroll` in the export. */
	overflow: hidden;
}

.nu-text-image__inner {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	align-items: var(--nu-ti-align);
	gap: var(--nu-ti-gap);
	width: 100%;
	max-width: var(--nu-ti-max-width);
	margin-inline: auto;
}

.nu-text-image--image-left .nu-text-image__content {
	order: 2;
}

.nu-text-image--image-left .nu-text-image__media {
	order: 1;
}

/* --------------------------------------------------------------- content ---- */

.nu-text-image__content {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-m, 2.8rem);
}

.nu-text-image__heading {
	margin: 0;
}

.nu-text-image__text > :first-child {
	margin-top: 0;
}

.nu-text-image__text > :last-child {
	margin-bottom: 0;
}

/* The export lifts <strong> into an accent-coloured lead-in rather than bold. */
.nu-text-image__text strong {
	color: var(--nu-ti-accent);
	font-size: 2.2rem;
}

.nu-text-image__text ul {
	margin-block-start: 0;
	padding-left: 1.55rem;
}

/*
 * The global type rhythm zeroes the bottom margin of `p:last-of-type`, and a
 * paragraph that introduces a list is exactly that — so the two ran together
 * with no break at all. Hand the list the lead-in the paragraph can no longer
 * carry, sized like every other paragraph gap on the site.
 */
.nu-text-image__text p + :is(ul, ol) {
	margin-block-start: 1.2em;
}

/* ----------------------------------------------------------------- media ---- */

.nu-text-image__media {
	display: flex;
	overflow: hidden;
	border-radius: var(--nu-ti-radius);
}

.nu-text-image__image {
	min-width: 100%;
	height: auto;
	object-fit: cover;
}

/* ---------------------------------------------------------------- button ---- */

.nu-text-image__button {
	display: inline-flex;
	align-items: center;
	gap: var(--space-3xs, 0.7rem);
	margin-top: var(--space-2xs, 0.99rem);
	padding: var(--space-2xs, 0.99rem) var(--space-m, 2.8rem);
	border-radius: var(--radius-full, 999rem);
	background-color: var(--color-2, #ef4400);
	color: var(--light, #fff);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-button, 1.6rem);
	font-weight: 500;
	line-height: 1.4;
	text-decoration: none;
	transition: background-color 0.25s ease;
}

/* Orange goes to brand blue on hover, as the home hero does. */
.nu-text-image__button:hover,
.nu-text-image__button:focus-visible {
	background-color: var(--color-1, #1600ba);
	color: var(--light, #fff);
}

.nu-text-image__button-icon {
	display: inline-flex;
	flex: none;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-text-image__button:hover .nu-text-image__button-icon,
.nu-text-image__button:focus-visible .nu-text-image__button-icon {
	transform: translateX(10px);
}

.nu-text-image__button-icon svg {
	display: block;
	width: 20px;
	height: 20px;
}

/* The shipped arrow carries a dark fill meant for light backgrounds. */
.nu-text-image__button-icon svg path {
	fill: currentColor;
}

/* ------------------------------------------------------------ responsive ---- */

@media (max-width: 767px) {
	.nu-text-image {
		--nu-ti-gap: var(--space-l, 3.96rem);
	}

	.nu-text-image__inner {
		grid-template-columns: minmax(0, 1fr);
	}

	/* Stacked, the image leads whichever side it was on. */
	.nu-text-image__content {
		order: 2;
	}

	.nu-text-image__media {
		order: 1;
	}
}


/* ------------------------------------------------------- Dark surface ---- */

/* The orange accent holds up on navy; only the body ink has to move. */
.nu-section--dark.nu-text-image {
	color: var(--color-5, #e0dcff);
}

@media (prefers-reduced-motion: reduce) {
	.nu-text-image__button,
	.nu-text-image__button-icon {
		transition: none;
	}

	.nu-text-image__button:hover .nu-text-image__button-icon,
	.nu-text-image__button:focus-visible .nu-text-image__button-icon {
		transform: none;
	}
}

/* ============ nu-cards-colors.css ============ */
/**
 * NÜ — Cartes couleurs alternées
 *
 * Ported from the "cards-alternating-colors" export. The alternation is
 * :nth-child based, as in the export's `color-card` class, so adding or
 * removing a card re-flows the colours without any per-row setting.
 *
 * On phones the grid becomes a horizontal scroller with cards at 85% width, so
 * the next one peeks in and the row reads as swipeable.
 *
 * @see elements/nu-cards-colors.php
 */

.nu-cards-colors {
	--nu-cc-max-width: 1400px;
	--nu-cc-columns: 4;
	--nu-cc-gap: var(--space-s, 1.98rem);
	--nu-cc-heading-gap: 4.8rem;

	--nu-cc-odd-bg: var(--color-3, #061745);
	--nu-cc-odd-ink: var(--color-2, #ef4400);
	--nu-cc-even-bg: var(--color-4, #d7e3f5);
	--nu-cc-even-ink: var(--color-3, #061745);

	/* `section_scroll` in the export. */
	overflow: hidden;
}

.nu-cards-colors__inner {
	display: flex;
	flex-direction: column;
	gap: var(--nu-cc-heading-gap);
	width: 100%;
	max-width: var(--nu-cc-max-width);
	margin-inline: auto;
}

/*
 * Heading and its optional lead-in sit together, a paragraph apart rather than
 * the section's own heading gap apart — .nu-cards-colors__inner is a flex column
 * carrying that larger gap between the header and the card grid.
 */
.nu-cards-colors__header {
	display: flex;
	flex-direction: column;
	gap: var(--space-s, 1.98rem);
}

.nu-cards-colors__heading {
	margin: 0;
}

.nu-cards-colors__intro {
	max-width: 90ch;
	margin: 0;
	font-size: var(--text-m, 2rem);
	font-weight: 400;
	line-height: 1.5;
}

.nu-cards-colors__grid {
	display: grid;
	grid-template-columns: repeat(var(--nu-cc-columns), minmax(0, 1fr));
	gap: var(--nu-cc-gap);
	margin: 0;
	padding: 0;
	list-style: none;
}

/* ----------------------------------------------------------------- cards ---- */

.nu-cards-colors__card {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-m, 2.8rem);
	padding: var(--space-l, 3.96rem);
	border-radius: var(--radius-s, 0.8rem);
}

.nu-cards-colors__card:nth-child(odd) {
	background-color: var(--nu-cc-odd-bg);
	color: var(--nu-cc-odd-ink);
}

.nu-cards-colors__card:nth-child(even) {
	background-color: var(--nu-cc-even-bg);
	color: var(--nu-cc-even-ink);
}

/* The card sets the ink; everything inside follows it. */
.nu-cards-colors__number,
.nu-cards-colors__title,
.nu-cards-colors__text {
	margin: 0;
	color: inherit;
}

.nu-cards-colors__number {
	font-family: "Space Mono", ui-monospace, monospace;
	font-size: var(--text-3xl, 6rem);
	font-weight: 700;
	line-height: 1.1;
	text-transform: uppercase;
}

.nu-cards-colors__title {
	font-size: var(--text-xl, 3.2rem);
	line-height: 1.2;
}

.nu-cards-colors__text {
	font-size: var(--text-s, 1.6rem);
	line-height: 1.7;
}

/* ------------------------------------------------------------ responsive ---- */

@media (max-width: 991px) {
	.nu-cards-colors {
		--nu-cc-columns: 2;
		--nu-cc-heading-gap: var(--space-xl, 5.6rem);
	}
}

@media (max-width: 478px) {
	.nu-cards-colors {
		--nu-cc-heading-gap: 4rem;
		--nu-section-space-inline: 0px;
	}

	.nu-cards-colors__heading,
	.nu-cards-colors__intro {
		padding-inline: var(--space-l, 3.96rem);
	}

	/*
	 * A swipeable row rather than a tall stack: cards keep 85% of the viewport
	 * so the next one peeks in, and scroll snapping makes the gesture land.
	 */
	.nu-cards-colors__grid {
		grid-auto-columns: 85%;
		grid-auto-flow: column;
		grid-template-columns: none;
		overflow-x: auto;
		padding-inline: var(--space-l, 3.96rem);
		padding-bottom: var(--space-l, 3.96rem);
		/* Snap measures from the scrollport edge, not the content edge, so
		 * without this the mandatory snap pulls card 1 under the left gutter. */
		scroll-padding-inline: var(--space-l, 3.96rem);
		scroll-snap-type: x mandatory;
		scrollbar-color: var(--color-2, #ef4400) var(--light-30, rgba(255, 255, 255, 0.3));
		scrollbar-width: thin;
	}

	.nu-cards-colors__card {
		padding: var(--space-4xl, 15.83rem) var(--space-2xl, 7.92rem) var(--space-2xl, 7.92rem);
		scroll-snap-align: start;
	}

	.nu-cards-colors__number {
		font-size: 5rem;
	}

	.nu-cards-colors__grid::-webkit-scrollbar {
		height: 10px;
	}

	.nu-cards-colors__grid::-webkit-scrollbar-track {
		border-radius: var(--radius-full, 999rem);
		background: var(--light-30, rgba(255, 255, 255, 0.3));
	}

	.nu-cards-colors__grid::-webkit-scrollbar-thumb {
		border-radius: var(--radius-full, 999rem);
		background: var(--color-2, #ef4400);
	}
}

/* ------------------------------------------------------- Dark surface ---- */

/* The cards carry their own two-tone ink, so only the section heading moves. */
.nu-section--dark.nu-cards-colors {
	color: var(--color-5, #e0dcff);
}

.nu-section--dark.nu-cards-colors .nu-cards-colors__heading {
	color: var(--color-5, #e0dcff);
}

/* ============ nu-channels.css ============ */
/**
 * NÜ — Grille canaux média
 *
 * Ported from the "DAP Tactiques" export (1680×1049 canvas):
 *   112 / 120  section padding
 *    80        gap under the header
 *    32        grid gap
 *    40        card padding, 30 between the icon row and the title
 *              (tightened to 32 / 24 for pinpoint #48, with compact
 *              tablet and phone cards for #53 — the export's canvas is
 *              1680 wide, real viewports are not)
 *
 * The content is capped at 1400 rather than the export's 1440, to line up with
 * the other sections' containers.
 *
 * Cards stretch to fill their grid track, so every card in a row shares the
 * tallest one's height. The export lets them size to content, which leaves a
 * ragged bottom edge wherever a title wraps to two lines.
 *
 * The light/tinted alternation is a checkerboard, not a simple odd/even: with
 * four columns the pattern has to flip on every row, so it runs on an 8-card
 * cycle. Equivalent cycles are given for the 2- and 1-column breakpoints.
 *
 * Card titles are normalised to 20px. The export sets eight of the eleven to
 * 20px and three — Audio numérique, Retail média, Geofencing — to 22px, which
 * reads as a nudge rather than a rule.
 *
 * @see elements/nu-channels.php
 */

.nu-channels {
	--nu-ch-max-width: 1400px;
	--nu-ch-header-gap: 80px;
	--nu-ch-columns: 4;
	--nu-ch-gap: 32px;
	--nu-ch-radius: 8px;
	--nu-ch-icon-size: 50px;
	--nu-ch-arrow-size: 44px;

	--nu-ch-ink: var(--color-3, #061745);
	--nu-ch-accent: var(--text-title, #0f18c6);
	--nu-ch-card-light: var(--light, #fff);
	--nu-ch-card-tinted: var(--color-5, #e0dcff);
	/* The arrow disc reads as a hole in the card, so it takes the other fill. */
	--nu-ch-arrow-on-light: var(--bg-surface, rgba(224, 220, 255, 0.3));
	--nu-ch-arrow-on-tinted: var(--light, #fff);

	overflow: hidden;
	color: var(--nu-ch-ink);
}

.nu-channels__inner {
	display: flex;
	flex-direction: column;
	gap: var(--nu-ch-header-gap);
	width: 100%;
	max-width: var(--nu-ch-max-width);
	margin-inline: auto;
}

/* ---------------------------------------------------------------- header ---- */

.nu-channels__header {
	display: flex;
	flex-wrap: wrap;
	/* Baseline of the button sits on the baseline of the subheading. */
	align-items: flex-end;
	justify-content: space-between;
	gap: 24px;
}

.nu-channels__headings {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	gap: 16px;
	min-width: 0;
}

.nu-channels__heading {
	margin: 0;
	color: var(--nu-ch-accent);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: 46px;
	font-weight: 300;
	line-height: 1.2;
}

.nu-channels__subheading {
	margin: 0;
	color: var(--nu-ch-ink);
	font-family: "Space Mono", ui-monospace, monospace;
	font-size: 18px;
	font-weight: 700;
	line-height: 1.1;
	text-transform: uppercase;
}

.nu-channels__text {
	margin: 0;
	max-width: 920px;
	font-size: 20px;
	line-height: 1.5;
}

.nu-channels__button {
	display: inline-flex;
	flex: none;
	align-items: center;
	justify-content: center;
	gap: 12px;
	padding: 14px 24px;
	border: 1px solid currentColor;
	border-radius: 80px;
	color: var(--nu-ch-ink);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: 14px;
	font-weight: 500;
	line-height: 1.5;
	text-decoration: none;
	transition: background-color 0.25s ease, color 0.25s ease;
}

.nu-channels__button:hover,
.nu-channels__button:focus-visible {
	background-color: var(--nu-ch-ink);
	color: var(--light, #fff);
}

.nu-channels__button-icon {
	display: inline-flex;
	flex: none;
	transition: transform 0.3s;
}

.nu-channels__button-icon svg {
	display: block;
	width: 20px;
	height: 20px;
}

.nu-channels__button-icon svg path,
.nu-channels__button-icon svg circle,
.nu-channels__button-icon svg rect,
.nu-channels__button-icon svg polygon {
	fill: currentColor;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-channels__button:hover .nu-channels__button-icon,
.nu-channels__button:focus-visible .nu-channels__button-icon {
	transform: translateX(10px);
}

/* ------------------------------------------------------------------ grid ---- */

.nu-channels__grid {
	display: grid;
	grid-template-columns: repeat(var(--nu-ch-columns), minmax(0, 1fr));
	/* Cards fill their track, so a row is as tall as its tallest card. The
	   export lets them size to content instead, which left ragged bottoms. */
	align-items: stretch;
	gap: var(--nu-ch-gap);
	margin: 0;
	padding: 0;
	list-style: none;
}

.nu-channels__item {
	display: flex;
}

.nu-channels__card {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: 24px;
	padding: 32px;
	border-radius: var(--nu-ch-radius);
	background-color: var(--nu-ch-card-light);
	color: var(--nu-ch-ink);
	text-decoration: none;
	transition: background-color 0.25s ease, color 0.25s ease;
}

/*
 * Hover inverts the card: the ink fills it, and the icon, title and arrow disc
 * all drop to the tint. Scoped through .nu-channels__grid so it outranks both
 * the checkerboard cycle and the per-card overrides, which are otherwise the
 * heavier selectors — the disc needs one step more again, since its own rules
 * carry an extra class.
 */
.nu-channels__grid a.nu-channels__card:hover,
.nu-channels__grid a.nu-channels__card:focus-visible {
	background-color: var(--nu-ch-ink);
	color: var(--nu-ch-card-tinted);
}

.nu-channels__grid a.nu-channels__card:hover .nu-channels__card-arrow,
.nu-channels__grid a.nu-channels__card:focus-visible .nu-channels__card-arrow {
	background-color: var(--nu-ch-card-tinted);
}

/* -------- checkerboard --------
 * The card is the only child of its <li>, so the cycle has to run on the item.
 * 4 columns: the pattern repeats every 8 cards (two rows); tinted slots are
 * 2, 4, 5 and 7 of each cycle.
 */
.nu-channels__item:nth-child(8n + 2) .nu-channels__card,
.nu-channels__item:nth-child(8n + 4) .nu-channels__card,
.nu-channels__item:nth-child(8n + 5) .nu-channels__card,
.nu-channels__item:nth-child(8n + 7) .nu-channels__card {
	background-color: var(--nu-ch-card-tinted);
}

.nu-channels__item:nth-child(8n + 2) .nu-channels__card .nu-channels__card-arrow,
.nu-channels__item:nth-child(8n + 4) .nu-channels__card .nu-channels__card-arrow,
.nu-channels__item:nth-child(8n + 5) .nu-channels__card .nu-channels__card-arrow,
.nu-channels__item:nth-child(8n + 7) .nu-channels__card .nu-channels__card-arrow {
	background-color: var(--nu-ch-arrow-on-tinted);
}

/*
 * Per-card overrides. Deliberately one class heavier than any cycle rule: the
 * breakpoints below re-declare the checkerboard, and a matching specificity
 * would let those later rules win back a card the editor pinned by hand.
 */
.nu-channels__grid .nu-channels__card.nu-channels__card--light {
	background-color: var(--nu-ch-card-light);
}

.nu-channels__grid .nu-channels__card.nu-channels__card--light .nu-channels__card-arrow {
	background-color: var(--nu-ch-arrow-on-light);
}

.nu-channels__grid .nu-channels__card.nu-channels__card--tinted {
	background-color: var(--nu-ch-card-tinted);
}

.nu-channels__grid .nu-channels__card.nu-channels__card--tinted .nu-channels__card-arrow {
	background-color: var(--nu-ch-arrow-on-tinted);
}

/* ------------------------------------------------------------ card parts ---- */

.nu-channels__card-top {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	min-height: var(--nu-ch-icon-size);
}

.nu-channels__card-icon {
	display: inline-flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: var(--nu-ch-icon-size);
	height: var(--nu-ch-icon-size);
	/* Inherited, so the hover state carries down to it. */
	color: inherit;
}

.nu-channels__card-icon svg {
	display: block;
	width: 100%;
	height: 100%;
}

.nu-channels__card-arrow {
	transition: background-color 0.25s ease;
	display: inline-flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: var(--nu-ch-arrow-size);
	height: var(--nu-ch-arrow-size);
	border-radius: var(--radius-full, 999rem);
	background-color: var(--nu-ch-arrow-on-light);
	color: var(--nu-ch-ink);
}

.nu-channels__card-arrow svg {
	display: block;
	width: 24px;
	height: 24px;
}

/* The shipped arrow carries its own fill. */
.nu-channels__card-arrow svg path {
	fill: currentColor;
}

.nu-channels__card-title {
	font-family: "Space Mono", ui-monospace, monospace;
	font-size: 20px;
	font-weight: 700;
	line-height: 1.1;
	text-transform: uppercase;
}

/*
 * Optional description, only on cards that carry one. The card is a flex column
 * with a 24px gap meant to separate the icon row from the title, which is far
 * too much between a title and its own one-liner — so the pair is pulled back
 * together with a negative offset rather than by restructuring the markup that
 * every other page already renders.
 */
.nu-channels__card-text {
	margin-top: -12px;
	font-size: 16px;
	font-weight: 400;
	line-height: 1.5;
	text-transform: none;
}

/* ------------------------------------------------------------ responsive ---- */

@media (max-width: 1279px) {
	.nu-channels {
		--nu-ch-header-gap: 56px;

	}

	.nu-channels__heading {
		font-size: 38px;
	}
}

@media (max-width: 991px) {
	.nu-channels {
		--nu-ch-columns: 2;
	}

	.nu-channels__card {
		padding: 28px;
	}

	/* 2 columns: the cycle is 4 cards, tinted at 2 and 3. */
	.nu-channels__item:nth-child(8n + 2) .nu-channels__card,
	.nu-channels__item:nth-child(8n + 4) .nu-channels__card,
	.nu-channels__item:nth-child(8n + 5) .nu-channels__card,
	.nu-channels__item:nth-child(8n + 7) .nu-channels__card {
		background-color: var(--nu-ch-card-light);
	}

	.nu-channels__item:nth-child(8n + 2) .nu-channels__card .nu-channels__card-arrow,
	.nu-channels__item:nth-child(8n + 4) .nu-channels__card .nu-channels__card-arrow,
	.nu-channels__item:nth-child(8n + 5) .nu-channels__card .nu-channels__card-arrow,
	.nu-channels__item:nth-child(8n + 7) .nu-channels__card .nu-channels__card-arrow {
		background-color: var(--nu-ch-arrow-on-light);
	}

	.nu-channels__item:nth-child(4n + 2) .nu-channels__card,
	.nu-channels__item:nth-child(4n + 3) .nu-channels__card {
		background-color: var(--nu-ch-card-tinted);
	}

	.nu-channels__item:nth-child(4n + 2) .nu-channels__card .nu-channels__card-arrow,
	.nu-channels__item:nth-child(4n + 3) .nu-channels__card .nu-channels__card-arrow {
		background-color: var(--nu-ch-arrow-on-tinted);
	}

}

@media (max-width: 767px) {
	.nu-channels {
		--nu-ch-columns: 1;
		--nu-ch-header-gap: 40px;
		--nu-ch-gap: 16px;
		--nu-ch-icon-size: 40px;
		--nu-ch-arrow-size: 40px;
	}

	/* Compact phone card — pinpoint #53. */
	.nu-channels__card {
		gap: 12px;
		padding: 20px;
	}

	.nu-channels__card-title {
		font-size: 18px;
	}

	.nu-channels__card-text {
		margin-top: -4px;
	}

	.nu-channels__heading {
		font-size: 32px;
	}

	.nu-channels__header {
		align-items: flex-start;
	}

	/* 1 column: plain alternation. */
	.nu-channels__item:nth-child(4n + 2) .nu-channels__card,
	.nu-channels__item:nth-child(4n + 3) .nu-channels__card {
		background-color: var(--nu-ch-card-light);
	}

	.nu-channels__item:nth-child(4n + 2) .nu-channels__card .nu-channels__card-arrow,
	.nu-channels__item:nth-child(4n + 3) .nu-channels__card .nu-channels__card-arrow {
		background-color: var(--nu-ch-arrow-on-light);
	}

	.nu-channels__item:nth-child(even) .nu-channels__card {
		background-color: var(--nu-ch-card-tinted);
	}

	.nu-channels__item:nth-child(even) .nu-channels__card .nu-channels__card-arrow {
		background-color: var(--nu-ch-arrow-on-tinted);
	}

}

@media (prefers-reduced-motion: reduce) {
	.nu-channels__card {
		transition: none;
	}

	.nu-channels__button-icon {
		transition: none;
	}

	.nu-channels__button:hover .nu-channels__button-icon,
	.nu-channels__button:focus-visible .nu-channels__button-icon {
		transform: none;
	}
}

/* ------------------------------------------------------- Dark surface ---- */

.nu-section--dark.nu-channels {
	--nu-ch-accent: var(--color-5, #e0dcff);
	--nu-ch-ink: var(--color-5, #e0dcff);
}

/* ============ nu-stats.css ============ */
/**
 * NÜ — Bloc statistiques
 *
 * Ported from the "Nbrs" export (1680×464 canvas):
 *   0 / 120 / 120  section padding — no top padding, it butts against the
 *                  section above it
 *   40             card padding, and the gap above the footnote
 *   200            row height: a fixed 140px figure over the caption, so every
 *                  caption starts on the same line whatever the number's size
 *   10             gap between figures, plus 10px of inline padding each
 *
 * Type, measured off the export by glyph pitch (Space Mono advances at 0.6em):
 *   label   12px pitch → 20px
 *   number  43px pitch → 72px
 *
 * The content is capped at 1400 rather than the export's 1440, to line up with
 * the other sections' containers.
 *
 * @see elements/nu-stats.php
 */

.nu-stats {
	--nu-st-max-width: 140rem;
	--nu-st-columns: 4;
	--nu-st-gap: 40px;
	--nu-st-figure-height: 140px;
	--nu-st-value-size: 72px;

	--nu-st-card-bg: var(--color-5, #e0dcff);
	--nu-st-accent: var(--text-title, #0f18c6);
	--nu-st-ink: var(--color-3, #061745);

	/*
	 * No top-padding override. The export had none because the row was drawn
	 * sitting straight under the block above it inside the same surface — but
	 * stating that permanently also flattened it against a *dark* hero, which
	 * is a different surface and wants the full gap. The automatic join in
	 * nu-section.css makes that call per placement instead.
	 */
}

.nu-stats__inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--nu-st-gap);
	width: 100%;
	max-width: var(--nu-st-max-width);
	margin-inline: auto;
	padding: 40px;
	border-radius: 8px;
	background-color: var(--nu-st-card-bg);
}

.nu-stats__list {
	width: 100%;
	margin: 0;
	padding: 0;
	list-style: none;
}

/*
 * Tablet up: the flat grid. Under 768px the list is a Splide track instead
 * (mounted by nu-slider.js, torn down again by its destroy breakpoint) — the
 * doubled selector outweighs Splide's own `.splide__list { display: flex }`.
 */
@media (min-width: 768px) {
	.nu-stats .nu-stats__list {
		display: grid;
		grid-template-columns: repeat(var(--nu-st-columns), minmax(0, 1fr));
		align-items: start;
		gap: 10px;
	}
}

/* ------------------------------------------------------- phone carousel ---- */

/*
 * The stats ride the shared .nu-slider shell, but inside the tinted card the
 * post sliders' edge bleed (overflow: visible + negative margins in
 * nu-slider.css) would let slides paint outside the card — so the track is
 * clipped horizontally and the peek vars zeroed; the mobile block below
 * re-opens a right peek. Clipping is x-only (overflow: clip) because the GSAP
 * card reveal rises 40px and must paint below the track's layout box; the
 * plain `overflow: hidden` line is the fallback for pre-clip browsers.
 * width: 100% matters: .nu-stats__inner is a centred flex column, so without
 * it the shell would shrink to fit-content. Splide's core sheet hides an
 * unmounted .splide root; from 768px up the slider is deliberately destroyed,
 * so visibility is forced back on.
 */
.nu-stats .nu-slider {
	width: 100%;
	--nu-slider-peek-l: 0px;
	--nu-slider-peek-r: 0px;
}

.nu-stats .nu-slider .splide__track {
	overflow: hidden;
	overflow-x: clip;
	overflow-y: visible;
	margin-left: 0;
	margin-right: 0;
}

@media (min-width: 768px) {
	.nu-stats .nu-stats__slider {
		visibility: visible;
	}
}

.nu-stats__item {
	display: flex;
	flex-direction: column;
	padding-inline: 10px;
}

/*
 * Fixed height so a one-line and a two-line label leave their captions on the
 * same baseline; the stat itself is centred inside it.
 */
.nu-stats__figure {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: var(--nu-st-figure-height);
}

.nu-stats__stat {
	display: flex;
	flex-direction: column;
	gap: 0;
	margin: 0;
	color: var(--nu-st-accent);
	text-align: center;
}

.nu-stats__label {
	font-family: "Space Mono", ui-monospace, monospace;
	font-size: 20px;
	font-weight: 700;
	line-height: 1;
}

.nu-stats__value {
	font-family: "Space Mono", ui-monospace, monospace;
	font-size: var(--nu-st-value-size);
	font-weight: 700;
	line-height: 1;
}

.nu-stats__caption {
	margin: 0;
	color: var(--nu-st-ink);
	font-size: 20px;
	font-weight: 400;
	line-height: 1.5;
	text-align: center;
}

.nu-stats__footnote {
	margin: 0;
	/* The export's rgba(6, 23, 69, 0.6) over the card. */
	color: color-mix(in srgb, var(--nu-st-ink) 60%, transparent);
	font-size: 16px;
	font-weight: 400;
	line-height: 1.5;
	text-align: center;
}

@supports not (color: color-mix(in srgb, red 60%, transparent)) {
	.nu-stats__footnote {
		color: rgba(6, 23, 69, 0.6);
	}
}

/* ------------------------------------------------------------ responsive ---- */

@media (max-width: 1279px) {
	.nu-stats {
		--nu-st-value-size: 56px;
		--nu-st-figure-height: 120px;

	}
}

@media (max-width: 991px) {
	.nu-stats {
		--nu-st-columns: 2;
		--nu-st-gap: 32px;
	}

	.nu-stats .nu-stats__list {
		row-gap: 40px;
	}
}

@media (max-width: 767px) {
	.nu-stats {
		--nu-st-columns: 1;
		--nu-st-value-size: 48px;
		--nu-st-figure-height: 96px;

	}

	.nu-stats__inner {
		padding: var(--space-m, 2.8rem);
	}

	/* A sliver of the next figure signals the swipe. Must match the Splide
	   `padding` option in nu-stats.php. */
	.nu-stats .nu-slider {
		--nu-slider-peek-r: 48px;
	}

	.nu-stats__caption {
		font-size: 18px;
	}
}

/* ------------------------------------------------------- Dark surface ---- */

.nu-section--dark.nu-stats {
	--nu-st-accent: var(--color-5, #e0dcff);
	--nu-st-ink: var(--color-5, #e0dcff);
}

/* ============ nu-faq.css ============ */
/**
 * NÜ — FAQ
 *
 * Ported from the "FAQ-1.1" export (1680×1306 canvas):
 *   120        section padding
 *   100        gap between the heading column and the list
 *   513 / 827  the two column widths, kept as a ratio so they scale
 *   40 / 0     row padding, halved on top for the first row
 *   70         gap between a question and its plus
 *   40         the plus box; its cross is 20×20 with 4px bars
 *
 * A single-line row still measures 120px tall because the 40px plus sets the
 * floor — that is the export's behaviour and it is reproduced here with
 * min-height rather than a fixed height, so a long question can still grow.
 *
 * The content is capped at 1400 rather than the export's 1440, to line up with
 * the other sections' containers.
 *
 * @see elements/nu-faq.php
 */

.nu-faq {
	--nu-faq-max-width: 140rem;
	--nu-faq-gap: 100px;
	--nu-faq-row-padding: 40px;
	--nu-faq-icon-size: 40px;

	/*
	 * The Bricks header (template 176) is sticky "on scroll", so it can slide
	 * back over the top of the viewport at any point in the section. Its bar
	 * bottoms out at roughly the section's --space-m padding (2.8rem) plus the
	 * ~76px pill container, so the sticky intro is parked clear of that with a
	 * gutter of its own. Tune the gutter to move the intro down; the height is
	 * only there to be corrected if the header itself ever changes.
	 */
	--nu-faq-header-height: 104px;
	--nu-faq-sticky-gutter: var(--space-xl, 5.6rem);
	--nu-faq-sticky-top: calc(var(--nu-faq-header-height) + var(--nu-faq-sticky-gutter));

	--nu-faq-accent: var(--text-title, #0f18c6);
	--nu-faq-ink: var(--color-3, #061745);
	--nu-faq-rule: var(--color-5, #e0dcff);
	--nu-faq-marker: var(--color-2, #ee5101);

}

.nu-faq__inner {
	display: grid;
	/* The export's 513 / 827 split, as a ratio so it survives a narrower cap. */
	grid-template-columns: 513fr 827fr;
	align-items: start;
	gap: var(--nu-faq-gap);
	width: 100%;
	max-width: var(--nu-faq-max-width);
	margin-inline: auto;
}

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

/*
 * The intro is short and the list is long, so it rides along with the answers
 * instead of scrolling away. The grid area is the sticky containing block, so
 * it releases at the bottom of the list on its own — no height juggling. The
 * inner grid's `align-items: start` is what keeps the item from stretching to
 * the row height, which would make sticky a no-op.
 */
.nu-faq__intro {
	position: sticky;
	top: var(--nu-faq-sticky-top);
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 40px;
}

.nu-faq__heading {
	margin: 0;
	color: var(--nu-faq-accent);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: 46px;
	font-weight: 300;
	line-height: 1.2;
}

.nu-faq__button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	padding: 12px 24px;
	border-radius: var(--radius-full, 999rem);
	background-color: var(--nu-faq-marker);
	color: var(--light, #fff);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: 16px;
	font-weight: 500;
	line-height: 24px;
	text-decoration: none;
	transition: background-color 0.25s ease;
}

/* Orange goes to brand blue on hover, as the home hero does. */
.nu-faq__button:hover,
.nu-faq__button:focus-visible {
	background-color: var(--color-1, #1600ba);
	color: var(--light, #fff);
}

.nu-faq__button-icon {
	display: inline-flex;
	flex: none;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-faq__button:hover .nu-faq__button-icon,
.nu-faq__button:focus-visible .nu-faq__button-icon {
	transform: translateX(10px);
}

.nu-faq__button-icon svg {
	display: block;
	width: 24px;
	height: 24px;
}

/* The shipped arrow carries a dark fill meant for light backgrounds. */
.nu-faq__button-icon svg path {
	fill: currentColor;
}

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

.nu-faq__list {
	margin: 0;
	padding: 0;
	list-style: none;
	counter-reset: nu-faq;
}

.nu-faq__item {
	counter-increment: nu-faq;
	border-bottom: 1px solid var(--nu-faq-rule);
}

.nu-faq__details {
	/* Its own margins would break the row rhythm. */
	margin: 0;
}

.nu-faq__question {
	display: flex;
	align-items: center;
	gap: 70px;
	min-height: calc(var(--nu-faq-icon-size) + var(--nu-faq-row-padding) * 2);
	padding-block: var(--nu-faq-row-padding);
	color: var(--nu-faq-accent);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: 24px;
	font-weight: 300;
	line-height: 1.2;
	text-align: left;
}

/* The first row sits tighter to the top, as in the export. */
.nu-faq__item:first-child .nu-faq__question {
	padding-top: calc(var(--nu-faq-row-padding) / 2);
	min-height: calc(var(--nu-faq-icon-size) + var(--nu-faq-row-padding) * 1.5);
}

summary.nu-faq__question {
	cursor: pointer;
	list-style: none;
}

/* Safari still paints its own triangle without this. */
summary.nu-faq__question::-webkit-details-marker {
	display: none;
}

.nu-faq__question-text {
	flex: 1;
	min-width: 0;
}

/*
 * The number hangs in its own fixed column, so a wrapped question lines up
 * under the first word rather than under the digit.
 */
.nu-faq__list--numbered .nu-faq__question-text {
	display: flex;
	gap: 0;
}

.nu-faq__list--numbered .nu-faq__question-text::before {
	content: counter(nu-faq) ".";
	flex: none;
	width: 26px;
}

/* ------------------------------------------------------------------ plus ---- */

.nu-faq__icon {
	display: inline-flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: var(--nu-faq-icon-size);
	height: var(--nu-faq-icon-size);
	color: var(--nu-faq-marker);
}

.nu-faq__icon svg {
	display: block;
	width: 20px;
	height: 20px;
	fill: currentColor;
}

/* Open turns the plus into a dash: the vertical bar (the icon's first rect)
   folds away and only the horizontal one stays. */
.nu-faq__icon svg rect:first-child {
	transform-origin: center;
	transition: transform 0.25s ease, opacity 0.25s ease;
}

.nu-faq__details[open] .nu-faq__icon svg rect:first-child {
	transform: scaleY(0);
	opacity: 0;
}

/* --------------------------------------------------------------- answer ---- */

.nu-faq__answer {
	padding-bottom: var(--nu-faq-row-padding);
	/* Aligned under the question text, clear of the hanging number. */
	padding-left: 26px;
	color: var(--nu-faq-ink);
	font-size: 18px;
	font-weight: 400;
	line-height: 1.6;
}

.nu-faq__list:not(.nu-faq__list--numbered) .nu-faq__answer {
	padding-left: 0;
}

.nu-faq__answer > :first-child {
	margin-top: 0;
}

.nu-faq__answer > :last-child {
	margin-bottom: 0;
}

/* ------------------------------------------------------------ responsive ---- */

@media (max-width: 1279px) {
	.nu-faq {
		--nu-faq-gap: 56px;

	}

	.nu-faq__heading {
		font-size: 38px;
	}

	.nu-faq__question {
		gap: 32px;
		font-size: 21px;
	}
}

@media (max-width: 991px) {
	.nu-faq {
		--nu-faq-row-padding: 28px;
	}

	.nu-faq__inner {
		grid-template-columns: minmax(0, 1fr);
	}

	/* Stacked, the intro sits in its own row and has nothing to stick against. */
	.nu-faq__intro {
		position: static;
	}
}

@media (max-width: 767px) {
	.nu-faq {
		--nu-faq-gap: 40px;
		--nu-faq-icon-size: 32px;

	}

	.nu-faq__heading {
		font-size: 32px;
	}

	.nu-faq__question {
		gap: 20px;
		/* A step above the 18px answer — at the same size the light-weight
		   question read smaller than the text under it. */
		font-size: 20px;
	}

	.nu-faq__icon svg {
		width: 16px;
		height: 16px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.nu-faq__icon svg,
	.nu-faq__icon svg rect:first-child,
	.nu-faq__button,
	.nu-faq__button-icon {
		transition: none;
	}

	.nu-faq__button:hover .nu-faq__button-icon,
	.nu-faq__button:focus-visible .nu-faq__button-icon {
		transform: none;
	}
}

/* ------------------------------------------------------- Dark surface ---- */

/*
 * The accent is `--text-title` blue, which disappears into navy, so on the dark
 * surface both it and the body ink move to the pale lavender the rest of the
 * site uses for text on dark.
 */
.nu-section--dark.nu-faq {
	--nu-faq-accent: var(--color-5, #e0dcff);
	--nu-faq-ink: var(--color-5, #e0dcff);
}

/* ============ nu-quote.css ============ */
/**
 * NÜ — Section citation
 *
 * Rebuilt from the home page's "Section Scroll" (#brxe-imovay), measured from
 * the live render:
 *   --color-4 surface, --space-3xl / --space-xl section padding
 *   two equal columns with a --space-2xl gutter
 *   450px portrait, 8px radius, centred in its column
 *   quote at 26px/1.7 weight 300; attribution Space Mono 700 at --text-s
 *
 * The original leaned on four global classes and three blocks of per-element
 * custom CSS; all of it is folded in here so the element is self-contained.
 *
 * @see elements/nu-quote.php
 */

.nu-quote {
	--nu-qt-max-width: 140rem;
	--nu-qt-gap: var(--space-2xl, 7.92rem);
	--nu-qt-image-width: 450px;
	--nu-qt-ink: var(--color-3, #061745);
	--nu-qt-mark-size: 21px;
	--nu-qt-watermark-width: calc(100% + 50px);

	position: relative;
	overflow: hidden;
	color: var(--nu-qt-ink);
}

.nu-quote__inner {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	justify-items: center;
	gap: var(--nu-qt-gap);
	width: 100%;
	max-width: var(--nu-qt-max-width);
	margin-inline: auto;
}

.nu-quote--image-right .nu-quote__media {
	order: 2;
}

/* ---------------------------------------------------------------- media ---- */

.nu-quote__media {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
}

/*
 * The NÜ mark sits behind the portrait and bleeds a little past the column, as
 * in the original. It carries its own opacity so it never competes with the
 * photo.
 */
.nu-quote__watermark {
	position: absolute;
	top: 50%;
	left: 50%;
	z-index: 0;
	width: var(--nu-qt-watermark-width, calc(100% + 50px));
	transform: translate(-50%, -50%);
	pointer-events: none;
}

.nu-quote__watermark-image {
	display: block;
	width: 100%;
	height: auto;
}

.nu-quote__frame {
	position: relative;
	z-index: 1;
	overflow: hidden;
	width: 100%;
	max-width: var(--nu-qt-image-width);
	border-radius: var(--radius-s, 0.8rem);
}

.nu-quote__image {
	display: block;
	width: 100%;
	height: auto;
}

/* ----------------------------------------------------------------- body ---- */

.nu-quote__body {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	justify-content: center;
	gap: var(--space-m, 2.8rem);
	width: 100%;
}

/*
 * Bricks styles a bare <blockquote> with a serif face, a 4px left rule and a
 * 30px indent, so all of it has to be unwound here.
 */
.nu-quote__text {
	position: relative;
	margin: 0;
	padding: 0;
	border: 0;
	color: inherit;
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: 2.6rem;
	font-weight: 300;
	line-height: 1.7;
}

.nu-quote__paragraph {
	margin: 0;
}

/* The guillemets hang outside the text block, above it and below it. */
.nu-quote__mark {
	position: absolute;
	display: block;
	width: var(--nu-qt-mark-size);
	color: var(--nu-qt-ink);
}

.nu-quote__mark svg {
	display: block;
	width: 100%;
	height: auto;
}

.nu-quote__mark--open {
	top: -25px;
	left: 0;
}

.nu-quote__mark--close {
	right: 20%;
	bottom: -25px;
}

/* Room for the marks, which sit outside the box. */
.nu-quote__text--marked {
	margin-block: 25px;
}

.nu-quote__attribution {
	margin: 0;
	color: var(--nu-qt-ink);
	font-family: "Space Mono", ui-monospace, monospace;
	font-size: var(--text-s, 1.6rem);
	font-weight: 700;
	line-height: 1.7;
	text-transform: uppercase;
}

/* --------------------------------------------------------------- button ---- */

.nu-quote__button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	padding: 12px 24px;
	border: 1px solid currentColor;
	border-radius: var(--radius-full, 999rem);
	color: var(--nu-qt-ink);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: 16px;
	font-weight: 500;
	line-height: 1.4;
	text-decoration: none;
	transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}

.nu-quote__button:hover,
.nu-quote__button:focus-visible {
	border-color: var(--color-1, #1600ba);
	background-color: var(--color-1, #1600ba);
	color: var(--light, #fff);
}

.nu-quote__button-icon {
	display: inline-flex;
	flex: none;
	transition: transform 0.3s ease;
}

.nu-quote__button-icon svg {
	display: block;
	width: 24px;
	height: 24px;
}

/* The shipped arrow carries a dark fill meant for light backgrounds. */
.nu-quote__button-icon svg path {
	fill: currentColor;
}

/* The arrow slides out on hover, as the original's custom CSS did. */
.nu-quote__button:hover .nu-quote__button-icon,
.nu-quote__button:focus-visible .nu-quote__button-icon {
	transform: translateX(10px);
}

/* ------------------------------------------------------------ responsive ---- */

@media (max-width: 1279px) {
	.nu-quote {
		--nu-qt-gap: var(--space-xl, 5.6rem);

	}

	.nu-quote__text {
		font-size: 2.2rem;
	}
}

@media (max-width: 767px) {
	.nu-quote {
		--nu-qt-gap: var(--space-l, 3.96rem);

	}

	.nu-quote__inner {
		grid-template-columns: minmax(0, 1fr);
	}

	/* Stacked, the portrait leads whichever side it was on. */
	.nu-quote--image-right .nu-quote__media {
		order: 0;
	}

	.nu-quote__text {
		font-size: 2rem;
	}

	.nu-quote__mark--close {
		right: 0;
	}
}

@media (prefers-reduced-motion: reduce) {
	.nu-quote__button,
	.nu-quote__button-icon {
		transition: none;
	}

	.nu-quote__button:hover .nu-quote__button-icon,
	.nu-quote__button:focus-visible .nu-quote__button-icon {
		transform: none;
	}
}

/* ------------------------------------------------------- Dark surface ---- */

.nu-section--dark.nu-quote {
	--nu-qt-ink: var(--color-5, #e0dcff);
}

/* ============ nu-hero.css ============ */
/**
 * NÜ — Hero (accueil)
 *
 * Rebuilt from the home page's `#brxe-sntlnd`, measured from the live render at
 * 1512×982. Every value below came off that measurement rather than from the
 * design file, so the two match pixel for pixel at that width:
 *
 *   section  982 tall (100dvh), padding 111.9 / 56 (--space-3xl / --space-xl)
 *   inner    1400 wide at x=56, align flex-start, row-gap 28 (--space-m)
 *   panel    900 wide (--max-width-90 = 90rem), padding 39.6 (--space-l),
 *            radius 20 (--radius-l), row-gap 50, backdrop-filter blur(20px)
 *   heading  60/66 Spline Sans 300 (--text-3xl at 1.1 line-height)
 *   tagline  20/22 Space Mono 700 uppercase
 *   button   258×45, padding 9.9/28, radius --radius-full, bg --color-2
 *
 * One deliberate departure: the original container is `width:
 * var(--max-screen-width)` (1440). Every NÜ section caps its content at 1400,
 * and at 1512 the original measures 1400 anyway, so the cap is used here.
 *
 * @see elements/nu-hero.php
 */

.nu-hero {
	--nu-hero-min-height: 100dvh;
	--nu-hero-max-width: 140rem;
	--nu-hero-gap: var(--space-m, 2.8rem);

	--nu-hero-panel-max-width: 90rem;
	--nu-hero-panel-padding: var(--space-l, 3.96rem);
	--nu-hero-panel-radius: var(--radius-l, 2rem);
	--nu-hero-panel-gap: 5rem;
	--nu-hero-panel-blur: 20px;
	--nu-hero-text-gap: 2rem;

	--nu-hero-ink: var(--light, #fff);
	--nu-hero-surface: var(--color-3, #061745);
	--nu-hero-overlay-color: var(--color-3, #061745);
	--nu-hero-overlay-opacity: 0.3;

	/* #D93E00 rather than the brand --color-2 (#ef4400): the darkest step of
	   the same hue that puts white 16px text at WCAG AA (4.53:1 vs 3.82:1). */
	--nu-hero-button-bg: #d93e00;
	--nu-hero-button-bg-hover: var(--color-1, #1600ba);
	--nu-hero-buttons-gap: 1.6rem;

	/*
	 * The section owns the stacking context the media, the scrim and the panel
	 * are layered in, exactly as the original's `z-index: 1` did.
	 */
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: flex-end;
	overflow: hidden;
	min-height: var(--nu-hero-min-height);
	background-color: var(--nu-hero-surface);
	color: var(--nu-hero-ink);
}

/* ---------------------------------------------------------------- media ---- */

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

/*
 * Bricks sizes its background video with JavaScript on every resize; `cover`
 * gets to the same place with none of it.
 */
.nu-hero__video,
.nu-hero__image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
}

.nu-hero__scrim {
	position: absolute;
	z-index: 1;
	inset: 0;
	background-color: var(--nu-hero-overlay-color);
	opacity: var(--nu-hero-overlay-opacity);
	pointer-events: none;
}

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

.nu-hero__inner {
	position: relative;
	z-index: 2;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--nu-hero-gap);
	width: 100%;
	max-width: var(--nu-hero-max-width);
	margin-inline: auto;
}

.nu-hero__panel {
	display: flex;
	flex-direction: column;
	gap: var(--nu-hero-panel-gap);
	width: 100%;
	max-width: var(--nu-hero-panel-max-width);
	padding: var(--nu-hero-panel-padding);
	border-radius: var(--nu-hero-panel-radius);
	backdrop-filter: blur(var(--nu-hero-panel-blur));
	-webkit-backdrop-filter: blur(var(--nu-hero-panel-blur));
	color: var(--nu-hero-ink);
}

.nu-hero__text {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--nu-hero-text-gap);
}

/* ----------------------------------------------------------- typography ---- */

/*
 * Bricks styles bare h1–h6 (Spline Sans 300, 1.1em, --text-title), so both
 * headings restate everything they need — including `color`, which would
 * otherwise come out navy on navy.
 */
.nu-hero__heading {
	margin: 0;
	color: inherit;
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-3xl, 6rem);
	font-weight: 300;
	line-height: 1.1;
}

.nu-hero__tagline {
	margin: 0;
	color: inherit;
	font-family: "Space Mono", ui-monospace, monospace;
	font-size: 2rem;
	font-weight: 700;
	line-height: 1.1;
	text-transform: uppercase;
}

/* --------------------------------------------------------------- button ---- */

/*
 * Only rendered when a second CTA is set — a single-button hero keeps the bare
 * <a> the original shipped, so its panel layout is untouched.
 */
.nu-hero__buttons {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--nu-hero-buttons-gap);
}

.nu-hero__button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	width: fit-content;
	padding: var(--space-2xs, 0.99rem) var(--space-m, 2.8rem);
	border: 0;
	border-radius: var(--radius-full, 999rem);
	background-color: var(--nu-hero-button-bg);
	color: var(--light, #fff);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-button, 1.6rem);
	font-weight: 500;
	line-height: 1.4;
	text-align: center;
	text-decoration: none;
	transition: background-color 0.3s;
}

.nu-hero__button:hover,
.nu-hero__button:focus-visible {
	background-color: var(--nu-hero-button-bg-hover);
	color: var(--light, #fff);
}

.nu-hero__button-icon {
	display: inline-flex;
	flex: none;
	transition: transform 0.3s;
}

/*
 * Height stays automatic on purpose: the shipped arrow is 24×25, and it is the
 * taller-than-the-line-box glyph that gives the button its 45px height in the
 * original. Pinning it to a square loses a pixel.
 */
.nu-hero__button-icon svg {
	display: block;
	width: 24px;
	height: auto;
}

/* The shipped arrow carries a navy fill meant for light surfaces. */
.nu-hero__button-icon svg path {
	fill: currentColor;
}

.nu-hero__button:hover .nu-hero__button-icon,
.nu-hero__button:focus-visible .nu-hero__button-icon {
	transform: translateX(10px);
}

/*
 * Secondary CTA. The outline sits on the frosted panel, so it borrows the
 * panel's ink rather than a fixed colour; the 1px border is inset with a shadow
 * so the two pills stay exactly the same height.
 */
.nu-hero__button--outline {
	background-color: transparent;
	box-shadow: inset 0 0 0 1px currentColor;
	color: var(--nu-hero-ink);
	transition: background-color 0.3s, color 0.3s;
}

.nu-hero__button--outline:hover,
.nu-hero__button--outline:focus-visible {
	background-color: var(--nu-hero-ink);
	color: var(--nu-hero-surface);
}

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

/*
 * The live site runs this from a page-level GSAP snippet. Same timings here,
 * driven by two classes the element's script flips: the scrim starts opaque and
 * eases down over 3s after a 0.4s beat, then the panel fades up from y+30 over
 * 1.5s. `power2.out` is GSAP's easeOutCubic.
 *
 * Both blocks are gated on `.nu-hero--intro`, which only the script adds, so
 * with JavaScript off — and on the builder canvas — the settled state renders.
 */
.nu-hero--intro .nu-hero__scrim {
	opacity: 1;
	transition: none;
}

.nu-hero--intro .nu-hero__panel {
	visibility: hidden;
	opacity: 0;
	transform: translateY(30px);
	transition: none;
}

/*
 * Transitions stay off until `is-armed`, one frame later. The script adds
 * `nu-hero--intro` to markup that is already in its settled state, so leaving
 * them on would play the whole intro backwards first.
 */
.nu-hero--intro.is-armed .nu-hero__scrim {
	transition: opacity 3s cubic-bezier(0.215, 0.61, 0.355, 1);
}

.nu-hero--intro.is-armed .nu-hero__panel {
	transition: opacity 1.5s cubic-bezier(0.215, 0.61, 0.355, 1),
		transform 1.5s cubic-bezier(0.215, 0.61, 0.355, 1),
		visibility 0s linear 1.5s;
}

.nu-hero--intro.is-settled .nu-hero__scrim {
	opacity: var(--nu-hero-overlay-opacity);
}

.nu-hero--intro.is-revealed .nu-hero__panel {
	visibility: visible;
	opacity: 1;
	transform: none;
	transition-delay: 0s;
}

/* The Lottie sits over the hero and above the scrim, under nothing else. */
.nu-hero__lottie {
	position: absolute;
	z-index: 3;
	inset: 0;
	display: grid;
	place-items: center;
	opacity: 1;
	pointer-events: none;
	transition: opacity 0.6s cubic-bezier(0.215, 0.61, 0.355, 1);
}

.nu-hero__lottie[hidden] {
	display: grid;
	opacity: 0;
}

.nu-hero__lottie dotlottie-wc {
	width: min(70vmin, 90%);
	height: auto;
}

/* ------------------------------------------------------------ responsive ---- */

@media (max-width: 478px) {
	/*
	 * Bricks' theme styles give every `.brxe-section` a taller block padding on
	 * phones. A custom element is not one, so the rule is restated here — it is
	 * a 25px difference at 430, and without it the panel sits low.
	 */
	

	/* `tagline-white` loosens its line-height and pins left on phones. */
	.nu-hero__tagline {
		line-height: 1.2;
		text-align: left;
	}

	/*
	 * "Planifier une consultation gratuite" measures 250px at the button's 16px,
	 * and a 370px phone leaves the pill only ~220px for it, so the label broke
	 * onto a second line. Step it down to the next type token and pull the pill
	 * in — inline padding, gap and arrow — which buys back the ~30px it was
	 * short. That holds one line from roughly 355px up; narrower than that the
	 * label is simply longer than the screen and still wraps.
	 */
	.nu-hero__button {
		gap: 8px;
		padding-inline: var(--space-s, 1.98rem);
		font-size: var(--text-s, 1.4rem);
	}

	.nu-hero__button-icon svg {
		width: 20px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.nu-hero--intro .nu-hero__scrim,
	.nu-hero--intro .nu-hero__panel,
	.nu-hero__lottie,
	.nu-hero__button,
	.nu-hero__button-icon {
		transition: none;
	}

	.nu-hero__button:hover .nu-hero__button-icon,
	.nu-hero__button:focus-visible .nu-hero__button-icon {
		transform: none;
	}
}

/* ============ nu-devices.css ============ */
/**
 * NÜ — Grille appareils
 *
 * Rebuilt from the live "#appareils" section of /campagnes-programmatiques/.
 * Every value below was measured off that section rather than guessed, so the
 * element stands on its own: the source markup leans on Bricks theme styles
 * (`.brxe-section` padding, `.brxe-container` width + row-gap, bare `h2`/`h3`
 * rules) and on four global classes — section_scroll, grid-3, gap-m and
 * grid-item-largestroke — none of which a custom element inherits.
 *
 * Resolved at a 1512 viewport:
 *     0 / 56 / 111.9   section padding (the 0 top is not kept — see below)
 *     1400             content width
 *     28               gap under the heading, and both grid gaps
 *     42 / 46.2        heading, Spline Sans 300 (h2 is 2.1em of --text-m)
 *     39.6 / 19.8      card padding, 10px border in --color-1-5
 *     50               icon, flush left inside the card
 *     18 / 19.8        card title, Space Mono 700 uppercase
 *     14 / 21          card text
 *
 * Four deliberate departures from the live section, all matching what the rest
 * of the NÜ library already does:
 *
 *  - The block padding is symmetric. The live section has no top padding
 *    (0 / 56 / 111.9) because on /campagnes-programmatiques/ it follows another
 *    section inside the same surface; standing alone it needs both halves, so
 *    the top gets the same var(--space-3xl) as the bottom. Same call as
 *    nu-logo-marquee.
 *  - Content caps at 1400, not the container's 1440. Below a 1552px viewport
 *    the two are identical (the section's 56px inline padding is what bites);
 *    above it, 1440 would leave this section 40px wider than its neighbours.
 *  - The card's last paragraph keeps no bottom margin. The site has a global
 *    `:where(p:last-of-type){margin-block-end: revert}` rule, which reverts to
 *    the UA's 1em and leaves ~14px of dead space at the bottom of every card.
 *  - Cards stay stretched inside the phone scroller. The source card carries
 *    `height: 100%`, which resolves in the desktop grid but not in the phone
 *    flex row — so the live strip has ragged card bottoms. Same call as
 *    nu-channels.
 *
 * Padding top and Padding bottom are exposed as their own controls on top of
 * the all-sides one, so a section that does sit under another can drop its top
 * half back to 0 without respecifying the other three values.
 *
 * @see elements/nu-devices.php
 */

.nu-devices {
	--nu-dev-max-width: 1400px;
	--nu-dev-header-gap: var(--space-m, 2.8rem);
	--nu-dev-columns: 3;
	--nu-dev-gap: var(--space-m, 2.8rem);
	--nu-dev-card-gap: var(--space-m, 2.8rem);
	--nu-dev-border-width: 10px;
	--nu-dev-border-color: var(--color-1-5, rgba(22, 0, 186, 0.05));
	--nu-dev-card-bg: transparent;
	--nu-dev-icon-size: 50px;
	--nu-dev-icon-color: var(--dark, #061745);
	--nu-dev-ink: var(--color-3, #061745);

	display: block;
	overflow: hidden;
	color: var(--nu-dev-ink);
	/* The heading is sized in em, so the root's font-size is load-bearing:
	   Bricks' own h2 rule is `font-size: 2.1em` against the body's --text-m. */
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-m, 2rem);
	line-height: 1.7;
}

.nu-devices__inner {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	row-gap: var(--nu-dev-header-gap);
	width: 100%;
	max-width: var(--nu-dev-max-width);
	margin-inline: auto;
}

.nu-devices__heading {
	margin: 0;
	color: var(--color-1, #1600ba);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: 2.1em;
	font-weight: 300;
	line-height: 1.1em;
}

/* ------------------------------------------------------------------ grid ---- */

.nu-devices__grid {
	display: grid;
	grid-template-columns: repeat(var(--nu-dev-columns), minmax(0, 1fr));
	/* Cards fill their track, so every card in a row is as tall as the tallest. */
	align-items: stretch;
	gap: var(--nu-dev-gap);
	width: 100%;
	margin: 0;
	padding: 0;
	list-style: none;
}

/*
 * The card is the grid item itself, as in the source markup. Its parts are
 * left-aligned by the flex cross-axis (icon and title hug their content), which
 * is why `text-align: center` here only shows on a title that wraps.
 */
.nu-devices__card {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	row-gap: var(--nu-dev-card-gap);
	padding: var(--space-l, 3.96rem) var(--space-s, 1.98rem);
	border: var(--nu-dev-border-width) solid var(--nu-dev-border-color);
	background-color: var(--nu-dev-card-bg);
	color: var(--nu-dev-ink);
	font-size: var(--text-s, 1.6rem);
	line-height: 1.7;
	text-align: center;
}

.nu-devices__icon {
	display: inline-flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: var(--nu-dev-icon-size);
	height: var(--nu-dev-icon-size);
	color: var(--nu-dev-icon-color);
}

.nu-devices__icon svg {
	display: block;
	width: 100%;
	height: 100%;
}

/* The shipped device SVGs carry a baked-in fill, as the site's icons__dark
   class also has to work around. */
.nu-devices__icon svg path {
	fill: var(--nu-dev-icon-color);
}

.nu-devices__card-title {
	margin: 0;
	/* Straight from the source class: nudges the tracked caps off the edge. */
	padding-left: 1px;
	color: var(--nu-dev-ink);
	font-family: "Space Mono", ui-monospace, monospace;
	font-size: 1.8rem;
	font-weight: 700;
	line-height: 1.1em;
	/* Left like the icon and body — centred only showed on a wrapped title, so
	   one-line and two-line cards disagreed (client note, 2026-08-12). */
	text-align: left;
	text-transform: uppercase;
}

.nu-devices__card-text {
	margin: 0;
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-xs, 1.4rem);
	font-weight: 400;
	line-height: 1.5;
	text-align: left;
}

/* ------------------------------------------------------------ responsive ---- */

/*
 * Phone: the grid becomes a horizontal scroller of 85%-wide cards, and the
 * section gives up its inline padding so the strip can bleed to both edges —
 * the heading takes that padding back on its own. Bricks' phone-only section
 * padding (`calc(var(--space-4xl) * 1.2)`) applies to `.brxe-section` only, so
 * it is restated here, on both halves like every other NÜ section.
 */
@media (max-width: 478px) {
	.nu-devices {
		--nu-section-space-inline: 0px;
	}

	.nu-devices__heading {
		padding-inline: var(--space-xl, 5.6rem);
	}

	.nu-devices__grid {
		display: flex;
		flex-direction: row;
		flex-wrap: nowrap;
		justify-content: flex-start;
		overflow-x: auto;
		padding: var(--space-l, 3.96rem) var(--space-xl, 5.6rem) var(--space-2xl, 7.92rem);
	}

	.nu-devices__card {
		min-width: 85%;
	}
}

/* ------------------------------------------------------- Dark surface ---- */

.nu-section--dark.nu-devices {
	--nu-dev-ink: var(--color-5, #e0dcff);
	--nu-dev-icon-color: var(--color-5, #e0dcff);
	--nu-dev-border-color: var(--color-5-5, rgba(224, 220, 255, 0.05));
}

.nu-section--dark.nu-devices .nu-devices__heading {
	color: var(--color-5, #e0dcff);
}

/* ============ nu-anchor-nav.css ============ */
/**
 * NÜ — Navigation ancres
 *
 * Ported from `pill_list-horizontal-wrapper` / `intro_services-item` on the
 * "Campagnes programmatiques" page. There the strip is a block inside the intro
 * section, so it inherited that section's surface, padding and 1400px container.
 * As a section of its own it has to state all four itself — Bricks' theme styles
 * for `.brxe-section` / `.brxe-container` do not reach a custom element.
 *
 * Two deliberate differences from the export:
 *
 * 1. It has no vertical section padding. The strip is meant to sit tight under
 *    an intro, and the space between the two belongs to whichever section comes
 *    first — putting it here as well would double it.
 * 2. The export goes to `font-weight: 700` on pill hover. Dropped: the pill is a
 *    fixed-width flex item in a row that scrolls rather than wraps, so the wider
 *    bold text reflows every pill after it, under the cursor.
 *
 * @see elements/nu-anchor-nav.php
 */

.nu-anchor-nav {
	--nu-anchor-nav-max-width: 1400px;
	/* Pills cluster in the middle of the rule — spread across the full 1400px
	   they read as unrelated islands (client note, 2026-08-12). The centring
	   itself comes from the auto margins on the end pills below, NOT from
	   `center` here: a centred flex row that overflows spills past both edges
	   and the start side cannot be scrolled back to, so on mobile the strip
	   loaded mid-way with the first pills unreachable (pin 57, 2026-08-31). */
	--nu-anchor-nav-justify: flex-start;
	--nu-anchor-nav-gap: var(--space-xs, 1.4rem);
	--nu-anchor-nav-padding-block: var(--space-m, 2.8rem);

	/* Re-pointed per theme below, never restyled part by part — a colour
	   control on any single part still wins over the theme it sits in. The
	   surface itself comes from nu-section.css. */
	--nu-anchor-nav-ink: var(--color-3, #061745);
	--nu-anchor-nav-rule: var(--color-5, #e0dcff);
	--nu-anchor-nav-item-ink: inherit;
	--nu-anchor-nav-item-accent: var(--color-2, #ee5101);
	--nu-anchor-nav-item-border: var(--color-3, #061745);
	--nu-anchor-nav-item-hover-bg: var(--color-5-30, rgba(224, 220, 255, 0.3));

	/*
	 * The strip is built to sit tight under the section above it, so it keeps
	 * no vertical padding of its own — its breathing room is the rules' own
	 * padding-block. That is also why the automatic join has nothing to do
	 * here: there is no top padding to drop.
	 */
	--nu-section-pt: 0px;
	--nu-section-pb: 0px;

	color: var(--nu-anchor-nav-ink);
}

/*
 * One row that scrolls sideways rather than wrapping — the export states
 * `flex-wrap: nowrap` at every breakpoint, and a half-empty second line reads
 * as a mistake rather than a layout. `justify-content` only has an effect while
 * the pills still fit; past that the row simply overflows and scrolls.
 */
.nu-anchor-nav__strip {
	display: flex;
	flex-wrap: nowrap;
	align-items: center;
	justify-content: var(--nu-anchor-nav-justify);
	gap: var(--nu-anchor-nav-gap);
	width: 100%;
	max-width: var(--nu-anchor-nav-max-width);
	margin-inline: auto;
	padding-block: var(--nu-anchor-nav-padding-block);
	border-top: 1px solid var(--nu-anchor-nav-rule);
	border-bottom: 1px solid var(--nu-anchor-nav-rule);
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scrollbar-width: thin;
}

/*
 * Centred while the pills fit, flush with the first pill once they overflow.
 * Auto margins on the two end pills split any free space — visually the same
 * as `justify-content: center` — and collapse to zero when there is none, so
 * the scrollable strip starts on the first pill instead of the middle.
 */
.nu-anchor-nav__item:first-child {
	margin-inline-start: auto;
}

.nu-anchor-nav__item:last-child {
	margin-inline-end: auto;
}

.nu-anchor-nav__item {
	flex: none;
	border: 1px solid var(--nu-anchor-nav-item-border);
	border-radius: var(--radius-full, 999rem);
	padding: var(--space-xs, 1.4rem) var(--space-m, 2.8rem);
	color: var(--nu-anchor-nav-item-ink);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-xs, 1.4rem);
	font-weight: 500;
	line-height: 1.2;
	text-decoration: none;
	white-space: nowrap;
	transition: background-color 0.2s ease, outline-color 0.2s ease;
}

/*
 * The ring is an inset outline rather than a wider border so it cannot resize
 * the pill, and inset so the scroll container cannot clip it off the first and
 * last one.
 */
.nu-anchor-nav__item:hover {
	outline: 2px solid var(--nu-anchor-nav-item-border);
	outline-offset: -1px;
	background-color: var(--nu-anchor-nav-item-hover-bg);
}

.nu-anchor-nav__item:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: -1px;
	background-color: var(--nu-anchor-nav-item-hover-bg);
}

/* `.intro_services-item:last-child` in the export, where the last pill is the
   product name. Here it is a per-pill setting, so it can sit anywhere. */
.nu-anchor-nav__item--accent {
	color: var(--nu-anchor-nav-item-accent);
}

/* ---------------------------------------------------------------- themes ---- */

/*
 * Only the ink — the surfaces are `.nu-section--{key}` in nu-section.css.
 *
 * The pill border is --color-3 on light surfaces, i.e. the dark surface itself
 * — it would vanish here. The rule keeps its faint tint.
 */
.nu-anchor-nav--dark {
	--nu-anchor-nav-ink: var(--light, #fff);
	--nu-anchor-nav-rule: var(--color-5-30, rgba(224, 220, 255, 0.3));
	--nu-anchor-nav-item-border: var(--color-5, #e0dcff);
}

/* ============ nu-technologies.css ============ */
/**
 * NÜ — Section technologies
 *
 * Rebuilt from the live "#technologies" section of /campagnes-programmatiques/.
 * The source leans on Bricks theme styles (`.brxe-section` padding, the bare
 * `h2`/`h3` rules, `.brxe-container` width and row-gap) and on five global
 * classes — section_scroll, bg-color-3, tagline, grid-3/gap-m and
 * grid-item-largestroke — none of which a custom element inherits, so all of it
 * is restated here.
 *
 * Resolved at a 1512 viewport, dark surface:
 *     111.9 / 56       section padding
 *     1400             content width
 *     56               gap under the header, 28 between eyebrow and heading
 *     18 / 19.8        eyebrow, Space Mono 700 uppercase, --light
 *     42 / 46.2        heading, Spline Sans 300, --light
 *     28               grid gap, and the gap between card parts
 *     39.6 / 19.8      card padding, 10px border in --color-5-5
 *     50               icon height (width follows the artwork), --color-5
 *     22 / 24.2        card title, left-aligned, --color-5  (20px on phones)
 *     14 / 21          card text, --color-5
 *
 * The card shell is the same `grid-item-largestroke` as nu-devices; what the
 * page adds on top of it here is per-instance custom CSS — left-aligned cards
 * and 2.2rem titles instead of the class's centred 1.8rem.
 *
 * Same three departures as nu-devices, for the same reasons: content caps at
 * 1400 rather than the container's 1440; the card's last paragraph keeps no
 * bottom margin (the site's global `:where(p:last-of-type){margin-block-end:
 * revert}` otherwise leaves ~14px of dead space); and the cards stay stretched
 * inside the phone scroller, where the source's `height: 100%` stops resolving.
 *
 * @see elements/nu-technologies.php
 */

.nu-technologies {
	--nu-tec-max-width: 1400px;
	--nu-tec-header-gap: var(--space-xl, 5.6rem);
	--nu-tec-heading-gap: var(--space-m, 2.8rem);
	--nu-tec-columns: 3;
	--nu-tec-gap: var(--space-m, 2.8rem);
	--nu-tec-card-gap: var(--space-m, 2.8rem);
	--nu-tec-border-width: 10px;
	--nu-tec-card-bg: transparent;
	--nu-tec-icon-size: 50px;

	/* Light surfaces. The dark modifier below re-points these five, which is
	   all a surface swap is — a per-part colour control still outranks it. */
	--nu-tec-heading: var(--color-1, #1600ba);
	--nu-tec-ink: var(--color-3, #061745);
	--nu-tec-title: var(--color-3, #061745);
	--nu-tec-icon: var(--dark, #061745);
	--nu-tec-border: var(--color-1-5, rgba(22, 0, 186, 0.05));

	display: block;
	overflow: hidden;
	color: var(--nu-tec-ink);
	/* Load-bearing: Bricks sizes bare headings in em against the parent, so the
	   heading's 2.1em only lands on 42px if the root sits at --text-m. */
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-m, 2rem);
	line-height: 1.7;
}


.nu-technologies--dark {
	--nu-tec-heading: var(--light, #fff);
	--nu-tec-ink: var(--color-5, #e0dcff);
	--nu-tec-title: var(--color-5, #e0dcff);
	--nu-tec-icon: var(--color-5, #e0dcff);
	--nu-tec-border: var(--color-5-5, rgba(224, 220, 255, 0.05));
}

.nu-technologies__inner {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	row-gap: var(--nu-tec-header-gap);
	width: 100%;
	max-width: var(--nu-tec-max-width);
	margin-inline: auto;
}

/* ---------------------------------------------------------------- header ---- */

.nu-technologies__header {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	row-gap: var(--nu-tec-heading-gap);
	width: 100%;
}

.nu-technologies__eyebrow {
	margin: 0;
	color: var(--nu-tec-heading);
	font-family: "Space Mono", ui-monospace, monospace;
	font-size: var(--text-tagline, 1.8rem);
	font-weight: 700;
	line-height: 1.1em;
	text-transform: uppercase;
}

.nu-technologies__heading {
	margin: 0;
	color: var(--nu-tec-heading);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: 2.1em;
	font-weight: 300;
	line-height: 1.1em;
}

/* ------------------------------------------------------------------ grid ---- */

.nu-technologies__grid {
	display: grid;
	grid-template-columns: repeat(var(--nu-tec-columns), minmax(0, 1fr));
	/* Cards fill their track, so every card in a row is as tall as the tallest. */
	align-items: stretch;
	gap: var(--nu-tec-gap);
	width: 100%;
	margin: 0;
	padding: 0;
	list-style: none;
}

.nu-technologies__card {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	row-gap: var(--nu-tec-card-gap);
	padding: var(--space-l, 3.96rem) var(--space-s, 1.98rem);
	border: var(--nu-tec-border-width) solid var(--nu-tec-border);
	background-color: var(--nu-tec-card-bg);
	color: var(--nu-tec-ink);
	font-size: var(--text-s, 1.6rem);
	line-height: 1.7;
	text-align: left;
}

/*
 * Height only: these six icons range from square to 50×52, and the source sizes
 * them with min-height/max-height + `width: fit-content` so each keeps its own
 * proportions. Forcing a square box would squash the tall ones.
 */
.nu-technologies__icon {
	display: block;
	flex: none;
	max-height: var(--nu-tec-icon-size);
	color: var(--nu-tec-icon);
}

.nu-technologies__icon svg {
	display: block;
	width: auto;
	height: var(--nu-tec-icon-size);
	max-height: var(--nu-tec-icon-size);
}

/* The shipped SVGs carry a baked-in fill, which the site's bg-color-3 rules
   also have to override. */
.nu-technologies__icon svg path {
	fill: var(--nu-tec-icon);
}

.nu-technologies__card-title {
	margin: 0;
	/* Straight from the source class: nudges the tracked caps off the edge. */
	padding-left: 1px;
	color: var(--nu-tec-title);
	font-family: "Space Mono", ui-monospace, monospace;
	font-size: 2.2rem;
	font-weight: 700;
	line-height: 1.1em;
	text-align: left;
	text-transform: uppercase;
}

.nu-technologies__card-text {
	margin: 0;
	color: var(--nu-tec-ink);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-xs, 1.4rem);
	font-weight: 400;
	line-height: 1.5;
	text-align: left;
}

/* ------------------------------------------------------------ responsive ---- */

/*
 * Phone: the grid becomes a horizontal scroller of 85%-wide cards, and the
 * section gives up its inline padding so the strip can bleed to both edges —
 * the header takes that padding back on its own. Bricks' phone-only section
 * padding (`calc(var(--space-4xl) * 1.2)`) applies to `.brxe-section` only, so
 * it is restated here.
 */
@media (max-width: 478px) {
	.nu-technologies {
		--nu-section-space-inline: 0px;
	}

	.nu-technologies__header {
		padding-inline: var(--space-xl, 5.6rem);
	}

	.nu-technologies__eyebrow {
		line-height: 1.2em;
	}

	.nu-technologies__grid {
		display: flex;
		flex-direction: row;
		flex-wrap: nowrap;
		justify-content: flex-start;
		overflow-x: auto;
		padding: var(--space-l, 3.96rem) var(--space-xl, 5.6rem) var(--space-2xl, 7.92rem);
	}

	.nu-technologies__card {
		min-width: 85%;
	}

	.nu-technologies__card-title {
		font-size: 2rem;
	}
}

/* ============ nu-tech-partners.css ============ */
/**
 * NÜ — Bandeau technologies partenaires
 *
 * Rebuilt from `#brxe-zhtmus`, the block that closes the live "#technologies"
 * section of /campagnes-programmatiques/. It leans on Bricks theme styles (the
 * bare `h3` rule, `.brxe-block` row-gap and width) plus the bg-color-3,
 * self-center, text-center, logo-box and logo-box__logo global classes, so all
 * of that is restated here.
 *
 * Resolved at a 1512 viewport, dark surface:
 *     1400             content width
 *     28               gap between heading, text and the logo box
 *     36 / 39.6        heading, Spline Sans 300, centred, --light
 *     20 / 34          text, centred, --color-5
 *     39.6             logo-box padding and the gap between logos
 *     8                logo-box radius (--radius-s), on white (--bg-body)
 *     135 × 55         logo slot, object-fit: contain
 *
 * Two changes that come from promoting the block to a section of its own:
 *
 *  - It gets the usual section rhythm, but on the top edge only —
 *    `var(--space-3xl) var(--space-xl) 0`. The band is meant to close a run of
 *    sections rather than stand between two, so its own bottom padding would
 *    only stack on top of whatever comes next.
 *  - It keeps its inline padding on phones. The source section drops its own so
 *    the card scroller can bleed edge to edge, which left this block's heading
 *    touching both screen edges; there is no scroller here, and the logo box
 *    lands on exactly the same 29.34px inset either way.
 *
 * @see elements/nu-tech-partners.php
 */

.nu-tech-partners {
	--nu-tep-max-width: 1400px;
	--nu-tep-gap: var(--space-m, 2.8rem);
	--nu-tep-logo-gap: var(--space-l, 3.96rem);
	--nu-tep-logo-width: 135px;
	--nu-tep-logo-height: 55px;
	/* The marks are drawn for a light background, so the box stays white on
	   every surface. */
	--nu-tep-box-bg: var(--bg-body, #fff);

	/* Light surfaces; the dark modifier re-points these three. */
	--nu-tep-heading: var(--color-3, #061745);
	--nu-tep-ink: var(--color-3, #061745);

	display: block;
	overflow: hidden;
	/*
	 * No bottom-padding override here. The export had none (3xl / xl / 0)
	 * because the band sat directly above another block inside the same tinted
	 * surface — the same reason the logo marquee shipped without a *top* one.
	 * As a standalone section it takes the symmetric rhythm, and the automatic
	 * join in nu-section.css reproduces the export whenever the section under it
	 * is on the same surface, without leaving it cramped when it is not.
	 */
	color: var(--nu-tep-ink);
	/* Load-bearing: Bricks sizes bare headings in em against the parent, so the
	   heading's 1.8em only lands on 36px if the root sits at --text-m. */
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-m, 2rem);
	line-height: 1.7;
}


.nu-tech-partners--dark {
	--nu-tep-heading: var(--light, #fff);
	--nu-tep-ink: var(--color-5, #e0dcff);
}

.nu-tech-partners__inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	row-gap: var(--nu-tep-gap);
	width: 100%;
	max-width: var(--nu-tep-max-width);
	margin-inline: auto;
}

.nu-tech-partners__heading {
	margin: 0;
	color: var(--nu-tep-heading);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: 1.8em;
	font-weight: 300;
	line-height: 1.1em;
	text-align: center;
}

.nu-tech-partners__text {
	margin: 0;
	color: var(--nu-tep-ink);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-m, 2rem);
	font-weight: 400;
	line-height: 1.7;
	text-align: center;
}

/* -------------------------------------------------------------- logo box ---- */

.nu-tech-partners__box-wrap {
	width: 100%;
}

.nu-tech-partners__box {
	display: flex;
	flex-direction: row;
	/*
	 * The source is `nowrap` until 767, where Bricks' own tablet rule flips it
	 * to `wrap`. That leaves a dead band: between roughly 768 and 1100 the seven
	 * marks no longer fit on one line, and with `overflow: visible` they spill
	 * straight out of the white box — visible on the live page at 991. Wrapping
	 * at every width fixes it and changes nothing where the row already fits.
	 */
	flex-wrap: wrap;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--space-m, 2.8rem) var(--nu-tep-logo-gap);
	padding: var(--space-l, 3.96rem);
	border-radius: var(--radius-s, 0.8rem);
	background-color: var(--nu-tep-box-bg);
}

.nu-tech-partners__link {
	display: inline-flex;
	flex: none;
	align-self: center;
}

.nu-tech-partners__logo {
	/* Each mark is fitted into a slot rather than sized by height alone: they
	   range from 1:1 to 2.6:1, so a shared height would leave the wide ones
	   running over their neighbours. */
	flex: none;
	align-self: center;
	width: auto;
	max-width: var(--nu-tep-logo-width);
	height: auto;
	max-height: var(--nu-tep-logo-height);
	object-fit: contain;
}

/* ------------------------------------------------------------ responsive ---- */

@media (max-width: 478px) {
	/* Phone: one scrolling row, as in the source — wrapping here would stack the
	   seven marks into four rows of a very tall box. */
	.nu-tech-partners__box {
		flex-wrap: nowrap;
		justify-content: flex-start;
		overflow-x: auto;
	}
}

/* ============ nu-channel-cards.css ============ */
/**
 * NÜ — Cartes canaux (couleurs alternées)
 *
 * Rebuilt from the live "#canaux" section of /campagnes-programmatiques/. The
 * source leans on Bricks theme styles (`.brxe-section` padding, `.brxe-container`
 * width + row-gap, the bare `h2`/`h3` rules) and on four global classes —
 * section_scroll, section_alternating-card-colours, grid-3/gap-m and color-card
 * — none of which a custom element inherits, so all of it is restated here.
 *
 * Resolved at a 1512 viewport:
 *     111.9 / 56       section padding
 *     1400             content width
 *     28               gap under the heading, both grid gaps, and between card parts
 *     42 / 46.2        heading, Spline Sans 300, --color-1
 *     39.6             card padding, 8px radius (--radius-s)
 *     50               icon height (width follows the artwork)
 *     22 / 24.2        card title, Space Mono 700 uppercase
 *     16 / 27.2        card text
 *
 * The alternation is :nth-child based, exactly as in the source's `color-card`
 * custom CSS: odd cards are navy on orange ink, even ones pale blue on navy. Add
 * or reorder a card and the colours re-flow with no per-card setting. The ink
 * colour is set once on the card and inherited by the title, the text and the
 * icon fill.
 *
 * Three deliberate departures, the same calls the rest of the library makes:
 *
 *  - Content caps at 1400, not the container's 1440. Below a 1552px viewport
 *    the two are identical (the section's 56px inline padding is what bites);
 *    above it, 1440 would leave this section 40px wider than its neighbours.
 *  - The card's last paragraph keeps no bottom margin. The site has a global
 *    `:where(p:last-of-type){margin-block-end: revert}` rule, which reverts to
 *    the UA's 1em and leaves ~16px of dead space at the bottom of every card.
 *  - Cards stay stretched inside the phone scroller. `color-card` sets no
 *    height, so the live strip sizes each card to its own text; on solid colour
 *    blocks a ragged bottom edge reads as a mistake in a way it does not on the
 *    near-invisible borders of nu-devices.
 *
 * One safety change: the source floors the icon at `min-height: 50px` and lets
 * anything taller through. Here it is bounded top and bottom, so an oversized
 * upload cannot blow the card open. Identical output for the shipped artwork.
 *
 * @see elements/nu-channel-cards.php
 */

.nu-channel-cards {
	--nu-chc-max-width: 1400px;
	--nu-chc-header-gap: var(--space-m, 2.8rem);
	--nu-chc-columns: 3;
	--nu-chc-gap: var(--space-m, 2.8rem);
	--nu-chc-card-gap: var(--space-m, 2.8rem);
	--nu-chc-icon-size: 50px;

	--nu-chc-odd-bg: var(--color-3, #061745);
	--nu-chc-odd-ink: var(--color-2, #ef4400);
	--nu-chc-even-bg: var(--color-4, #d7e3f5);
	--nu-chc-even-ink: var(--color-3, #061745);

	display: block;
	/* `section_scroll` in the source. */
	overflow: hidden;
	color: var(--color-3, #061745);
	/* The heading is sized in em, so the root's font-size is load-bearing:
	   Bricks' own h2 rule is `font-size: 2.1em` against the body's --text-m. */
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-m, 2rem);
	line-height: 1.7;
}

.nu-channel-cards__inner {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	row-gap: var(--nu-chc-header-gap);
	width: 100%;
	max-width: var(--nu-chc-max-width);
	margin-inline: auto;
}

.nu-channel-cards__heading {
	margin: 0;
	color: var(--color-1, #1600ba);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: 2.1em;
	font-weight: 300;
	line-height: 1.1em;
}

/* ------------------------------------------------------------------ grid ---- */

.nu-channel-cards__grid {
	display: grid;
	grid-template-columns: repeat(var(--nu-chc-columns), minmax(0, 1fr));
	/* Cards fill their track, so every card in a row is as tall as the tallest. */
	align-items: stretch;
	gap: var(--nu-chc-gap);
	width: 100%;
	margin: 0;
	padding: 0;
	list-style: none;
}

.nu-channel-cards__card {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	row-gap: var(--nu-chc-card-gap);
	padding: var(--space-l, 3.96rem);
	border-radius: var(--radius-s, 0.8rem);
	background-color: var(--nu-chc-odd-bg);
	color: var(--nu-chc-odd-ink);
	font-size: var(--text-s, 1.6rem);
	line-height: 1.7;
}

.nu-channel-cards__card:nth-child(even) {
	background-color: var(--nu-chc-even-bg);
	color: var(--nu-chc-even-ink);
}

/*
 * Height only: the shipped marks are 48×50 and 50×50, and the source sizes them
 * from the height alone so each keeps its own proportions.
 */
.nu-channel-cards__icon {
	display: block;
	flex: none;
	color: inherit;
}

.nu-channel-cards__icon svg {
	display: block;
	width: auto;
	height: var(--nu-chc-icon-size);
	min-height: var(--nu-chc-icon-size);
	max-height: var(--nu-chc-icon-size);
}

/* The shipped SVGs carry a baked-in fill, which the source's color-card rules
   also have to override — so the icon follows the card's ink. */
.nu-channel-cards__icon svg path {
	fill: currentColor;
}

.nu-channel-cards__card-title {
	margin: 0;
	color: inherit;
	font-family: "Space Mono", ui-monospace, monospace;
	font-size: var(--text-l, 2.2rem);
	font-weight: 700;
	line-height: 1.1em;
	text-transform: uppercase;
}

.nu-channel-cards__card-text {
	margin: 0;
	color: inherit;
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-s, 1.6rem);
	font-weight: 400;
	line-height: 1.7;
}

/* ------------------------------------------------------------ responsive ---- */

/*
 * Phone: the grid becomes a horizontal scroller of 85%-wide cards, and the
 * section gives up its inline padding so the strip can bleed to both edges —
 * the heading takes that padding back on its own. The cards also swap to the
 * source's taller phone padding, which drops the icon well clear of the top
 * corner. Bricks' phone-only section padding (`calc(var(--space-4xl) * 1.2)`)
 * applies to `.brxe-section` only, so it is restated here.
 */
@media (max-width: 478px) {
	.nu-channel-cards {
		--nu-section-space-inline: 0px;
	}

	.nu-channel-cards__heading {
		padding-inline: var(--space-xl, 5.6rem);
	}

	.nu-channel-cards__grid {
		display: flex;
		flex-direction: row;
		flex-wrap: nowrap;
		justify-content: flex-start;
		overflow-x: auto;
		padding: var(--space-l, 3.96rem) var(--space-xl, 5.6rem) var(--space-2xl, 7.92rem);
	}

	.nu-channel-cards__card {
		min-width: 85%;
		padding: var(--space-4xl, 15.83rem) var(--space-2xl, 7.92rem) var(--space-2xl, 7.92rem);
	}
}

/* ------------------------------------------------------- Dark surface ---- */

/* The cards carry their own two-tone ink, so only the section heading moves. */
.nu-section--dark.nu-channel-cards .nu-channel-cards__heading {
	color: var(--color-5, #e0dcff);
}

/* ============ nu-inventory-list.css ============ */
/**
 * NÜ — Réseau publicitaire (liste)
 *
 * Rebuilt from the live "#reseau-publicitaire" section of /nu-optima/. The
 * source leans on Bricks theme styles (`.brxe-section` padding, `.brxe-container`
 * width, the bare `h2` rule) and on the `text-intro`, `inventaires_liste`,
 * `inventaires`, `inventaires__type`, `inventaires__icon`,
 * `inventaires__logo-wrapper` and `inventaires__logo` global classes, so all of
 * it is restated here.
 *
 * Resolved at a 1512 viewport:
 *     111.9 / 56       section padding (no overflow clipping — the rows scroll)
 *     1400             content width
 *     56               gap under the header, 28 between heading and intro
 *     42 / 46.2        heading, Spline Sans 300, --color-1
 *     32 / 54.4        intro, Spline Sans 300, capped at 80%
 *     39.6             row padding-block, and the tile's own padding
 *     79.2             gap between tile and logos; the hairline sits at its middle
 *     150              tile min width, 20px radius (--radius-l)
 *     50 × 60          icon box
 *     18 / 19.8        tile label, Space Mono 700 uppercase, centred
 *     140              logo height (80 on phones), 56 between logos
 *
 * Tiles alternate by position: odd is navy with lilac ink, even is lilac with
 * navy ink — the `inventaires_liste` :nth-of-type rules. Setting `color` on the
 * tile is enough, because both the label and the icon fill inherit from it.
 *
 * Every row is its own horizontal scroller, which is why the section itself is
 * NOT `overflow: hidden` here: it has no `section_scroll` class in the source,
 * and clipping the section would cut the tiles' hairline dividers.
 *
 * Two deliberate departures, the same calls the rest of the library makes:
 * content caps at 1400 rather than the container's 1440, and the phone padding
 * is restated because Bricks' `calc(var(--space-4xl) * 1.2)` only applies to
 * `.brxe-section`.
 *
 * @see elements/nu-inventory-list.php
 */

.nu-inventory-list {
	--nu-inv-max-width: 1400px;
	--nu-inv-header-gap: var(--space-xl, 5.6rem);
	--nu-inv-heading-gap: var(--space-m, 2.8rem);
	--nu-inv-intro-width: 80%;
	--nu-inv-row-gap: var(--space-2xl, 7.92rem);
	--nu-inv-tile-width: 150px;
	--nu-inv-icon-width: 50px;
	--nu-inv-icon-size: 60px;
	--nu-inv-logo-height: 140px;
	--nu-inv-logo-gap: var(--space-xl, 5.6rem);

	--nu-inv-line: var(--color-5, #e0dcff);
	--nu-inv-odd-bg: var(--color-3, #061745);
	--nu-inv-odd-ink: var(--color-5, #e0dcff);
	--nu-inv-even-bg: var(--color-5, #e0dcff);
	--nu-inv-even-ink: var(--color-3, #061745);

	display: block;
	color: var(--color-3, #061745);
	/* The heading is sized in em, so the root's font-size is load-bearing:
	   Bricks' own h2 rule is `font-size: 2.1em` against the body's --text-m. */
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-m, 2rem);
	line-height: 1.7;
}

.nu-inventory-list__inner {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	row-gap: var(--nu-inv-header-gap);
	width: 100%;
	max-width: var(--nu-inv-max-width);
	margin-inline: auto;
}

/* ---------------------------------------------------------------- header ---- */

.nu-inventory-list__header {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	row-gap: var(--nu-inv-heading-gap);
	width: 100%;
}

.nu-inventory-list__heading {
	margin: 0;
	color: var(--color-1, #1600ba);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: 2.1em;
	font-weight: 300;
	line-height: 1.1em;
}

.nu-inventory-list__intro {
	/* The source's `text-intro` class ships this -1px, and it is what makes the
	   block below sit where it does. */
	margin: 0 0 -1px;
	max-width: var(--nu-inv-intro-width);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-xl, 3.2rem);
	font-weight: 300;
	line-height: 1.7;
}

/* ------------------------------------------------------------------ rows ---- */

.nu-inventory-list__rows {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	row-gap: 0;
	width: 100%;
	margin: 0;
	padding: 0;
	list-style: none;
}

.nu-inventory-list__row {
	position: relative;
	display: flex;
	flex-direction: row;
	flex-wrap: nowrap;
	align-items: flex-start;
	column-gap: var(--nu-inv-row-gap);
	width: 100%;
	padding-block: var(--space-l, 3.96rem);
	border-bottom: 1px solid var(--nu-inv-line);
	/* Each row scrolls on its own once the strip outgrows the container. */
	overflow-x: auto;
}

/*
 * A fixed 150px column, not a shrink-to-fit one. In the source the tile is
 * nominally `min-width: 150px` and free to shrink, but every row's logo strip
 * fills the line and pushes it back onto that floor — so all four tiles end up
 * exactly 150 whatever their label, and a one-word label like DISPLAY simply
 * overflows its box. Stating the width outright reproduces that without leaving
 * the tile's size at the mercy of how long the strip beside it happens to be.
 */
.nu-inventory-list__type {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	row-gap: var(--space-xs, 1.4rem);
	width: var(--nu-inv-tile-width);
	min-width: var(--nu-inv-tile-width);
	padding: var(--space-l, 3.96rem);
	border-radius: var(--radius-l, 2rem);
	background-color: var(--nu-inv-odd-bg);
	color: var(--nu-inv-odd-ink);
}

/* The hairline that separates the tile from its logos, parked halfway across
   the row gap so it stays centred whatever that gap is. */
.nu-inventory-list__type::after {
	content: "";
	position: absolute;
	top: 0;
	right: calc(var(--nu-inv-row-gap) * -0.5);
	width: 1px;
	height: 100%;
	background-color: var(--nu-inv-line);
}

.nu-inventory-list__row:nth-child(even) .nu-inventory-list__type {
	background-color: var(--nu-inv-even-bg);
	color: var(--nu-inv-even-ink);
}

/*
 * A fixed 50 × 60 box, with the artwork letterboxed inside it by the SVG's own
 * preserveAspectRatio. The source arrives at the same box by accident: it puts
 * `display: flex` on the <svg> itself, which stops it sizing as a replaced
 * element, so its width collapses to nothing and lands on the 50px floor rather
 * than following the 50 × 51 viewBox up to 58.8 at this height. Sizing by
 * height alone here would draw every mark ~18% larger than the section it
 * copies, so the box is stated outright instead.
 */
.nu-inventory-list__icon {
	display: flex;
	flex: none;
	width: var(--nu-inv-icon-width);
	height: var(--nu-inv-icon-size);
	color: inherit;
}

.nu-inventory-list__icon svg {
	display: block;
	width: 100%;
	height: 100%;
}

/* The shipped SVGs carry a baked-in fill, which the source's inventaires rules
   also have to override — so the icon follows the tile's ink. */
.nu-inventory-list__icon svg path {
	fill: currentColor;
}

/*
 * The `max-width` is what keeps every tile on its 150px floor: without it a
 * label wider than the tile's content box sets the tile's shrink-to-fit width
 * and the row gets a wider tile than its neighbours. Bricks hands the source the
 * same cap for free through its blanket `[class*="brxe-"] { max-width: 100% }`.
 * A one-word label simply overflows its box, as it does in the source.
 */
.nu-inventory-list__label {
	margin: 0;
	max-width: 100%;
	color: inherit;
	font-family: "Space Mono", ui-monospace, monospace;
	font-size: var(--text-tagline, 1.8rem);
	font-weight: 700;
	line-height: 1.1em;
	text-align: center;
	text-transform: uppercase;
}

.nu-inventory-list__logos {
	display: flex;
	flex-direction: row;
	flex-wrap: nowrap;
	align-items: flex-start;
	justify-content: flex-start;
	column-gap: var(--nu-inv-logo-gap);
}

/*
 * Height and object-fit only, exactly as the source sets them — no width and no
 * flex-basis. That matters: the marks are flex items with the default
 * `flex: 0 1 auto`, so a long strip squeezes them to fit the row instead of
 * pushing it into a scroll, and `contain` letterboxes each mark inside whatever
 * box it lands in. Pinning them with `flex: none` made the desktop rows scroll,
 * which the source never does.
 */
.nu-inventory-list__logo {
	display: block;
	height: var(--nu-inv-logo-height);
	object-fit: contain;
}

/* ------------------------------------------------------------ responsive ---- */

/*
 * Phone: the section gives up its inline padding so a row's strip can run to
 * both edges, and the header and each row take that padding back on their own.
 * Bricks' phone-only section padding (`calc(var(--space-4xl) * 1.2)`) applies
 * to `.brxe-section` only, so it is restated here.
 */
@media (max-width: 478px) {
	.nu-inventory-list {
		--nu-section-space-inline: 0px;

		--nu-inv-logo-height: 80px;
	}

	.nu-inventory-list__header {
		padding-inline: var(--space-xl, 5.6rem);
	}

	.nu-inventory-list__intro {
		max-width: 100%;
		font-size: var(--text-xl, 3.2rem);
	}

	.nu-inventory-list__row {
		padding-inline: var(--space-xl, 5.6rem);
	}

	/* Short strips read better centred against the tile than pinned to its top. */
	.nu-inventory-list__logos {
		align-self: center;
	}
}

/* ------------------------------------------------------- Dark surface ---- */

/* The rows carry their own two-tone ink, so only the section header moves. */
.nu-section--dark.nu-inventory-list .nu-inventory-list__heading {
	color: var(--color-5, #e0dcff);
}

/* ============ nu-inventories.css ============ */
/**
 * NÜ — Section inventaires
 *
 * Rebuilt from the live "#inventaires" section of /campagnes-programmatiques/.
 * The source leans on Bricks theme styles (`.brxe-section` padding,
 * `.brxe-container` width, the bare `h2` rule) and on the bg-surface, gap-3xl,
 * section_scroll, tagline, text-intro, grid-3/gap-m, white-card,
 * white-card__logo-wrapper, white-card__image and logo-7 global classes, so all
 * of it is restated here.
 *
 * Resolved at a 1512 viewport:
 *     111.9 / 56       section padding, on --bg-surface
 *     111.9            gap between the two blocks (gap-3xl)
 *     1400             content width
 *     79.2 / 56        gap under the first / second block's header
 *     28               gap between heading, tagline and intro; and the grid gap
 *     42 / 46.2        heading, Spline Sans 300, --color-1
 *     18 / 19.8        tagline, Space Mono 700 uppercase, --color-3
 *     32 / 54.4        intro, Spline Sans 300, capped at 80%
 *     56 / 28          card padding, 8px radius, white
 *     28%              card logo max width, on a hairline-ruled row
 *     140 × 65         marquee logo slot, 28 either side, 35s loop
 *
 * The marquee itself is nu_logo_marquee_html(), shared with nu-logo-marquee, so
 * only its slot size, background and logo opacity are re-pointed below — all of
 * them through selectors one class heavier than that sheet's `:where()` rules.
 *
 * Three deliberate departures, the same calls the rest of the library makes:
 * content caps at 1400 rather than the container's 1440; a card's last block
 * keeps no bottom margin (the site's global `:where(p:last-of-type)
 * {margin-block-end: revert}` and the UA's list margin otherwise leave ~16px of
 * dead space inside every card); and the phone padding is restated because
 * Bricks' `calc(var(--space-4xl) * 1.2)` only applies to `.brxe-section`.
 *
 * Cards size to their own text, as in the source. The "Equal card heights"
 * control adds `--stretch` when a flush bottom edge is wanted instead.
 *
 * @see elements/nu-inventories.php
 */

.nu-inventories {
	--nu-inv2-max-width: 1400px;
	--nu-inv2-block-gap: var(--space-3xl, 11.19rem);
	--nu-inv2-header-gap-one: var(--space-2xl, 7.92rem);
	--nu-inv2-header-gap-two: var(--space-xl, 5.6rem);
	--nu-inv2-heading-gap: var(--space-m, 2.8rem);
	--nu-inv2-intro-width: 80%;
	--nu-inv2-columns: 3;
	--nu-inv2-gap: var(--space-m, 2.8rem);

	--nu-inv2-card-bg: var(--light, #fff);
	--nu-inv2-card-logo-width: 28%;
	--nu-inv2-line: var(--color-5, #e0dcff);

	--nu-inv2-marquee-bg: var(--light, #fff);
	--nu-inv2-slot-width: 140px;
	--nu-inv2-slot-height: 65px;

	display: flex;
	flex-direction: column;
	align-items: center;
	row-gap: var(--nu-inv2-block-gap);
	/* `section_scroll` in the source. */
	overflow: hidden;
	color: var(--color-3, #061745);
	/* The heading is sized in em, so the root's font-size is load-bearing:
	   Bricks' own h2 rule is `font-size: 2.1em` against the body's --text-m. */
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-m, 2rem);
	line-height: 1.7;
}

.nu-inventories__block {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	width: 100%;
	max-width: var(--nu-inv2-max-width);
	margin-inline: auto;
}

/* The two blocks breathe differently in the source — cards need more air above
   them than the marquee card does. */
.nu-inventories__block--one {
	row-gap: var(--nu-inv2-header-gap-one);
}

.nu-inventories__block--two {
	row-gap: var(--nu-inv2-header-gap-two);
}

/* ---------------------------------------------------------------- header ---- */

.nu-inventories__header {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	row-gap: var(--nu-inv2-heading-gap);
	width: 100%;
}

.nu-inventories__heading {
	margin: 0;
	color: var(--color-1, #1600ba);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: 2.1em;
	font-weight: 300;
	line-height: 1.1em;
}

.nu-inventories__tagline {
	margin: 0;
	color: var(--color-3, #061745);
	font-family: "Space Mono", ui-monospace, monospace;
	font-size: var(--text-tagline, 1.8rem);
	font-weight: 700;
	line-height: 1.1em;
	text-transform: uppercase;
}

.nu-inventories__intro {
	/* The source's `text-intro` class ships this -1px, and it is what makes the
	   block below sit where it does. */
	margin: 0 0 -1px;
	max-width: var(--nu-inv2-intro-width);
	font-family: "Spline Sans", system-ui, sans-serif;
	font-size: var(--text-xl, 3.2rem);
	font-weight: 300;
	line-height: 1.7;
}

/* ----------------------------------------------------------------- cards ---- */

.nu-inventories__grid {
	display: grid;
	grid-template-columns: repeat(var(--nu-inv2-columns), minmax(0, 1fr));
	/* Cards size to their own text, as in the source. */
	align-items: start;
	gap: var(--nu-inv2-gap);
	width: 100%;
	margin: 0;
	padding: 0;
	list-style: none;
}

.nu-inventories--stretch .nu-inventories__grid {
	align-items: stretch;
}

.nu-inventories__card {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	row-gap: var(--space-m, 2.8rem);
	padding: var(--space-xl, 5.6rem) var(--space-m, 2.8rem);
	border-radius: var(--radius-s, 0.8rem);
	background-color: var(--nu-inv2-card-bg);
	font-size: var(--text-s, 1.6rem);
	line-height: 1.7;
}

.nu-inventories__card-logos {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	align-items: center;
	justify-content: flex-start;
	column-gap: var(--space-m, 2.8rem);
	row-gap: var(--space-m, 2.8rem);
	width: 100%;
	/* Fixed row height so the hairline under it sits at the same level on all
	   three cards — a square logo used to make its row twice as tall as one
	   holding only wide marks. The cap below is the other half of that. */
	min-height: 4.8rem;
	padding-bottom: var(--space-m, 2.8rem);
	border-bottom: 1px solid var(--nu-inv2-line);
}

.nu-inventories__card-logo {
	display: block;
	width: auto;
	max-width: var(--nu-inv2-card-logo-width);
	height: auto;
	max-height: 4.8rem;
	object-fit: contain;
}

.nu-inventories__card-text {
	width: 100%;
}

/* Bricks' own `:where(p)` margins are zero-specificity, so the rich text is
   spaced here instead — and the last block's trailing margin is dropped, which
   the site's global `:where(p:last-of-type){margin-block-end: revert}` and the
   UA's list margin would otherwise leave inside the card. */
.nu-inventories__card-text > :first-child {
	margin-top: 0;
}

.nu-inventories__card-text > :last-child {
	margin-bottom: 0;
}

.nu-inventories__card-text p {
	margin-block: 0 1em;
}

.nu-inventories__card-text ul,
.nu-inventories__card-text ol {
	margin-block: 1em;
	padding-left: 40px;
}

.nu-inventories__card-text li {
	line-height: inherit;
}

/* --------------------------------------------------------------- marquee ---- */

.nu-inventories__marquee-wrap {
	width: 100%;
}

/*
 * One class heavier than nu-logo-marquee.css, whose defaults are wrapped in
 * :where() — so these land whichever order the two sheets are printed in.
 */
.nu-inventories .nu-inventories__marquee {
	--nu-marquee-slot-width: var(--nu-inv2-slot-width);
	--nu-marquee-slot-height: var(--nu-inv2-slot-height);

	background-color: var(--nu-inv2-marquee-bg);
}

/* The source shows the marks at full strength; the shared band dims them. */
.nu-inventories .nu-logo-marquee__logo {
	opacity: 1;
}

/* ------------------------------------------------------------ responsive ---- */

/*
 * Phone: the section gives up its inline padding so the card strip can bleed to
 * both edges, and everything else takes that padding back on its own. Bricks'
 * phone-only section padding (`calc(var(--space-4xl) * 1.2)`) applies to
 * `.brxe-section` only, so it is restated here.
 */
@media (max-width: 478px) {
	.nu-inventories {
		--nu-inv2-header-gap-one: var(--space-2xl, 7.92rem);
		--nu-inv2-header-gap-two: var(--space-xl, 5.6rem);

		--nu-section-space-inline: 0px;
	}

	.nu-inventories__header {
		padding-inline: var(--space-xl, 5.6rem);
	}

	.nu-inventories__intro {
		max-width: 100%;
	}

	.nu-inventories__grid {
		display: flex;
		flex-direction: row;
		flex-wrap: nowrap;
		justify-content: flex-start;
		overflow-x: auto;
		padding: var(--space-l, 3.96rem) var(--space-xl, 5.6rem) var(--space-2xl, 7.92rem);
	}

	.nu-inventories__card {
		min-width: 85%;
		padding: var(--space-xl, 5.6rem) var(--space-m, 2.8rem);
	}

	.nu-inventories__card-logo {
		max-width: calc(33% - var(--space-xs, 1.4rem));
	}

	.nu-inventories__marquee-wrap {
		padding-inline: var(--space-xl, 5.6rem);
	}
}

/* ------------------------------------------------------- Dark surface ---- */

.nu-section--dark.nu-inventories .nu-inventories__heading,
.nu-section--dark.nu-inventories .nu-inventories__tagline {
	color: var(--color-5, #e0dcff);
}

/* ============ nu-back-to-top.css ============ */
/**
 * NÜ — back to top (pinpoint QA pin 46)
 *
 * One fixed circular button, injected on every front-end page from
 * inc/nu-back-to-top.php (wp_footer). Same 48px pill vocabulary as the
 * slider arrows, same colour convention as the hero CTA: orange at rest,
 * brand blue on hover/focus. assets/js/nu-back-to-top.js removes [hidden]
 * once it is running and flips data-visible after one viewport of scroll —
 * with the script absent the button never appears, so a dead control never
 * renders. Selectors stay plain classes, like every other NÜ sheet.
 */

.nu-back-to-top {
	position: fixed;
	right: 24px;
	bottom: calc(24px + env(safe-area-inset-bottom, 0px));
	/* Over the content, under the sticky header (998) and the megamenu
	   drawer (9990); the Complianz banner sits far above all of these. */
	z-index: 980;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	padding: 0;
	border: 0;
	border-radius: var(--radius-full, 999rem);
	background-color: var(--color-2, #ef4400);
	color: var(--light, #fff);
	box-shadow: 0 4px 14px rgba(6, 23, 69, 0.25);
	cursor: pointer;
	opacity: 0;
	transform: translateY(8px);
	pointer-events: none;
	/* Hidden state must also leave the tab order: visibility waits for the
	   fade-out, then takes the button out of focus/AT reach entirely. */
	visibility: hidden;
	transition: opacity 0.3s, transform 0.3s, background-color 0.3s, visibility 0s 0.3s;
}

/* The class sets display, which would otherwise beat the UA's [hidden]. */
.nu-back-to-top[hidden] {
	display: none;
}

.nu-back-to-top[data-visible="true"] {
	opacity: 1;
	transform: none;
	pointer-events: auto;
	visibility: visible;
	transition: opacity 0.3s, transform 0.3s, background-color 0.3s, visibility 0s;
}

/* Orange hovers to brand blue — the hero CTA convention. */
.nu-back-to-top:hover,
.nu-back-to-top:focus-visible {
	background-color: var(--color-1, #1600ba);
}

/* The CTA arrow nudge, turned upward: right arrows slide, this one lifts. */
.nu-back-to-top__arrow {
	display: block;
	width: 20px;
	height: 20px;
	transition: transform 0.3s;
}

.nu-back-to-top:hover .nu-back-to-top__arrow,
.nu-back-to-top:focus-visible .nu-back-to-top__arrow {
	transform: translateY(-3px);
}

@media (max-width: 767px) {
	.nu-back-to-top {
		right: 16px;
		bottom: calc(16px + env(safe-area-inset-bottom, 0px));
		width: 40px;
		height: 40px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.nu-back-to-top,
	.nu-back-to-top__arrow {
		transition: none;
	}

	.nu-back-to-top:hover .nu-back-to-top__arrow,
	.nu-back-to-top:focus-visible .nu-back-to-top__arrow {
		transform: none;
	}
}

/* ============ nu-slider.css ============ */
/**
 * NÜ — Shared SplideJS shell for the custom NÜ carousels.
 *
 * Loaded alongside 'bricks-splide' (Splide's own core CSS) by every NÜ element
 * that mounts a slider: the three post sliders and Section Confiance.
 *
 * Three things live here, all carried over from the source templates:
 *   1. the edge bleed — the track is padded so neighbouring slides peek, then
 *      pulled back out by an equal negative margin so the first slide still
 *      lines up with the container edge;
 *   2. the NÜ pill arrows, absolutely placed over the card image;
 *   3. pagination rendered as a full-width row of bars instead of dots.
 *
 * Zero-specificity :where() defaults so any builder value wins.
 *
 * Custom properties, set per element instance:
 *   --nu-slider-arrow-top          vertical centre of the arrow row (else 50%)
 *   --nu-slider-arrow-x            how far the arrows sit outside the track
 *   --nu-slider-peek-l/-r          must match the Splide `padding` option
 *   --nu-slider-pagination-bar     bar colour (else --dark-20)
 *   --nu-slider-pagination-bar-hover  ditto on hover/focus (else --dark-30)
 *
 * --nu-slider-arrow-top and the two pagination colours are deliberately *not*
 * given a value here: elements set them on the section, and a declaration on
 * .nu-slider (a descendant) would shadow that inherited value. The fallback in
 * each var() below is the default instead.
 */

:where(.nu-slider) {
	position: relative;

	--nu-slider-peek-l: clamp(12px, 3vw, 32px);
	--nu-slider-peek-r: clamp(24px, 5vw, 56px);
	--nu-slider-arrow-bg: var(--color-2, #ef4400);
	--nu-slider-arrow-fg: var(--light, #fff);
}

/* -------------------------------------------------------------- Edge bleed */

/* Splide writes the padding inline; repeat it so the negative margin below is
 * computed against a value we control, and let slides paint past the track. */
.nu-slider .splide__track {
	overflow: visible;
	padding-left: var(--nu-slider-peek-l) !important;
	padding-right: var(--nu-slider-peek-r) !important;
	margin-left: calc(var(--nu-slider-peek-l) * -1);
	margin-right: calc(var(--nu-slider-peek-r) * -1);
}

:where(.nu-slider, .nu-slider .splide__list) {
	overflow: visible;
}

:where(.nu-slider .splide__list) {
	margin: 0;
	padding: 0;
	list-style: none;
}

:where(.nu-slider .splide__slide) {
	height: auto;
}

@media (max-width: 1024px) {
	:where(.nu-slider) {
		--nu-slider-peek-l: clamp(12px, 3vw, 28px);
		--nu-slider-peek-r: clamp(20px, 5vw, 40px);
	}
}

@media (max-width: 640px) {
	:where(.nu-slider) {
		--nu-slider-peek-l: 16px;
		--nu-slider-peek-r: 24px;
	}
}

/* ---------------------------------------------------------------- Arrows */

:where(.nu-slider__arrows) {
	position: absolute;
	top: var(--nu-slider-arrow-top, 50%);
	left: 0;
	right: 0;
	height: 0;
	pointer-events: none;
	z-index: 3;
}

:where(.nu-slider .splide__arrow) {
	position: absolute;
	top: 0;
	transform: translateY(-50%);
	width: 48px;
	height: 49px;
	padding: 0;
	border: 0;
	border-radius: var(--radius-full, 999rem);
	background: none;
	cursor: pointer;
	pointer-events: auto;
	opacity: 1;
}

:where(.nu-slider .splide__arrow--prev) { left: var(--nu-slider-arrow-x, -16px); }
:where(.nu-slider .splide__arrow--next) { right: var(--nu-slider-arrow-x, -16px); }

:where(.nu-slider__arrow-svg) {
	display: block;
	width: 100%;
	height: 100%;
}

/* Colours live on the SVG parts, never on fill/stroke attributes, so a Bricks
 * colour control can override them. */
.nu-slider__arrow-pill {
	fill: var(--nu-slider-arrow-bg);
	transition: fill 0.2s ease;
}

.nu-slider__arrow-chevron {
	fill: none;
	stroke: var(--nu-slider-arrow-fg);
	transition: stroke 0.2s ease;
}

.nu-slider__arrow-shaft {
	fill: var(--nu-slider-arrow-fg);
	transition: fill 0.2s ease;
}

/* Inverted on hover. */
.nu-slider .splide__arrow:hover .nu-slider__arrow-pill,
.nu-slider .splide__arrow:focus-visible .nu-slider__arrow-pill {
	fill: var(--nu-slider-arrow-fg);
}

.nu-slider .splide__arrow:hover .nu-slider__arrow-chevron,
.nu-slider .splide__arrow:focus-visible .nu-slider__arrow-chevron {
	stroke: var(--nu-slider-arrow-bg);
}

.nu-slider .splide__arrow:hover .nu-slider__arrow-shaft,
.nu-slider .splide__arrow:focus-visible .nu-slider__arrow-shaft {
	fill: var(--nu-slider-arrow-bg);
}

.nu-slider .splide__arrow:disabled {
	opacity: 0;
	pointer-events: none;
}

@media (max-width: 767px) {
	:where(.nu-slider .splide__arrow) {
		transform: translateY(-50%) scale(0.65);
	}

	:where(.nu-slider .splide__arrow--prev) { left: -20px; }
	:where(.nu-slider .splide__arrow--next) { right: -20px; }
}

/* ------------------------------------------------------------ Pagination */

/* Splide appends its own <ul>; restyled as a full-width row of bars. */
:where(.nu-slider .splide__pagination) {
	position: static;
	display: flex;
	width: 100%;
	gap: 0;
	margin: var(--space-m, 2.8rem) 0 0;
	padding: 0;
	list-style: none;
	transform: none;
}

:where(.nu-slider .splide__pagination li) {
	flex: 1 1 0;
	margin: 0;
}

:where(.nu-slider .splide__pagination__page) {
	display: block;
	width: 100%;
	height: 4px;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: var(--radius-full, 999rem);
	background: var(--nu-slider-pagination-bar, var(--dark-20, rgba(6, 23, 69, 0.2)));
	opacity: 1;
	cursor: pointer;
	transform: none;
	transition: background 0.25s ease, height 0.2s ease;
}

:where(.nu-slider .splide__pagination__page:hover),
:where(.nu-slider .splide__pagination__page:focus-visible) {
	height: 5px;
	background: var(--nu-slider-pagination-bar-hover, var(--dark-30, rgba(6, 23, 69, 0.3)));
	outline: none;
}

:where(.nu-slider .splide__pagination__page.is-active) {
	height: 6px;
	background: var(--color-2, #ef4400);
	transform: none;
}

/* ============ nu-post-slider.css ============ */
/**
 * NÜ — Post sliders (Nouvelles, Revue de presse, Études de cas).
 *
 * The section chrome and card composition shared by the three post carousels;
 * the Splide shell they sit in lives in nu-slider.css.
 *
 * Zero-specificity :where() defaults so any builder value wins. Colours that
 * must beat theme element rules use plain class selectors (0,1,0).
 *
 * Custom properties, set per element instance by PHP:
 *   --nu-post-slider-media-height   305px (posts) / 453px (case studies) — cap
 *   --nu-slider-arrow-top           152px (posts) / 226px (case studies)
 * and by this stylesheet, per variant:
 *   --nu-post-slider-media-ratio    395 / 305 (posts), 642 / 453 (case studies)
 *
 * Every colour is read through a custom property declared on the section root,
 * so the four brand surfaces at the bottom of this file re-point the palette
 * instead of restyling parts — which keeps each per-part colour control (Bricks
 * writes those as #brxe-{id} rules) winning over whichever theme is picked.
 *
 * Core Framework tokens (html font-size 62.5%, 1rem = 10px):
 *   heading  → theme h2, var(--color-1)
 *   title    → 2.4rem
 *   pill     → Space Mono 1.2rem on var(--light), radius-full
 *   button   → text-only, no background: ink var(--color-3), orange on hover
 */

:where(.nu-post-slider) {
	--nu-post-slider-heading: var(--color-1, #1600ba);
	--nu-post-slider-ink: var(--text-body, #061745);
	--nu-post-slider-muted: var(--text-body, #061745);
	--nu-post-slider-cta-bg: transparent;
	--nu-post-slider-cta-ink: var(--color-3, #061745);
	--nu-post-slider-cta-ink-hover: var(--color-2, #ef4400);
	--nu-post-slider-pill-bg: var(--light, #fff);
	--nu-post-slider-pill-ink: var(--color-3, #061745);
	--nu-post-slider-button-ink: var(--color-3, #061745);
	--nu-post-slider-button-ink-hover: var(--color-2, #ef4400);

	/* The card title has no colour of its own — Bricks' theme styles give bare
	   headings a face and a line-height but no colour — so it inherits this. */
	color: var(--nu-post-slider-ink);

	width: 100%;
	overflow: hidden;
}

:where(.nu-post-slider__inner) {
	display: flex;
	flex-direction: column;
	gap: 4.8rem;
	max-width: 140rem;
	margin-inline: auto;
}

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

:where(.nu-post-slider__head) {
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-m, 2.8rem);
}

:where(.nu-post-slider__heading) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
}

.nu-post-slider__heading {
	color: var(--nu-post-slider-heading);
}

:where(.nu-post-slider__cta) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.8rem;
	flex: none;
	padding: 0;
	border-radius: var(--radius-full, 999rem);
	font-family: 'Spline Sans', sans-serif;
	font-weight: 700;
	font-size: var(--text-button, 1.6rem);
	line-height: 2.4rem;
	text-decoration: none;
	color: var(--nu-post-slider-cta-ink);
	background-color: var(--nu-post-slider-cta-bg);
	transition: background-color 0.25s ease, color 0.25s ease;
}

.nu-post-slider__cta {
	color: var(--nu-post-slider-cta-ink);
}

/* Plain class, not :where(): the base colour above is a plain class too, so a
   zero-specificity hover would never win. */
.nu-post-slider__cta:hover,
.nu-post-slider__cta:focus-visible {
	color: var(--nu-post-slider-cta-ink-hover);
}

:where(.nu-post-slider__cta-icon) {
	display: inline-flex;
	flex: none;
	width: 2rem;
	height: 2rem;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-post-slider__cta:hover .nu-post-slider__cta-icon,
.nu-post-slider__cta:focus-visible .nu-post-slider__cta-icon {
	transform: translateX(10px);
}

:where(.nu-post-slider__cta-icon svg) {
	width: 100%;
	height: 100%;
}

/* --------------------------------------------------------------- Slider */

:where(.nu-post-slider__slider) {
	padding-bottom: var(--space-2xl, 7.92rem);
}

/* ----------------------------------------------------------------- Card */

:where(.nu-post-slider__card) {
	display: flex;
	flex-direction: column;
	gap: var(--space-s, 1.98rem);
	height: 100%;
}

/**
 * The media box is always landscape: a fixed aspect-ratio sizes it at every
 * viewport, so a portrait thumbnail is cropped by object-fit below instead of
 * reshaping the card. The per-variant height variable now only caps the box
 * at the mockup height (395x305 / 642x453 — pixel-equal to the old fixed
 * heights at full desktop width). NOTE: the Bricks "Image height" control
 * writes only `height` at #brxe scope while the root's inline
 * --nu-post-slider-media-height keeps the variant default, so a control value
 * LARGER than 305px/453px is clamped by this max-height; smaller values win.
 * No instance sets the control today.
 */
:where(.nu-post-slider__media) {
	position: relative;
	overflow: hidden;
	border-radius: var(--radius-s, 0.8rem);
	aspect-ratio: var(--nu-post-slider-media-ratio, 395 / 305);
	max-height: var(--nu-post-slider-media-height, 305px);
	flex: none;
}

/* Case-study covers are taller than post covers: same cap logic, own ratio. */
.nu-post-slider--etudes {
	--nu-post-slider-media-ratio: 642 / 453;
}

:where(.nu-post-slider__media-link) {
	display: block;
	width: 100%;
	height: 100%;
}

/**
 * The thumbnail fills its window and is cropped.
 *
 * The source templates got there by a detour — a square image element inside a
 * shorter wrapper with overflow hidden — which only fills when the thumbnail
 * happens to be square. object-fit does the same thing for any aspect ratio, and
 * keeps the category pills legible over the photo instead of stranding them on
 * the letterbox band.
 */
:where(.nu-post-slider__image) {
	display: block;
	width: 100%;
	min-width: 100%;
	height: 100%;
	min-height: 100%;
	object-fit: cover;
	transition: transform 0.3s ease;
}

:where(.nu-post-slider__media:hover .nu-post-slider__image) {
	transform: scale(1.2);
}

:where(.nu-post-slider__client-logo) {
	position: absolute;
	top: var(--space-s, 1.98rem);
	right: var(--space-s, 1.98rem);
	max-width: 150px;
	height: auto;
	z-index: 2;
}

:where(.nu-post-slider__pills) {
	position: absolute;
	left: var(--space-xs, 1.4rem);
	bottom: var(--space-xs, 1.4rem);
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-start;
	gap: var(--space-2xs, 0.99rem);
	z-index: 2;
}

:where(.nu-post-slider__pill) {
	display: inline-block;
	padding: var(--space-3xs, 0.7rem) var(--space-s, 1.98rem);
	border-radius: var(--radius-full, 999rem);
	background-color: var(--nu-post-slider-pill-bg);
	font-family: 'Space Mono', monospace;
	font-weight: 700;
	font-size: 1.2rem;
	line-height: 1.5rem;
	letter-spacing: 0.1rem;
	text-transform: uppercase;
	text-align: center;
	color: var(--nu-post-slider-pill-ink);
}

:where(.nu-post-slider__title) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 300;
	font-size: 2.4rem;
	line-height: 1.25;
}

:where(.nu-post-slider__title a) {
	color: inherit;
	text-decoration: none;
}

:where(.nu-post-slider__title a:hover) {
	text-decoration: underline;
}

:where(.nu-post-slider__subtitle) {
	margin: 0;
	font-family: 'Spline Sans', sans-serif;
	font-size: 1.8rem;
	line-height: 1.5;
	color: var(--nu-post-slider-muted);
}

:where(.nu-post-slider__button) {
	display: inline-flex;
	align-items: center;
	gap: 0.8rem;
	align-self: flex-start;
	margin-top: auto;
	padding-block: 0;
	font-family: 'Spline Sans', sans-serif;
	font-weight: 500;
	font-size: var(--text-button, 1.6rem);
	line-height: 2.4rem;
	text-decoration: none;
	color: var(--nu-post-slider-button-ink);
	transition: color 0.25s ease;
}

.nu-post-slider__button {
	color: var(--nu-post-slider-button-ink);
}

.nu-post-slider__button:hover,
.nu-post-slider__button:focus-visible {
	color: var(--nu-post-slider-button-ink-hover);
}

:where(.nu-post-slider__button-icon) {
	display: inline-flex;
	flex: none;
	width: 2rem;
	height: 2rem;
	transition: transform 0.3s;
}

/* The arrow slides right on hover — same 10px nudge as the home hero. */
.nu-post-slider__button:hover .nu-post-slider__button-icon,
.nu-post-slider__button:focus-visible .nu-post-slider__button-icon {
	transform: translateX(10px);
}

:where(.nu-post-slider__button-icon svg) {
	width: 100%;
	height: 100%;
}

.nu-post-slider__cta-icon svg path,
.nu-post-slider__button-icon svg path {
	fill: currentColor;
}

/* ------------------------------------------------------------ Breakpoints */

@media (max-width: 991px) {
	:where(.nu-post-slider__inner) {
		gap: 4rem;
	}
}

@media (max-width: 767px) {
	:where(.nu-post-slider__head) {
		flex-direction: column;
		align-items: flex-start;
	}

	:where(.nu-post-slider__button) {
		font-size: 1.6rem;
		font-weight: 600;
	}

	/* Case-study covers now scale through the shared media aspect-ratio. */
}

/* ---------------------------------------------------------------- Themes */

/*
 * The four brand surfaces, matching Section Intro's set.
 *
 * "White" is the absence of a rule: the default surface is transparent rather
 * than #fff, so a slider dropped onto an already-tinted page keeps showing
 * through — which is how all three rendered before this control existed.
 *
 * Only the section root's variables move. The defaults above sit in :where()
 * (zero specificity) and these blocks are a plain class, so they win; and both
 * lose to the #brxe-{id} rules Bricks writes for the Style tab's own colour
 * controls, which is what lets a single part be recoloured inside a theme.
 */

/*
 * On navy neither the color-1 heading nor the color-3 CTA text has any edge
 * left, so both move to the light end of the palette: the heading to --light,
 * secondary copy to color-5, and the CTA to --light with the same orange hover
 * it has elsewhere. The pills stay white-on-photo — they never touch the
 * surface.
 */
.nu-post-slider--dark {
	--nu-post-slider-heading: var(--light, #fff);
	--nu-post-slider-ink: var(--light, #fff);
	--nu-post-slider-muted: var(--color-5, #e0dcff);
	--nu-post-slider-cta-ink: var(--light, #fff);
	--nu-post-slider-button-ink: var(--color-5, #e0dcff);

	/* The pagination bars live in nu-slider.css and are tinted from --dark-*,
	   which is all but invisible on navy. */
	--nu-slider-pagination-bar: var(--light-20, rgba(255, 255, 255, 0.2));
	--nu-slider-pagination-bar-hover: var(--light-30, rgba(255, 255, 255, 0.3));
}

@media (prefers-reduced-motion: reduce) {
	.nu-post-slider__cta,
	.nu-post-slider__cta-icon {
		transition: none;
	}

	.nu-post-slider__cta:hover .nu-post-slider__cta-icon,
	.nu-post-slider__cta:focus-visible .nu-post-slider__cta-icon {
		transform: none;
	}

	.nu-post-slider__button,
	.nu-post-slider__button-icon {
		transition: none;
	}

	.nu-post-slider__button:hover .nu-post-slider__button-icon,
	.nu-post-slider__button:focus-visible .nu-post-slider__button-icon {
		transform: none;
	}
}

/* ============ nu-icons.css ============ */
/*
 * The two FontAwesome "brands" glyphs the site actually uses, drawn as CSS
 * masks over currentColor. Replaces the fa-brands font (115 KB) and its layer
 * stylesheet, which functions.php deregisters. Path data © Fonticons (FA Free,
 * CC BY 4.0).
 */
.fab {
	display: inline-block;
	width: 1em;
	height: 1em;
	line-height: 1;
	vertical-align: -0.125em;
	/* The share circles are tightly-padded flex boxes: without this the glyph
	   is flex-shrunk to a sliver (Bricks sets the same on its own svgs). */
	flex-shrink: 0;
}

/* Bricks' post-sharing circles zero out the em context, which collapsed the
   mask glyphs — size those two in rem instead. */
.brxe-post-sharing .fab {
	width: 1.125rem;
	height: 1.125rem;
}

.fab::before {
	content: "";
	display: block;
	width: 100%;
	height: 100%;
	background: currentColor;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
}

.fab.fa-linkedin-in::before {
	-webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath d='M100.28 448H7.4V148.9h92.88zM53.79 108.1C24.09 108.1 0 83.5 0 53.8a53.79 53.79 0 0 1 107.58 0c0 29.7-24.1 54.3-53.79 54.3zM447.9 448h-92.68V302.4c0-34.7-.7-79.2-48.29-79.2-48.29 0-55.69 37.7-55.69 76.7V448h-92.78V148.9h89.08v40.8h1.3c12.4-23.5 42.69-48.3 87.88-48.3 94 0 111.28 61.9 111.28 142.3z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath d='M100.28 448H7.4V148.9h92.88zM53.79 108.1C24.09 108.1 0 83.5 0 53.8a53.79 53.79 0 0 1 107.58 0c0 29.7-24.1 54.3-53.79 54.3zM447.9 448h-92.68V302.4c0-34.7-.7-79.2-48.29-79.2-48.29 0-55.69 37.7-55.69 76.7V448h-92.78V148.9h89.08v40.8h1.3c12.4-23.5 42.69-48.3 87.88-48.3 94 0 111.28 61.9 111.28 142.3z'/%3E%3C/svg%3E");
}

.fab.fa-facebook-f::before {
	-webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath d='M80 299.3V512H196V299.3h86.5l18-97.8H196V166.9c0-51.7 20.3-71.5 72.7-71.5c16.3 0 29.4 .4 37 1.2V7.9C291.4 4 256.4 0 236.2 0C129.3 0 80 50.5 80 151.1v50.4H14v97.8z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath d='M80 299.3V512H196V299.3h86.5l18-97.8H196V166.9c0-51.7 20.3-71.5 72.7-71.5c16.3 0 29.4 .4 37 1.2V7.9C291.4 4 256.4 0 236.2 0C129.3 0 80 50.5 80 151.1v50.4H14v97.8z'/%3E%3C/svg%3E");
}

/*
 * Obfuscated links (SEO): spans that behave like links for humans. The script
 * that activates them is printed from inc/nu-seo.php.
 */
.nu-obf {
	cursor: pointer;
}

.nu-obf:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}

/* ============ nu-animate.css ============ */
/**
 * NÜ — scroll-reveal start states.
 *
 * Every rule is gated on `html.nu-anim`, which an inline head script stamps
 * only when JavaScript is running and the visitor has not asked for reduced
 * motion — so without JS, in the builder, and under prefers-reduced-motion
 * nothing here applies and the page renders settled. The script also removes
 * the class if assets/js/nu-animate.js never arms itself, so a failed script
 * can never leave content hidden.
 *
 * The selector lists mirror the RECIPES map in nu-animate.js — the JS is what
 * animates each of these nodes back to its natural state, so the two files
 * must list the same targets. Only opacity / transform / filter, never
 * display or visibility: removing the class must revert instantly, and the
 * content has to stay in the accessibility tree throughout.
 *
 * @see assets/js/nu-animate.js
 * @see inc/nu-animate-assets.php
 */

/* Split-text containers: hidden until their lines are built, then the lines
   animate and the container is revealed inline. */
html.nu-anim .nu-agency__title,
html.nu-anim .nu-section-split__heading,
html.nu-anim .nu-channels__heading,
html.nu-anim .nu-logo-marquee__heading,
html.nu-anim .nu-post-slider__heading,
html.nu-anim .nu-confiance__heading,
html.nu-anim .nu-contact__heading,
html.nu-anim .nu-content-text__heading,
html.nu-anim .nu-text-image__heading,
html.nu-anim .nu-cards-colors__heading,
html.nu-anim .nu-channel-cards__heading,
html.nu-anim .nu-devices__heading,
html.nu-anim .nu-technologies__heading,
html.nu-anim .nu-tech-partners__heading,
html.nu-anim .nu-inventory-list__heading,
html.nu-anim .nu-inventories__heading,
html.nu-anim .nu-trio1__headline,
html.nu-anim .nu-trio2__headline,
html.nu-anim .nu-banner__headline,
html.nu-anim .nu-overview__headline,
html.nu-anim .nu-distinctions__heading,
html.nu-anim .nu-recompenses__headline,
html.nu-anim .nu-ciblages__heading,
html.nu-anim .nu-cadre-ethique__heading,
html.nu-anim .nu-cta__heading,
html.nu-anim .nu-faq__heading,
html.nu-anim .nu-intro__text,
html.nu-anim .nu-section-split__text,
html.nu-anim .nu-quote__paragraph,
html.nu-anim .nu-contact__text,
html.nu-anim .nu-content-text__text,
html.nu-anim .nu-text-image__text,
html.nu-anim .nu-cards-colors__header .nu-cards-colors__text,
html.nu-anim .nu-tech-partners__text,
html.nu-anim .nu-inventory-list__intro,
html.nu-anim .nu-inventories__intro,
html.nu-anim .nu-trio1__headlines .nu-trio1__paragraph,
html.nu-anim .nu-trio2__headlines .nu-trio2__paragraph,
html.nu-anim .nu-banner__paragraph,
html.nu-anim .nu-overview__paragraph,
html.nu-anim .nu-distinctions__text,
html.nu-anim .nu-ciblages__intro .nu-ciblages__text,
html.nu-anim .nu-cadre-ethique__intro .nu-cadre-ethique__text,
html.nu-anim .nu-cta__text,
html.nu-anim .nu-faq__intro p {
	opacity: 0;
}

/* Rise: standalone taglines, buttons and short copy. */
html.nu-anim .nu-hero-inner__heading,
html.nu-anim .nu-hero-inner__text,
html.nu-anim .nu-hero-inner__button,
html.nu-anim .nu-intro__tagline,
html.nu-anim .nu-intro__button,
html.nu-anim .nu-agency__head .nu-agency__button,
html.nu-anim .nu-section-split__button,
html.nu-anim .nu-channels__subheading,
html.nu-anim .nu-channels__header .nu-channels__button,
html.nu-anim .nu-logo-marquee__text,
html.nu-anim .nu-logo-marquee-wrap .nu-logo-marquee__button,
html.nu-anim .nu-post-slider__cta,
html.nu-anim .nu-quote__attribution,
html.nu-anim .nu-quote__button,
html.nu-anim .nu-content-text__button,
html.nu-anim .nu-text-image__button,
html.nu-anim .nu-technologies__eyebrow,
html.nu-anim .nu-inventories__tagline,
html.nu-anim .nu-banner__subtitle,
html.nu-anim .nu-banner__button,
html.nu-anim .nu-overview__button,
html.nu-anim .nu-distinctions__button,
html.nu-anim .nu-ciblages__button,
html.nu-anim .nu-cta__tagline,
html.nu-anim .nu-cta__button,
/* Cards and list items: same start state, staggered by the JS. */
html.nu-anim .nu-stats__item,
html.nu-anim .nu-agency__card,
html.nu-anim .nu-section-split__item,
html.nu-anim .nu-channels__item,
html.nu-anim .nu-post-slider__card,
html.nu-anim .nu-confiance__card,
html.nu-anim .nu-contact__info,
html.nu-anim .nu-contact__form,
html.nu-anim .nu-cards-colors__card,
html.nu-anim .nu-channel-cards__card,
html.nu-anim .nu-devices__card,
html.nu-anim .nu-technologies__card,
html.nu-anim .nu-inventory-list__row,
html.nu-anim .nu-inventories__card,
html.nu-anim .nu-trio1__card,
html.nu-anim .nu-trio2__card,
html.nu-anim .nu-distinctions__item,
html.nu-anim .nu-recompenses__card,
html.nu-anim .nu-ciblages__card,
html.nu-anim .nu-cadre-ethique__item,
html.nu-anim .nu-feature-grid__card,
html.nu-anim .nu-faq__item {
	opacity: 0;
	transform: translateY(40px);
}

/* Fade: bands and ornaments that should not move. */
html.nu-anim .nu-stats__footnote,
html.nu-anim .nu-logo-marquee-wrap .nu-logo-marquee,
html.nu-anim .nu-confiance__logos,
html.nu-anim .nu-quote__watermark,
html.nu-anim .nu-quote__mark,
html.nu-anim .nu-tech-partners__box-wrap,
html.nu-anim .nu-inventories__marquee-wrap,
html.nu-anim .nu-cta__mark {
	opacity: 0;
}

/* Images unveil from a blur — their wrappers all clip, so the overscale
   never bleeds. will-change because filter transitions are the one
   genuinely expensive treatment. */
html.nu-anim .nu-section-split__image,
html.nu-anim .nu-text-image__image,
html.nu-anim .nu-quote__image {
	filter: blur(18px);
	transform: scale(1.35);
	will-change: filter, transform;
}
