@font-face {
	font-family: "Uncut Sans";
	src: url("../fonts/uncut-sans/UncutSans-Regular.woff2") format("woff2");
	font-weight: 400;
	font-style: normal;
	font-display: swap;
}
@font-face {
	font-family: "Uncut Sans";
	src: url("../fonts/uncut-sans/UncutSans-Medium.woff2") format("woff2");
	font-weight: 500;
	font-style: normal;
	font-display: swap;
}
@font-face {
	font-family: "Uncut Sans";
	src: url("../fonts/uncut-sans/UncutSans-Semibold.woff2") format("woff2");
	font-weight: 600;
	font-style: normal;
	font-display: swap;
}
@font-face {
	font-family: "Uncut Sans";
	src: url("../fonts/uncut-sans/UncutSans-Bold.woff2") format("woff2");
	font-weight: 700;
	font-style: normal;
	font-display: swap;
}

/* Reserve the scrollbar's width on BOTH edges so the content column stays centered
   relative to the window (not to window-minus-scrollbar). Without this, the vertical
   scrollbar pushes every centered header ~8px off-center on the screen. */
html {
	scrollbar-gutter: stable both-edges;
}

.hv2 {
	margin: 0;
	background: #0e0e0e;
	color: #fff;
	font-family: "Uncut Sans", "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
	-webkit-font-smoothing: antialiased;
}
.hv2 * {
	box-sizing: border-box;
}
/* Force Uncut Sans on every element inside V2 pages — overrides the theme's
   global element rules (style.css sets p{monospace}, body{sans}) which otherwise
   win over inheritance. */
.hv2,
.hv2 *,
.hv2 h1, .hv2 h2, .hv2 h3, .hv2 h4, .hv2 h5, .hv2 h6,
.hv2 p, .hv2 a, .hv2 span, .hv2 li, .hv2 div,
.hv2 button, .hv2 input, .hv2 select, .hv2 textarea {
	font-family: "Uncut Sans", "Inter", -apple-system, BlinkMacSystemFont, sans-serif !important;
}

:root {
	/* Distance from the viewport edge to the vertical frame rails. Figma's 1920
	   frame puts them at 100px. Below 1440 this ramps down: the rails were
	   pinned at 100px all the way to 1024, where a fixed 100 + 60 inset left
	   only 704px of a 1024 screen for content (31% of the viewport in gutters,
	   against the 16.7% the 1920 design actually specifies). The ramp hits
	   exactly 100px at 1440, so every width from 1440 up is unchanged. */
	--hv-gutter: 100px;
	/* Gap between the vertical frame rails and section content. Figma puts the
	   content column at 1600 inside the 1720 rails. Scales with the gutter so
	   the two never drift out of proportion. */
	--hv-rail-inset: 60px;
}
@media (min-width: 1024px) and (max-width: 1439px) {
	:root {
		--hv-gutter: clamp(48px, 12.5vw - 80px, 100px);
		--hv-rail-inset: clamp(28px, 7.7vw - 50.8px, 60px);
	}
}

.hv-shell {
	max-width: min(1920px, 100%);
	margin-inline: auto;
	padding-inline: var(--hv-gutter);
}

/* Continuous vertical frame lines down both edges of the content column (Figma 87:13238).
   Content column = 1720px centred with 100px gutters; lines sit at the gutter boundary and
   run the full height of the header, every stacked section, and the footer, so they read as
   one unbroken line from the very top of the page to the very bottom. */
.hv-header,
main > section,
.hv-footer { position: relative; }
.hv-header::before,  .hv-header::after,
main > section::before, main > section::after,
.hv-footer::before,  .hv-footer::after {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	width: 1px;
	background: rgba(255, 255, 255, 0.12);
	pointer-events: none;
	z-index: 4;
}
.hv-header::before, main > section::before, .hv-footer::before { left: max(var(--hv-gutter), calc((100% - 1720px) / 2)); }
.hv-header::after,  main > section::after,  .hv-footer::after  { right: max(var(--hv-gutter), calc((100% - 1720px) / 2)); }
/* Business Impact ends in a bright glow, and a white rail stays visible against it — with
   the section's own bottom edge the two rails close into a lit rectangle sitting on top of
   the glow. Fade them out as the glow comes up. The line still reads as continuous: the
   light section directly below picks the rail straight back up in its dark variant. */
.hv-impact::before,
.hv-impact::after {
	background: linear-gradient(
		180deg,
		rgba(255, 255, 255, 0.12) 0%,
		rgba(255, 255, 255, 0.12) 55%,
		rgba(255, 255, 255, 0) 80%
	);
}
/* light-theme sections use a dark line instead (covers every product page:
   hv-, se-, rp-, cbv-, cp-, en-, oiq- ... any "*-light" section) */
main > section[class*="-light"]::before,
main > section[class*="-light"]::after {
	background: rgba(0, 0, 0, 0.12);
}
/* Contain a dotted header's top margin inside the light section so it never
   collapses out as a dark gap above it — this keeps the glow's light edge from
   the section above connected straight into the light section (no black band). */
main > section[class*="-light"] { display: flow-root; }
/* Content must never touch the frame rails. The rails sit at the 100px gutter,
   and .hv-shell's own 100px padding put content flush against them — sections
   only looked right where they happened to wrap their content in a
   `max-width: 1600px` inner, and even then the gap collapsed once the viewport
   dropped below ~1800px. Figma puts the content column at 1600 inside the 1720
   rails, i.e. a 60px gap, which is what 160px of padding gives. This was
   already the rule for heroes; it applies to every section.

   Header and footer are deliberately excluded: Figma has their frames flush at
   x=100 (the nav's bordered cells start on the rail) and the footer insets its
   own content instead. */
@media (min-width: 1024px) {
	main > section > .hv-shell {
		padding-inline: calc(var(--hv-gutter) + var(--hv-rail-inset));
	}
	/* The dotted heading bands are full-bleed: their hairline top/bottom rules
	   are meant to meet the vertical rails, so they have to come back out of
	   the inset above. Pulled by the same variable, so the two cannot drift. */
	main > section > .hv-shell > [class*="head--dots"],
	main > section > .hv-shell > [class*="head--bordered"],
	main > section > .hv-shell > .au-team__head,
	main > section > .hv-shell > .cr-head--dots,
	/* Other full-bleed bands and strips that meet the rails. They carry the
	   same hairline top/bottom rules but don't share the head--* naming. */
	main > section > .hv-shell > .hv-sechead,
	main > section > .hv-shell > .hv-proof__grid,
	main > section > .hv-shell > .rp-loyalty__head,
	main > section > .hv-shell > .se-engine__feats,
	main > section > .hv-shell > .cp-stack__feats,
	main > section > .hv-shell > .cbv-problem__grid,
	main > section > .hv-shell > .au-stats,
	main > section > .hv-shell > .au-marquee {
		margin-inline: calc(-1 * var(--hv-rail-inset));
		/* Several bands set `width: 100%` or `max-width: min(Npx, 100%)`, which
		   pin them to the parent's content box — the negative margins would
		   then only shift them sideways instead of widening them out to the
		   rails. The shell is already capped, so releasing these is safe: the
		   band ends up exactly rail-to-rail at every width. */
		width: auto;
		max-width: none;
	}
}

/* Nav */
.hv-header {
	position: sticky;
	top: 0;
	z-index: 50;
	background: #0e0e0e;
}
.hv-nav {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding-right: 12px;
	border-bottom: 1px solid rgba(255, 255, 255, 0.2);
}
.hv-nav__left {
	display: flex;
	align-items: stretch;
}
.hv-nav__logo {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 10px 24px;
	border-right: 1px solid rgba(255, 255, 255, 0.2);
}
.hv-nav__logo img {
	width: 178px;
	height: 53px;
	object-fit: contain;
	display: block;
}
.hv-nav__group {
	position: relative;
	display: flex;
	align-items: stretch;
	border-right: 1px solid rgba(255, 255, 255, 0.2);
}
.hv-nav__item {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	padding: 10px 24px;
	border: 0;
	background: transparent;
	color: rgba(255, 255, 255, 0.7);
	font: inherit;
	font-size: 18px;
	line-height: 1.5;
	letter-spacing: -0.18px;
	cursor: pointer;
	white-space: nowrap;
	transition: color 0.15s ease;
}
.hv-nav__item:hover,
.hv-nav__group.is-open .hv-nav__item {
	color: #fff;
}
.hv-nav__chev {
	width: 16px;
	height: 16px;
	display: block;
	transition: transform 0.2s ease;
}
.hv-nav__group.is-open .hv-nav__chev {
	transform: rotate(180deg);
}

/* Mega-menu dropdown */
.hv-nav__menu {
	position: absolute;
	top: 100%;
	left: 0;
	width: 480px;
	background: #0a0a0a;
	border: 1px solid rgba(255, 255, 255, 0.1);
	opacity: 0;
	visibility: hidden;
	transform: translateY(6px);
	transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s;
	z-index: 60;
}
.hv-nav__menu--wide {
	width: 708px;
}
/* Only `.is-open` reveals a menu. The old `:hover` half of this selector opened
   a second dropdown on top of a click-opened one (TQ-3119); hover is handled in
   HvNav.tsx now, so a single piece of state decides what is open. */
.hv-nav__group.is-open .hv-nav__menu {
	opacity: 1;
	visibility: visible;
	transform: translateY(0);
}
.hv-nav__menu-row {
	position: relative;
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 16px 40px 16px 20px;
	border-bottom: 1px solid rgba(255, 255, 255, 0.1);
	text-decoration: none;
	transition: background 0.15s ease;
}
.hv-nav__menu-row:last-child {
	border-bottom: 0;
}
.hv-nav__menu-row:hover {
	background: rgba(255, 255, 255, 0.05);
}
.hv-nav__menu-row:hover .hv-nav__menu-title,
.hv-nav__menu-row:hover .hv-nav__menu-desc {
	color: #2ad9c4;
}
.hv-nav__menu-copy {
	flex: 1 0 0;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.hv-nav__menu-title {
	font-size: 20px;
	line-height: 1.1;
	letter-spacing: -0.4px;
	color: #fff;
}
.hv-nav__menu-desc {
	font-size: 16px;
	line-height: 1.4;
	letter-spacing: -0.16px;
	color: rgba(255, 255, 255, 0.4);
}
.hv-nav__menu-arrow {
	width: 16px;
	height: 16px;
	flex-shrink: 0;
	color: rgba(255, 255, 255, 0.4);
	display: block;
	transition: color 0.15s ease;
}
.hv-nav__menu-row:hover .hv-nav__menu-arrow {
	color: #2ad9c4;
}
.hv-nav__cta {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	height: 56px;
	padding: 12px 24px;
	background: #2ad9c4;
	color: #0a0a0a;
	font-size: 16px;
	line-height: 1.5;
	letter-spacing: -0.16px;
	font-weight: 500;
	text-decoration: none;
	white-space: nowrap;
	transition: opacity 0.15s ease;
}
.hv-nav__cta:hover {
	opacity: 0.9;
}
.hv-nav__burger {
	display: none;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 5px;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	background: transparent;
	cursor: pointer;
}
.hv-nav__burger span {
	display: block;
	width: 22px;
	height: 2px;
	background: #fff;
	transition: transform 0.2s ease, opacity 0.2s ease;
}
.hv-nav__burger.is-open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.hv-nav__burger.is-open span:nth-child(2) { opacity: 0; }
.hv-nav__burger.is-open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
.hv-nav__mobile {
	display: none;
	/* Overlay the page content instead of pushing it down: hang below the nav
	   bar, positioned against the sticky .hv-header. */
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	z-index: 40;
	background: #0e0e0e;
	/* The panel opens and closes by animating a single grid row from 0fr to
	   1fr. That interpolates to the content's real height, so no max-height
	   guess is needed and the close is as smooth as the open — `hidden`, which
	   this used before, cannot transition at all. The border is held until the
	   panel is open, otherwise a hairline sits under the closed bar. */
	grid-template-rows: 0fr;
	border-bottom: 1px solid transparent;
	transition: grid-template-rows 0.38s cubic-bezier(0.22, 0.61, 0.36, 1), border-bottom-color 0.38s ease;
}
.hv-nav__mobile.is-open {
	grid-template-rows: 1fr;
	border-bottom-color: rgba(255, 255, 255, 0.2);
}
/* min-height:0 lets the row actually collapse; the scroller lives here so the
   panel can still overflow on short screens. */
.hv-nav__mobile-inner {
	min-height: 0;
	overflow-y: auto;
	overflow-x: hidden;
	max-height: calc(100vh - 56px);
	-webkit-overflow-scrolling: touch;
}
.hv-nav__macc {
	border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.hv-nav__macc-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	padding: 22px 24px;
	background: none;
	border: 0;
	font-family: inherit;
	font-size: 18px;
	text-align: left;
	color: #fff;
	cursor: pointer;
}
.hv-nav__macc-chev {
	width: 20px;
	height: 20px;
	flex: none;
	/* inline svg now, so it takes its colour from the row */
	color: rgba(255, 255, 255, 0.5);
	transition: transform 0.28s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.hv-nav__macc-head[aria-expanded="true"] .hv-nav__macc-chev {
	transform: rotate(180deg);
}
/* Same 0fr -> 1fr collapse as the panel. <details> was used here before and
   cannot animate its body, so each group snapped open. */
.hv-nav__macc-body {
	display: grid;
	grid-template-rows: 0fr;
	transition: grid-template-rows 0.34s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.hv-nav__macc-body.is-open { grid-template-rows: 1fr; }
.hv-nav__macc-inner { min-height: 0; overflow: hidden; }
@media (prefers-reduced-motion: reduce) {
	.hv-nav__mobile,
	.hv-nav__macc-body,
	.hv-nav__macc-chev { transition: none; }
}
.hv-nav__mrow {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 12px 24px;
	border-top: 1px solid rgba(255, 255, 255, 0.06);
	text-decoration: none;
}
.hv-nav__mrow-copy {
	flex: 1 0 0;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 4px;
}
.hv-nav__mrow-title {
	font-size: 16px;
	color: #fff;
}
.hv-nav__mrow-desc {
	font-size: 13px;
	color: rgba(255, 255, 255, 0.4);
}
.hv-nav__mrow-arrow {
	flex-shrink: 0;
	color: rgba(255, 255, 255, 0.4);
}
.hv-nav__mrow:active .hv-nav__mrow-title,
.hv-nav__mrow:active .hv-nav__mrow-desc,
.hv-nav__mrow:active .hv-nav__mrow-arrow {
	color: #2ad9c4;
}
.hv-nav__mobile-foot {
	padding: 24px;
}
.hv-nav__mobile-cta {
	display: block;
	padding: 15px;
	background: #2ad9c4;
	color: #0a0a0a !important;
	text-align: center;
	font-weight: 500;
	text-decoration: none;
}

/* Hero (placeholder region until the video asset is provided) */
.hv-hero {
	position: relative;
	background: #0e0e0e;
	padding-bottom: 100px;
}
.hv-hero__video {
	width: 100%;
	overflow: hidden;
	line-height: 0;
}
.hv-hero__video video {
	width: 100%;
	height: auto;
	display: block;
}

/* Mobile */
/* The desktop nav needs ~1120px: at 1024 the Platform panel (708px) ends at
   1044 and the Resources panel (480px) at 1089, past the 924px content edge —
   and because the closed panels are visibility:hidden they still occupy layout,
   so every page picked up ~50px of horizontal scroll. Use the mobile nav until
   there is room for the dropdowns. Only the nav switches here; the shell
   padding and frame rails keep their own 1023px breakpoint below. */
@media (min-width: 1024px) and (max-width: 1119px) {
	.hv-nav__group,
	.hv-nav__cta {
		display: none;
	}
	.hv-nav__logo {
		padding-left: 0;
		border-right: 0;
	}
	.hv-nav__burger {
		display: flex;
	}
	.hv-nav__mobile {
		display: grid;
	}
}

@media (max-width: 1023px) {
	.hv-shell {
		padding-inline: 20px;
	}
	/* frame lines are a desktop-only detail — hidden on mobile */
	.hv-header::before,  .hv-header::after,
	main > section::before, main > section::after,
	.hv-footer::before,  .hv-footer::after { display: none; }
	.hv-nav__group,
	.hv-nav__cta {
		display: none;
	}
	.hv-nav__logo {
		padding-left: 0;
		border-right: 0;
	}
	.hv-nav__logo img {
		width: 148px;
		height: 44px;
	}
	.hv-nav__burger {
		display: flex;
	}
	.hv-nav__mobile {
		display: grid;
	}
	.hv-hero {
		display: flex;
		align-items: center;
		min-height: 60vh;
		padding: 24px 0 48px;
	}
	.hv-hero .hv-shell {
		padding-inline: 10px;
		width: 100%;
	}
	.hv-proof__handle {
		display: none;
	}
	.hv-proof {
		padding: 56px 0;
	}
	.hv-platform {
		padding-bottom: 64px;
	}
	.hv-impact {
		padding-bottom: 80px;
	}
	.hv-sechead {
		padding: 40px 16px 40px;
	}
	/* light sections start flush against the dark section above — add top space so the header's top border shows.
	   Not .hv-adv: its mobile frame (87:43008) also opens with the dotted band at y=0, i.e. genuinely flush. */
	.hv-cases { padding-top: 24px; }
}

/* Social proof */
.hv-proof {
	padding: 140px 0;
	background: #0e0e0e;
}
.hv-proof__grid {
	position: relative;
	width: 100%;
	max-width: min(1719px, 100%);
	margin-inline: auto;
	display: flex;
	flex-direction: column;
}
.hv-proof__head {
	height: 268px;
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	padding: 24px 40px;
	border-top: 1px solid rgba(255, 255, 255, 0.2);
	border-bottom: 1px solid rgba(255, 255, 255, 0.2);
	overflow: hidden;
	/* Dots come from <BackgroundPattern> (components/BackgroundPattern.tsx),
	   which draws the grid on a canvas rather than loading dot-grid.png.
	   isolation + the canvas's z-index:-1 keep it under the header's own text. */
	position: relative;
	isolation: isolate;
}
.hv-proof__head h2 {
	margin: 0;
	font-size: 36px;
	line-height: 1.5;
	letter-spacing: -0.72px;
	font-weight: 500;
	color: #fff;
}
.hv-proof__stats {
	position: relative;
	display: flex;
	align-items: stretch;
}
.hv-proof__stat {
	flex: 1 0 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 24px;
	padding: 40px;
}
.hv-proof__stat-num {
	margin: 0;
	font-size: 92px;
	line-height: 1;
	letter-spacing: -1.86px;
	font-weight: 500;
	color: #fff;
}
.hv-proof__stat-label {
	margin: 0;
	font-size: 24px;
	line-height: 1.5;
	letter-spacing: -0.48px;
	color: #fff;
}
.hv-proof__vdiv {
	width: 1px;
	background: rgba(255, 255, 255, 0.2);
	align-self: stretch;
}
/* stat-box corner + divider square markers (Figma 87:13267) */
.hv-proof__sq {
	position: absolute;
	width: 16px;
	height: 16px;
	background: #2a2a2b;
	border: 1px solid #414141;
	border-radius: 2px;
	/* above the content-edge frame lines (z-index 4) so the marker covers them cleanly */
	z-index: 5;
}
.hv-proof__sq--tl { top: -8px; left: -8px; }
.hv-proof__sq--tr { top: -8px; right: -8px; }
.hv-proof__sq--bl { bottom: -8px; left: -8px; }
.hv-proof__sq--br { bottom: -8px; right: -8px; }
/* desktop: middle squares sit on the vertical 8.5M+/20M+ divider (top & bottom) */
.hv-proof__sq--tm { top: -8px; left: 50%; transform: translateX(-50%); }
.hv-proof__sq--bm { bottom: -8px; left: 50%; transform: translateX(-50%); }
/* middle-of-edge squares are for the mobile stacked layout only */
.hv-proof__sq--ml,
.hv-proof__sq--mr { display: none; }
.hv-proof__logos {
	position: relative;
	height: 166px;
	display: flex;
	align-items: center;
	border-top: 1px solid rgba(255, 255, 255, 0.2);
	border-bottom: 1px solid rgba(255, 255, 255, 0.2);
	overflow: hidden;
	/* The clip is a containment boundary, so the moving row can't invalidate
	   anything outside it and the edge gradients stay rasterised. */
	contain: paint;
	/* Opaque, and the same colour the section already showed through this box, so
	   the strip is visually unchanged. It matters because the row inside is a
	   composited layer that stops on a half-pixel: see .hv-marquee. */
	background: #0e0e0e;
}
/* The end fades. These used to be two gradient overlays painted on top of the
   moving row; the row then had a hard edge where the band clipped it, and that
   edge flashed a thin white line on phones — a composited layer whose offset is
   fractional (see .hv-marquee) resamples its edge column, and the logos are
   white. As a mask there is no overlay above the row and no hard edge below it:
   the row's own pixels are already fully transparent when they reach the band, so
   there is nothing at the boundary that can fringe. Same 160px ramp as before. */
.hv-marquee__mask {
	--hv-fade: 160px;
	flex: none;
	width: 100%;
	overflow: hidden;
	/* The 2px transparent hold at each end is the part that matters. With the ramp
	   starting at 0 the zero-alpha stop lands on the boundary pixel itself, and the
	   compositor rounds a fractional mask position one way — on the left, where the
	   logos exit, that left a column of not-quite-zero alpha, so an exiting mark
	   bled a hairline through it. Holding full transparency for 2px means the
	   boundary column is unambiguously alpha 0 whichever way it rounds. */
	-webkit-mask-image: linear-gradient(
		90deg,
		transparent 0,
		transparent 2px,
		#000 var(--hv-fade),
		#000 calc(100% - var(--hv-fade)),
		transparent calc(100% - 2px),
		transparent 100%
	);
	mask-image: linear-gradient(
		90deg,
		transparent 0,
		transparent 2px,
		#000 var(--hv-fade),
		#000 calc(100% - var(--hv-fade)),
		transparent calc(100% - 2px),
		transparent 100%
	);
}
.hv-marquee {
	/* One source for the rhythm: the gap between logos and the half-gap of
	   padding that ends each set. They have to stay in lockstep or the seam
	   where the loop wraps reads as a wider gap than the rest of the row. */
	--hv-logo-gap: 72px;
	display: flex;
	width: max-content;
	/* Never shrink. Chrome's automatic minimum size holds a nested flex container
	   at its content width, but Safari lets it drop below — the two sets were
	   squeezed into the 1210px rail and the logos landed on top of each other. */
	flex: none;
	animation: hv-scroll 45s linear infinite;
	/* Hold the layer for the whole loop — see the keyframes note. */
	will-change: transform;
	backface-visibility: hidden;
	/* Was on each img — see the note there. Identical to look at: every mark is
	   still at 90%, and the row's own #0e0e0e over the band's #0e0e0e is a no-op. */
	opacity: 0.9;
	/* The white flash at both ends of the strip.
	   The logos are intrinsically sized (93.594px, 136.984px, …), so one set is
	   1487.766px and the loop's `-50%` is a fractional offset — the layer sits on
	   a half device pixel for most of the 45s. A transparent layer resampled at a
	   half pixel blends its edge column against nothing, so wherever a white logo
	   pixel met the clip boundary it fringed into a bright 1px line that flickered
	   as the offset crossed each half pixel. Giving the layer the section's own
	   colour makes that edge column resample #0e0e0e against #0e0e0e: identical to
	   look at, but there is no longer any transparency for the fringe to form in.
	   The row is 2975px inside a 353px clip, so this paint is never visible. */
	background: #0e0e0e;
}
.hv-marquee:hover { animation-play-state: paused; }
.hv-marquee__set {
	display: flex;
	align-items: center;
	flex: none;
	gap: var(--hv-logo-gap);
	margin: 0;
	padding: 0 calc(var(--hv-logo-gap) / 2);
	list-style: none;
}
.hv-marquee__set li {
	/* Sized by the logo rather than a fixed slot: equal slots made the *visible*
	   gap depend on how wide each mark happened to be (54px beside a wide
	   wordmark, 152px beside a narrow one). Auto width + one gap reads even. */
	flex: none;
	display: flex;
	align-items: center;
}
.hv-marquee__set img {
	/* normalise on height so every mark reads at the same weight; the cap keeps
	   an unusually wide wordmark from running away with the row */
	height: 44px;
	width: auto;
	max-width: 200px;
	object-fit: contain;
	/* The 0.9 lives on .hv-marquee, not here: per-image opacity made 22 separate
	   composited groups inside the masked row, and each group's bounds round to
	   whole device pixels independently of the mask. On the exit side that let a
	   sliver of a group escape the mask. One group for the whole row cannot. */
}
/* translate3d, not translateX: it puts the row on its own compositor layer, so a
   frame is a layer offset instead of a repaint of the whole clipped strip plus
   the two gradient overlays on top of it. Without that, phones tore the logos
   into horizontal white streaks at both ends of the row. */
@keyframes hv-scroll {
	from { transform: translate3d(0, 0, 0); }
	/* --hv-shift is one set's width snapped to a whole device pixel, set by
	   components/home/LogoMarquee.tsx; the 50% fallback is the old value, used
	   until the measurement lands. A fractional distance left the composited row
	   parked on a fraction of a device pixel, and whether that resampled into a
	   visible hairline at the band's edge depended on the screen's pixel ratio. */
	to { transform: translate3d(calc(-1 * var(--hv-shift, 50%)), 0, 0); }
}
@media (prefers-reduced-motion: reduce) {
	.hv-marquee { animation: none; }
}
/* decorative corner handles */
.hv-proof__handle {
	position: absolute;
	width: 16px;
	height: 16px;
	background: #2a2a2b;
	border: 1px solid #414141;
	border-radius: 2px;
	/* above the content-edge frame lines (z-index 4) so the marker covers them cleanly */
	z-index: 5;
}
.hv-proof__handle--tl { top: -8px; left: -8px; }
.hv-proof__handle--tr { top: -8px; right: -8px; }
.hv-proof__handle--bl { bottom: -8px; left: -8px; }
.hv-proof__handle--br { bottom: -8px; right: -8px; }

@media (max-width: 1023px) {
	.hv-proof { padding: 64px 0; }
	.hv-proof__grid { gap: 24px; }
	.hv-proof__handle { display: none; }
	.hv-proof__head { height: auto; padding: 32px 16px; }
	.hv-proof__head h2 { font-size: 22px; }
	/* stats: its own bordered box, stacked, with 4 corner + 2 middle squares */
	.hv-proof__stats { position: relative; flex-direction: column; border: 1px solid rgba(255, 255, 255, 0.2); }
	.hv-proof__vdiv { width: auto; height: 1px; }
	.hv-proof__stat { padding: 36px; }
	.hv-proof__stat-num { font-size: 56px; }
	.hv-proof__stat-label { font-size: 16px; }
	/* mobile: stats stack vertically, so the middle squares move to the left/right edges (on the horizontal divider); the vertical-divider squares are hidden */
	.hv-proof__sq { width: 12px; height: 12px; border-width: 2px; }
	.hv-proof__sq--tm, .hv-proof__sq--bm { display: none; }
	.hv-proof__sq--ml { display: block; top: 50%; left: -7px; transform: translateY(-50%); }
	.hv-proof__sq--mr { display: block; top: 50%; right: -7px; transform: translateY(-50%); }
	.hv-proof__sq--tl { top: -7px; left: -7px; }
	.hv-proof__sq--tr { top: -7px; right: -7px; }
	.hv-proof__sq--bl { bottom: -7px; left: -7px; }
	.hv-proof__sq--br { bottom: -7px; right: -7px; }
	.hv-proof__logos { height: 110px; }
	/* Keeps the row 8px off each end of the band. The clip-path that used to sit
	   here as well is gone: the mask is now the only edge treatment, so there is a
	   single composited boundary at each end instead of three stacked ones (clip,
	   containment, mask) that each round to device pixels on their own. */
	.hv-proof__logos { padding-inline: 8px; }
	/* 160px of fade at each end would cover 320px of a 353px strip, leaving one
	   narrow window of full-strength logo in the middle. Narrow enough to still
	   soften the entry, small enough that a mark is readable while it crosses. */
	.hv-marquee__mask { --hv-fade: 48px; }
	.hv-marquee { --hv-logo-gap: 40px; }
	.hv-marquee__set img { height: 30px; max-width: 130px; }
}

/* ---- Reusable section header (eyebrow + title + subtitle on dotted grid) ---- */
.hv-sechead {
	max-width: min(1719px, 100%);
	margin-inline: auto;
	padding: 60px 40px 64px;
	text-align: center;
	border: 1px solid rgba(255, 255, 255, 0.2);
	border-left: 0;
	border-right: 0;
	/* Dots come from <BackgroundPattern> (components/BackgroundPattern.tsx),
	   which draws the grid on a canvas rather than loading dot-grid.png.
	   isolation + the canvas's z-index:-1 keep it under the header's own text. */
	position: relative;
	isolation: isolate;
}
.hv-sechead__eyebrow {
	display: block;
	font-size: 13px;
	letter-spacing: 2px;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.5);
	margin-bottom: 18px;
}
.hv-sechead__title {
	margin: 0 auto 16px;
	max-width: min(900px, 100%);
	font-size: 40px;
	line-height: 1.2;
	letter-spacing: -0.9px;
	font-weight: 500;
	color: #fff;
}
.hv-sechead__sub {
	margin: 0 auto;
	max-width: 640px;
	font-size: 18px;
	line-height: 1.5;
	letter-spacing: -0.18px;
	color: rgba(255, 255, 255, 0.55);
}
/* light variant: same dotted look, dark dots — <BackgroundPattern theme="light" />.
   Stays transparent so the canvas behind the content isn't covered. */
.hv-light .hv-sechead {
	border-color: rgba(0, 0, 0, 0.12);
	background: none;
}
.hv-light .hv-sechead__eyebrow { color: rgba(0, 0, 0, 0.45); }
.hv-light .hv-sechead__title { color: #0a0a0a; }
.hv-light .hv-sechead__sub { color: rgba(0, 0, 0, 0.55); }

/* Breathing room above and below every dotted-background section header, on all
   pages: the home `.hv-sechead` band and the product-page `*-head--dots` /
   `*-head--dots-dk` bands (e.g. rewards-plus "Programmable Rewards Logic"). */
.hv-sechead,
main > section [class*="-head--dots"] {
	margin-top: 64px;
	margin-bottom: 64px;
}
@media (max-width: 1023px) {
	.hv-sechead,
	main > section [class*="-head--dots"] {
		margin-top: 36px;
		margin-bottom: 36px;
	}
}

.hv-media-ph {
	display: flex;
	align-items: center;
	justify-content: center;
	border: 1px dashed rgba(255, 255, 255, 0.14);
	border-radius: 12px;
	color: rgba(255, 255, 255, 0.3);
	font-size: 12px;
	letter-spacing: 0.4px;
	text-transform: uppercase;
	min-height: 200px;
}
.hv-tag {
	display: inline-block;
	padding: 4px 10px;
	border-radius: 6px;
	background: rgba(42, 217, 196, 0.12);
	color: #2ad9c4;
	font-size: 12px;
	letter-spacing: 1.2px;
	text-transform: uppercase;
}

/* ---- 3. Platform (bento) ---- */
/* flow-root for the same reason the light sections have it: .hv-sechead carries
   a 64px top margin and this section has no top padding or border, so the margin
   collapsed out of it and opened a 64px gap above the "Platform" header. The gap
   showed #hvh-after's curtain background (#04060c) against the section's #0e0e0e
   — a black band under the logo marquee. .hv-impact escapes this only because
   its `overflow: hidden` (for the glow) already makes a block formatting context. */
.hv-platform { background: #0e0e0e; padding-bottom: 120px; display: flow-root; }
/* Bento geometry, straight off Figma 87:13350 (1600-wide content column inside
   the 1920 frame): two rows of 1600x520 with 24px gaps, row 1 split 620/956 and
   row 2 split 520/516/516. The 60px rail inset already comes from .hv-shell, so
   these must NOT subtract it again — doing that made the column 1480 instead of
   1600, which shrank every card and pushed the titles onto a second line right
   where the animation art starts.

   Height is width-proportional (aspect-ratio) rather than a fixed min-height so
   the cards stay at the Figma 620x520 / 956x520 shape at every desktop width;
   the min-height is only a floor for narrow desktops, where a proportional card
   would get shorter than the (fixed-px) title block needs. */
.hv-bento {
	width: 100%;
	margin: 48px auto 0;
	display: grid;
	grid-template-columns: 620fr 956fr;
	gap: 24px;
	aspect-ratio: 1600 / 520;
	min-height: 430px;
}
/* Radius and background colour are Figma 87:13352 (`rounded-[28px]`, `#131313`).
   The 28 is not cosmetic: card-bg.png is a 620x520 export of that same frame with
   the 28px corner baked in and flat #444 filling the area outside the curve, so
   clipping at 20px let a ~4px band of that grey show as a bright crescent on
   every corner. Any change here has to stay in step with the asset's own radius. */
.hv-bento__card {
	position: relative;
	overflow: hidden;
	border: 1px solid rgba(255, 255, 255, 0.12);
	border-radius: 28px;
	background: #131313 url("../img/home-v2/card-bg.webp") center / cover no-repeat;
	min-height: 430px;
}
/* The animation spans the card's full width at its OWN aspect ratio, anchored to
   the card's bottom edge — never stretched or cropped to the card's height.
   `height: 100%` + `object-fit: cover` did stretch it: four of the five assets
   were exported 430 tall against a 520-tall Figma card (the empty headroom band
   above the artwork is cropped out of the file), and Smart Engage is a full
   956x520 card export. Filling a shorter card with `cover` scaled them up and
   cut that headroom off the top, so the artwork climbed into the title.
   Letting each asset keep its own height puts the headroom back as bare card
   background — which is exactly what Figma has above the art (87:13352: text
   block ends at y=105, artwork starts at y=174). */
.hv-bento__anim {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	width: 100%;
	height: auto;
	z-index: 1;
}
/* legibility gradient behind the title */
.hv-bento__card::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: 55%;
	background: linear-gradient(to bottom, rgba(10, 10, 10, 0.85) 0%, rgba(10, 10, 10, 0) 100%);
	z-index: 2;
	pointer-events: none;
}
/* Figma 87:13357: text block inset 24px, tag -> title gap 12px, title spans the
   full content width (572 in a 620 card). */
.hv-bento__head {
	position: relative;
	z-index: 3;
	padding: 24px;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 12px;
}
.hv-bento__title {
	margin: 0;
	font-size: 28px;
	line-height: normal;
	letter-spacing: -0.56px;
	font-weight: 500;
	color: #fff;
	/* Narrow bento cells: break a long word rather than let it spill out. */
	overflow-wrap: anywhere;
}
.hv-bento__row2 {
	width: 100%;
	margin: 24px auto 0;
	display: grid;
	grid-template-columns: 520fr 516fr 516fr;
	gap: 24px;
	aspect-ratio: 1600 / 520;
	min-height: 430px;
}

/* ---- 4. Business Impact ---- */
/* Figma 87:14187 leaves 400px between the cards and the section foot; at 240px
   the glow had nowhere to go but up behind the cards (TQ-3128). */
.hv-impact { background: #0e0e0e; padding-bottom: 400px; position: relative; }
.hv-impact__cards {
	/* content inset 60px from the frame lines (Figma) while the header above stays flush */
	width: calc(100% - 120px);
	max-width: min(1719px, 100%);
	margin: 48px auto 0;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 24px;
	position: relative;
	z-index: 1;
}
.hv-impact__card {
	position: relative;
	overflow: hidden;
	/* No stroke: Figma 87:14201 draws the card as a flat #131313 fill with no
	   border — sampled along its edge the export is a uniform (19,19,19). The
	   1px rgba(255,255,255,0.1) that used to be here rendered as a visible
	   lighter line tracing the rounded corners, which is what the review
	   flagged as an outline that isn't in the design. */
	border-radius: 20px;
	/* The overlay type is sized against this box, not the viewport — see
	   .hv-impact__title. */
	container-type: inline-size;
	/* The animation SVG is only partly opaque, so it needs this backing: made
	   transparent, the section glow shows through it and the card's edges go
	   blotchy (edge-vs-centre delta jumps from ~3 to ~10). */
	background: #131313 url("../img/home-v2/card-bg.webp") center / cover no-repeat;
	aspect-ratio: 507 / 612;
}
/* animation fills the whole card (card matches the SVG's 507x612 aspect, so no crop) */
.hv-impact__anim {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	z-index: 1;
}
/* teal filter gradient at the bottom of the card */
.hv-impact__card::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 42%;
	background: linear-gradient(to top, rgba(42, 217, 196, 0.22) 0%, rgba(42, 217, 196, 0.05) 45%, rgba(42, 217, 196, 0) 100%);
	z-index: 2;
	pointer-events: none;
}
/* title (top) + caption (bottom) overlaid on the animation */
.hv-impact__overlay {
	position: relative;
	z-index: 3;
	height: 100%;
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	/* 36/28 against the 467px card the design draws at 1920. */
	padding: 7.709cqw 5.996cqw;
	text-align: center;
}
/* Sized in cqw against the card, not in fixed px. The card keeps a 507/612 box
   whatever the column width, so fixed type meant the caption took 16% of the
   card at 1920 but 35-44% at 1280 — which is what pushed it onto the chart line
   and the coin pile and forced the grid to two columns between 1024 and 1439.
   Scaling with the card holds the design's proportion at every width, so three
   columns work the whole way down. The clamps keep 1920 identical and stop the
   text going unreadable at the narrow end. */
.hv-impact__title { margin: 0; font-size: clamp(13px, 4.71cqw, 22px); font-weight: 500; color: #fff; letter-spacing: -0.3px; }
.hv-impact__cap { margin: 0; font-size: clamp(12px, 4.283cqw, 20px); line-height: 1.4; color: #fff; letter-spacing: -0.3px; }
.hv-impact { overflow: hidden; }
/* Reusable section glow arc — drop <img class="hv-section-glow" src=".../section-glow.webp">
   into any position:relative; overflow:hidden section to get the teal glow at its bottom. */
.hv-section-glow {
	position: absolute;
	left: 50%;
	bottom: 0;
	transform: translateX(-50%);
	width: 100%;
	height: auto;
	pointer-events: none;
	user-select: none;
	z-index: 0;
}
.hv-section-glow--desktop { min-width: 1100px; }
/* Business Impact (TQ-3128): the arc used to be forced taller than its artwork,
   which pushed it up behind the cards and pooled light behind the middle one.
   It now renders at its natural 1920x766 — no forced height, no crop — and the
   section's own foot decides how much of it clears the content. */
.hv-section-glow--mobile { display: none; }
/* These four sections used to force the arc to 760px to "show more of it",
   which pushed it 560-640px up behind their own copy — the same fault the home
   page had, and it dropped the body text there to 1.9-3.1:1 contrast. They now
   use the geometry measured off Figma 87:14188: the arc clears the content by
   266px and the section leaves 400px beneath it. */
@media (min-width: 1024px) {
	.en-how .hv-section-glow--desktop,
	.oiq-steps .hv-section-glow--desktop,
	.rp-orch .hv-section-glow--desktop,
	.cp-stack .hv-section-glow--desktop {
		/* NO crop. The arc is an ellipse whose curved edge lives entirely in the
		   top 40% of the artwork — it is still narrowing at 40% down (spans
		   x 16..1904 of 1920). Constraining the box and using object-fit: cover
		   clipped that away and left the widest part, which reads as a flat
		   rectangle rather than a dome. The image now renders at its natural
		   1920x766 so the curve is intact and continues past the section foot. */
		height: auto;
	}
}

/* ---- 5. Advantage + Compliance (light) ---- */
.hv-adv { background: #f6f6f6; color: #0a0a0a; padding: 0 0 160px; }
/* Figma 87:27869 opens with its dotted header band as the first child at y=0:
   the light section butts straight up against the dark section above it, with no
   band of #f6f6f6 in between. The shared `.hv-sechead` 64px top margin (36 on
   mobile) opened exactly that gap, so it comes off here. */
.hv-adv > .hv-shell > .hv-sechead { margin-top: 0; }
.hv-adv__rows { width: calc(100% - 120px); max-width: min(1719px, 100%); margin: 72px auto 0; display: flex; flex-direction: column; gap: 40px; position: relative; }
/* Dashed guide rail down the left of the numbered labels (Figma 87:27869),
   plus the highlight that fills it as the rows scroll past — the behaviour the
   mobile layout already had and desktop did not (it applied .is-active and then
   consumed it nowhere but the label colour).

   Both are repeating gradients rather than `border-left: dashed`, and both
   start at the same 24px origin, so their dashes stay in lockstep as the
   highlight grows. Chrome renders a 1px dashed border as 3-on/2-off, so the
   resting rail is unchanged. */
.hv-adv__rows::before,
.hv-adv__rows::after {
	content: "";
	position: absolute;
	left: 0;
	top: 24px;
	width: 1px;
}
.hv-adv__rows::before {
	bottom: 24px;
	background: repeating-linear-gradient(to bottom, rgba(0,0,0,0.28) 0 3px, transparent 3px 5px);
}
.hv-adv__rows::after {
	height: clamp(0px, calc(var(--adv-progress, 0px) - 24px), calc(100% - 48px));
	background: repeating-linear-gradient(to bottom, rgba(0,0,0,0.85) 0 3px, transparent 3px 5px);
	transition: height 0.45s ease;
}
@media (prefers-reduced-motion: reduce) { .hv-adv__rows::after { transition: none; } }
.hv-adv__row {
	display: grid;
	grid-template-columns: 220px 1fr 1fr;
	/* stretch, NOT center. The two cells are drawn as one bordered box (the
	   second drops its left border), so they have to be the same height. With
	   `center` each cell was only as tall as its own content and floated
	   independently: as soon as one title wrapped to two lines and the other
	   did not — "Plug-and-Play Integration" vs "No-Code Configuration" between
	   roughly 1120 and 1200 — the pair measured 226px vs 196px with a 15px
	   vertical offset, and the shared border visibly stepped. Invisible at 1920
	   only because every title fits on one line there. */
	align-items: stretch;
}
.hv-adv__label {
	padding: 40px 24px;
	/* The label keeps its old centring; only the cells needed to stretch. */
	align-self: center;
	font-size: 18px;
	font-weight: 600;
	color: #0a0a0a;
	transition: color 0.3s ease;
}
.hv-adv__label--muted { color: rgba(0,0,0,0.4); font-weight: 500; }
/* the two feature cells form one bordered box with corner + middle square markers */
.hv-adv__cell {
	position: relative;
	padding: 40px;
	background: #fff;
	border: 1px solid rgba(0,0,0,0.14);
	display: flex;
	flex-direction: column;
	gap: 48px;
}
.hv-adv__cell + .hv-adv__cell { border-left: 0; }
.hv-adv__icon {
	width: 44px; height: 44px; border-radius: 10px;
	background: #2ad9c4; color: #05201c;
	display: flex; align-items: center; justify-content: center;
}
/* The glyphs are Figma exports (node 87:27869) drawn in #1D403C on the teal
   tile. They replaced Unicode placeholder characters, which is why two of them
   looked identical and one rendered as a colour emoji (TQ-3129). */
.hv-adv__icon img {
	width: 24px;
	height: 24px;
	object-fit: contain;
	display: block;
}
.hv-adv__cell-title { font-size: 20px; font-weight: 500; letter-spacing: -0.3px; }
/* square markers: cell1 pseudo => top-left/bottom-left, cell2 pseudo => top-middle/bottom-middle, cell2 spans => top-right/bottom-right */
.hv-adv__cell::before, .hv-adv__cell::after {
	content: ""; position: absolute; left: -6px; width: 11px; height: 11px;
	background: #e8e8e8; border: 2px solid #cfcfcf; border-radius: 1px; z-index: 2;
}
.hv-adv__cell::before { top: -6px; }
.hv-adv__cell::after { bottom: -6px; }
.hv-adv__csq { display: block; position: absolute; right: -6px; width: 11px; height: 11px; background: #e8e8e8; border: 2px solid #cfcfcf; border-radius: 1px; z-index: 2; }
.hv-adv__csq--tr { top: -6px; }
.hv-adv__csq--br { bottom: -6px; }
/* ---- Compliance strip (Figma 87:27973) ------------------------------------
   Built from the six badge artworks instead of the two exported strip PNGs it
   used to be (one for desktop, one for the 3x2 mobile layout). Everything but
   the logos is CSS, all values off Figma:

     strip   1600 x 324.03, 1px rgba(17,17,17,.1) border, six equal cells
     divider 1.36px rgba(17,17,17,.1) on every cell but the last
     hatch   87:27982 — #111 at 5% opacity, 1.87px lines on a 22.095px vertical
             pitch rotated 30.15deg, on cells 1/3/5. Straight lines with exact
             stroke values, so a gradient rather than an asset: it stays sharp at
             every width, and Figma's own SVG export comes baked to one cell size
             with a #1E1E1E canvas rect behind it.
     marker  87:28229-28242 — 10.85 x 10.92, #e0e0e0 on 1px #c7c7c7, r 2.72,
             centred on each divider where it meets the top and bottom edge
     badge   width is the Figma logo width over the 267.797 cell width; height
             follows the asset's own ratio (each PNG is a 3x export at its node
             size), so nothing is stretched

   The strip's height is width-proportional, so the whole thing keeps its Figma
   shape as the column narrows and the hatch/markers stay put. Figma's
   backdrop-blur on the strip and markers is dropped: nothing sits behind them
   here, so it paints identically and costs a compositing layer. */
.hv-compliance { width: 100%; max-width: min(1719px, 100%); margin: 80px auto 0; text-align: center; }
.hv-compliance__title {
	margin: 0 0 24px;
	font-size: 36px;
	line-height: 1.4;
	letter-spacing: -0.72px;
	font-weight: 500;
	color: #111;
	text-transform: capitalize;
}
/* one line on desktop; emphasised phrases are dark, connectors are dimmed (Figma 87:27976) */
.hv-compliance__sub {
	margin: 0 auto 40px;
	color: #111;
	font-size: 24px;
	line-height: 1.4;
	letter-spacing: -0.48px;
}
/* 0.5 blended to #848484 on the strip's #f6f6f6 — 3.46:1, under the 4.5:1 WCAG AA
   minimum for 16px text and the only genuine contrast failure on the page. 0.6
   lands on ~#6d6d6d for 4.8:1. */
.hv-compliance__sub-dim { color: rgba(17, 17, 17, 0.6); }
.hv-compliance__strip {
	--hv-cmp-hatch-line: 1.87px;
	--hv-cmp-hatch-pitch: 19.1px;
	--hv-cmp-sq: 10.85px;
	--hv-cmp-sq-radius: 2.72px;
	position: relative;
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	aspect-ratio: 1600 / 324.03;
	border: 1px solid rgba(17, 17, 17, 0.1);
}
.hv-compliance__cell {
	position: relative;
	overflow: hidden;
	display: flex;
	align-items: center;
	justify-content: center;
	border-right: 1.36px solid rgba(17, 17, 17, 0.1);
}
/* the six cells come first in the markup, then the markers — hence nth-child */
.hv-compliance__cell:nth-child(6) { border-right: 0; }
.hv-compliance__cell:nth-child(odd)::before {
	content: "";
	position: absolute;
	inset: 0;
	/* 149.85deg = perpendicular to Figma's 30.15deg stroke direction, so the pitch
	   below is the gap measured across the lines rather than down the cell. */
	background-image: repeating-linear-gradient(
		149.85deg,
		rgba(17, 17, 17, 0.05) 0 var(--hv-cmp-hatch-line),
		rgba(17, 17, 17, 0) var(--hv-cmp-hatch-line) var(--hv-cmp-hatch-pitch)
	);
}
.hv-compliance__logo { position: relative; display: block; height: auto; }
.hv-compliance__logo--iso,
.hv-compliance__logo--soc2,
.hv-compliance__logo--sar { width: 51.85%; }
.hv-compliance__logo--pci { width: 58.77%; }
.hv-compliance__logo--spdx { width: 87.67%; }
.hv-compliance__logo--cbom { width: 75.44%; }
.hv-compliance__sq {
	position: absolute;
	width: var(--hv-cmp-sq);
	height: var(--hv-cmp-sq);
	box-sizing: border-box;
	background: #e0e0e0;
	border: 1px solid #c7c7c7;
	border-radius: var(--hv-cmp-sq-radius);
	transform: translate(-50%, -50%);
}
.hv-compliance__sq--top { top: 0; }
.hv-compliance__sq--bottom { top: 100%; }
/* the row divider only exists once the strip breaks into two rows */
.hv-compliance__sq--mid { top: 50%; display: none; }
.hv-compliance__sq--c0 { left: 0; }
.hv-compliance__sq--c1 { left: 16.6667%; }
.hv-compliance__sq--c2 { left: 33.3333%; }
.hv-compliance__sq--c3 { left: 50%; }
.hv-compliance__sq--c4 { left: 66.6667%; }
.hv-compliance__sq--c5 { left: 83.3333%; }
.hv-compliance__sq--c6 { left: 100%; }

/* ---- 6. Case Studies (light) ---- */
.hv-cases { background: #f6f6f6; color: #0a0a0a; padding: 0 0 100px; }
.hv-cases__wrap { width: calc(100% - 120px); max-width: min(1719px, 100%); margin: 48px auto 0; display: flex; align-items: center; gap: 24px; }
/* Same pager mark and sizing as the careers testimonials carousel
   (.cr-tst__arrow): the shared light-grey asset, darkened to sit on this light
   section, and mirrored for the previous button. */
.hv-cases__arrow {
	flex: 0 0 auto; width: 44px; height: 40px; border: 0; background: transparent;
	display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.hv-cases__arrow img {
	width: 100%; height: 100%;
	filter: brightness(0.4);
	transition: filter 0.2s ease;
}
.hv-cases__arrow:hover img { filter: brightness(0.2); }
.hv-cases__arrow--prev img { transform: scaleX(-1); }
/* The pager clamps at both ends instead of looping, so the arrow that can't
   move any further reads as unavailable and stops responding to hover. */
.hv-cases__arrow:disabled { cursor: default; opacity: 0.25; }
.hv-cases__arrow:disabled:hover img { filter: brightness(0.4); }
/* All three slides live in this one grid cell so its height is the tallest of
   them and never changes as you page through — otherwise the arrows, centred
   against it, jump on every click. */
/* The white panel is the stage's, not each card's: the cards cross-fade through
   each other, and two half-transparent panels stacked in the same cell would
   composite lighter than one opaque panel — a flash on every click. One panel
   that never moves, cards that only fade their content. */
.hv-cases__stage {
	flex: 1 1 0; min-width: 0; display: grid;
	background: #fff; border-radius: 20px;
	box-shadow: 0 30px 70px -50px rgba(0,0,0,0.35);
}
.hv-cases__stage > .hv-cases__card { grid-area: 1 / 1; }
/* align-items: stretch, not center. The stage is as tall as the tallest card, so
   centring pushed every card's copy down by half its own slack — up to ~20px of
   vertical drift between slides, which read as the card resizing. Stretched, the
   title starts at the same y on all three; only the empty space below differs. */
.hv-cases__card {
	flex: 1; display: grid; grid-template-columns: 1fr 1fr; gap: 40px;
	padding: 24px; align-items: stretch;
	transition: opacity 0.35s ease, visibility 0.35s;
}
/* Fixed art box: the column width sets it and the ratio sets the height, so all
   three panels occupy exactly the same rectangle no matter what a given export's
   intrinsic size is (they are 800x480 today). object-fit fills it without
   distortion. Centred against the stretched row so it keeps its old position. */
.hv-cases__art {
	position: relative; align-self: center; aspect-ratio: 5 / 3;
	border-radius: 14px; overflow: hidden;
}
.hv-cases__art img { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (prefers-reduced-motion: reduce) {
	.hv-cases__card { transition: none; }
}
.hv-cases__art-label { background: #fff; color: #0a0a0a; font-weight: 600; padding: 6px 12px; }
.hv-cases__title { margin: 0 0 20px; font-size: 26px; font-weight: 500; letter-spacing: -0.4px; }
.hv-cases__list { list-style: none; margin: 0 0 28px; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.hv-cases__list li { color: rgba(0,0,0,0.6); font-size: 15px; }
.hv-cases__list li::before { content: "\2713"; color: #12b39a; margin-right: 8px; }
/* The copy column fills the card and the link is pushed to its bottom edge, so
   "Read Case Study" sits at the same y on all three slides. Otherwise a study
   with a bullet that wraps to two lines pushed its link ~20px lower than the
   others and the only thing that moved on a card change was that link. */
.hv-cases__body { display: flex; flex-direction: column; }
.hv-cases__link {
	color: #0a0a0a; font-weight: 600; text-decoration: underline; font-size: 14px;
	margin-top: auto; align-self: flex-start;
}

/* ---- 7. Closing CTA ---- */
.hv-cta { background: #0e0e0e; padding: 120px 0; }
.hv-cta__banner {
	/* inset from the frame lines + shared CTA background image (same as other pages) */
	width: calc(100% - 120px); max-width: min(1600px, 100%); margin: 0 auto; border-radius: 24px; overflow: hidden;
	min-height: 340px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 24px;
	background: #0a1614 url("../img/home-v2/cta-bg.webp") center / cover no-repeat;
	text-align: center; padding: 60px 24px;
}
.hv-cta__title { margin: 0; font-size: 47px; font-weight: 500; letter-spacing: -1px; color: #fff; }
.hv-cta__title em { font-style: normal; color: #2ad9c4; border: 1px solid rgba(42,217,196,0.5); border-radius: 8px; padding: 0 12px; }
.hv-cta__btn { background: #fff; color: #0a0a0a; padding: 14px 22px; font-weight: 500; text-decoration: none; }

/* ---- 8. Newsletter + Footer  (Figma 87:28298, 1920 frame) ----------------
   Rebuilt to the design for TQ-3122. The reported symptom was the link columns
   starting ~31% across instead of ~65%: they were four equal-ish grid tracks
   (1.3fr 1fr 1fr 1fr), whereas Figma is a two-part row — an 816px brand block
   and a 564px column group pushed to the right edge, 212px apart. Type scale,
   gaps and dividers were off throughout as well, so all of them are restated
   here from the node rather than adjusted by eye.

   Geometry: rails at the 1720 column, content inset 64px inside them -> a
   1592px content width, which is what every width below is measured against. */

/* Sections inset 60px from the rails; Figma gives the footer 64px. Tracks the
   gutter so the footer stays in step with every other section below 1440. */
@media (min-width: 1024px) {
	.hv-footer .hv-shell { padding-inline: calc(var(--hv-gutter) + 64px); }
}

/* --- Newsletter (87:28300) --- */
.hv-news {
	padding: 64px 0;
	border-top: 1px solid rgba(255, 255, 255, 0.2);
	border-bottom: 1px solid rgba(255, 255, 255, 0.2);
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 40px;
	flex-wrap: wrap;
}
.hv-news__title {
	margin: 0;
	/* 664px at the 1920 anchor; scales with the viewport below it so the
	   headline keeps its two lines instead of towering over a narrow column. */
	flex: 0 1 664px;
	font-size: clamp(24px, 2.1vw, 40px);
	font-weight: 500;
	line-height: 1.2;
	letter-spacing: -0.8px;
	color: rgba(255, 255, 255, 0.6);
}
.hv-news__title strong { color: #fff; font-weight: 500; }
.hv-news__side {
	flex: 0 1 523px;
	display: flex;
	flex-direction: column;
	gap: 12px;
}
.hv-news__form { display: flex; align-items: center; gap: 16px; }
.hv-news__input {
	flex: 1 0 0;
	min-width: 0;
	height: 48px;
	padding: 16px 20px;
	background: rgba(255, 255, 255, 0.2);
	border: 1px solid rgba(255, 255, 255, 0.4);
	border-radius: 2px;
	backdrop-filter: blur(36.35px);
	color: #fff;
	font-size: 16px;
	line-height: 1.2;
	letter-spacing: -0.32px;
}
.hv-news__input::placeholder { color: rgba(255, 255, 255, 0.5); font-weight: 300; }
.hv-news__submit {
	flex: none;
	padding: 12px 24px;
	background: #2ad9c4;
	border: 0;
	border-radius: 2px;
	color: #0a0a0a;
	font-size: 16px;
	font-weight: 500;
	line-height: 1.5;
	letter-spacing: -0.16px;
	cursor: pointer;
	transition: opacity 0.15s ease;
}
.hv-news__submit:disabled {
	opacity: 0.45;
	cursor: not-allowed;
}
.hv-news__note {
	display: flex;
	flex-direction: column;
	gap: 8px;
	color: rgba(255, 255, 255, 0.6);
	font-size: 16px;
	line-height: 22px;
	letter-spacing: -0.32px;
}
.hv-news__note p { margin: 0; }
.hv-news__note p:first-child { font-weight: 500; }

.hv-news__notice {
	margin: 8px 0 0;
	font-size: 16px;
	line-height: 22px;
	letter-spacing: -0.32px;
}
.hv-news__notice--ok  { color: #2ad9c4; }
.hv-news__notice--err { color: #ff8f8f; }

.hv-footer {
	background: #0e0e0e;
	position: relative;
	overflow: hidden;
	/* The glow is sized off the footer's own width, the way Figma lays it out. */
	container-type: inline-size;
}
/* The arc runs up behind the columns, so the text needs its own layer. */
.hv-footer .hv-shell { position: relative; z-index: 2; }

/* --- Brand + link columns (87:28311 / 87:28313) --- */
.hv-footer__main {
	/* Figma leaves 56px between the newsletter's bottom rule (y 360) and the
	   block (y 416) before its own 64px padding starts. */
	margin-top: 56px;
	padding: 64px 0 0;
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 40px;
}
.hv-footer__brand {
	flex: 0 1 816px;
	display: flex;
	flex-direction: column;
	gap: 20px;
}
.hv-footer__brand-logo { width: 56px; height: 56px; object-fit: contain; display: block; }
.hv-footer__tagline {
	margin: 0;
	font-size: clamp(24px, 2.1vw, 40px);
	font-weight: 500;
	line-height: 1.2;
	letter-spacing: -0.8px;
	color: #fff;
}
.hv-footer__tagline em { font-style: normal; color: #2ad9c4; }
/* The three columns are one 564px group against the right edge, spread apart —
   NOT three tracks of a page-wide grid. This is the reported defect. */
.hv-footer__cols {
	flex: none;
	width: 564px;
	display: flex;
	justify-content: space-between;
}
.hv-footer__col { width: 118px; display: flex; flex-direction: column; gap: 16px; }
/* h3, not h4: the nearest preceding heading is the CTA's h2, so an h4 skipped a
   level and failed axe's heading-order on every page. Purely semantic — the size
   and weight below are unchanged. */
.hv-footer__col h3 {
	margin: 0;
	font-size: 16px;
	font-weight: 500;
	line-height: 22px;
	letter-spacing: -0.32px;
	color: rgba(255, 255, 255, 0.6);
}
.hv-footer__col ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 16px;
}
.hv-footer__col a {
	color: #fff;
	text-decoration: none;
	font-size: 18px;
	line-height: 22px;
	letter-spacing: -0.36px;
	/* Figma marks the long labels nowrap and lets them run past the 118px
	   column ("Product Updates" is 130, the Cerebra links 135). Wrapping them
	   instead broke the 38px row rhythm the whole column is built on. */
	white-space: nowrap;
	/* Block, so the row is the link's own 22px and not the 24px line-height the
	   <li> inherits from the body — that alone stretched every step to 40px. */
	display: block;
}
.hv-footer__col a:hover { color: #2ad9c4; }
/* Cerebra's two comparison links: smaller and dimmer, and nested under the
   Cerebra entry with a turn-down arrow, 8px apart rather than 16px. */
.hv-footer__sub {
	position: relative;
	padding-left: 20px;
	font-size: 14px !important;
	line-height: 17px !important;
	letter-spacing: -0.28px !important;
	color: rgba(255, 255, 255, 0.5) !important;
}
.hv-footer__sub::before {
	content: "\21B3";
	position: absolute;
	left: 2px;
	top: 0;
	color: rgba(255, 255, 255, 0.4);
}
.hv-footer__col li:has(> .hv-footer__sub) { margin-top: -8px; }

/* --- Badges + socials (87:28346). No divider above it in Figma; the rule sits
       under the whole block instead. --- */
.hv-footer__strip {
	margin-top: 40px;
	padding: 0 0 64px;
	border-bottom: 1px solid rgba(255, 255, 255, 0.2);
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 20px;
}
.hv-footer__badges img { height: 46px; width: auto; display: block; }
.hv-footer__social { display: flex; gap: 12px; align-items: center; }
.hv-footer__social span {
	color: rgba(255, 255, 255, 0.6);
	font-size: 16px;
	font-weight: 500;
	line-height: 22px;
	letter-spacing: -0.32px;
}
.hv-footer__social a { display: inline-flex; }
.hv-footer__social img { width: 32px; height: 32px; display: block; }

/* --- Copyright + wordmark (87:28400) --- */
.hv-footer__glow {
	position: relative;
	/* 56px from the block's bottom rule (design y 930) to the copyright rule
	   (design y 986). */
	margin-top: 56px;
	padding-top: 0;
	padding-bottom: 0;
	/* NOT hidden: the arc is 1199 tall against a 1920 frame and Figma starts it
	   at y 522, i.e. up behind the link columns where it is still black. Clipping
	   it to this box instead showed the middle of the gradient at the box's top
	   edge, which is the hard line across the glow. */
	overflow: visible;
	display: flex;
	flex-direction: column;
	/* Copyright + wordmark travel together at the foot of the arc; any spare
	   height in the section opens up above them, not between them. */
	justify-content: flex-end;
	/* How far the wordmark's baseline sits above the page edge. */
	padding-bottom: 5cqw;
}
@media (min-width: 1024px) {
	/* Copyright rule (986) down to the arc's foot, over a 1920 frame. Enough
	   height that the arc's top lands up in the black region behind the block. */
	.hv-footer__glow { min-height: 38.28cqw; }
}
.hv-footer__glow-bg {
	position: absolute;
	left: 50%;
	/* Sat on the page's bottom edge. Figma ends the arc 236px higher, but the SVG
	   is a crop of the artwork — lifting it that far exposes the crop as a second
	   hard edge, so the cut is parked off the bottom of the page instead. */
	bottom: 0;
	top: auto;
	transform: translateX(-50%);
	width: 100%;
	height: auto;
	pointer-events: none;
	user-select: none;
	z-index: 0;
}
.hv-footer__bottom {
	position: relative;
	z-index: 2;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 12px;
	/* Figma draws a 1678px rule here (design y 986), but it reads as a hard edge
	   sitting on top of the glow, so it is dropped by request. The 80px it stood
	   off the copyright is kept as plain spacing. */
	width: min(1678px, 100%);
	margin-inline: auto;
	padding-top: 80px;
}
.hv-footer__copy {
	display: flex;
	align-items: flex-start;
	gap: 6px;
	color: rgba(255, 255, 255, 0.5);
	font-size: 16px;
	line-height: 20px;
}
.hv-footer__copy-mark { font-size: 20px; line-height: 20px; }
.hv-footer__bottom-links {
	display: flex;
	align-items: center;
	gap: 8px;
	color: #fff;
	font-size: 18px;
	line-height: 1.2;
	letter-spacing: -0.36px;
}
.hv-footer__bottom-links a {
	color: #fff;
	text-decoration: underline;
	text-underline-position: from-font;
}
/* The footer's divider rules run the full width of the rail column, not the
   padded content column. In Figma the newsletter (87:28300) and the block above
   the footer (87:28311) are both 1720 wide — exactly rail to rail — and only
   their CONTENTS sit 64px in. Taking that inset from .hv-shell's padding applied
   it to the borders too, so every rule stopped 64px short of the vertical lines.

   Pulling the border box back out by 64px and restoring it as padding lands the
   rule ends on the rails while leaving the content where it was.

   This must sit AFTER the .hv-news / .hv-footer__strip rules above: both set
   `padding` with the shorthand, which would otherwise reset the inline padding
   and drag the content out to the rails along with the border.

   The copyright rule is deliberately excluded — Figma insets that one to 1678
   (21px inside each rail). */
@media (min-width: 1024px) {
	.hv-footer .hv-news,
	.hv-footer .hv-footer__strip {
		margin-inline: -64px;
		padding-inline: 64px;
	}
}

.hv-footer__wordmark {
	position: relative;
	z-index: 1;
	display: block;
	/* 1678 of the 1720 column — 21px inside each rail (TQ-3123). The percentage
	   has to be taken against the RAIL COLUMN, not the footer: the wordmark sits
	   outside .hv-shell, so sizing it against the full footer width let it run
	   up to 88px past both rails on anything under ~1920px. The rails sit at
	   max(100px, (100% - 1720px) / 2), so the column is min(1720px, 100% - 200px). */
	width: calc(min(1720px, 100% - 200px) * 0.97558);
	/* Figma sets 64px between the policy links and the top of the glyphs
	   (design y 1120 -> 1184), so the copyright block reads as a caption sitting
	   directly on the wordmark. 64/1920 of the footer width. */
	margin: 3.33cqw auto 0;
	opacity: 0.5;
	mix-blend-mode: screen;
	pointer-events: none;
	user-select: none;
}

@media (max-width: 1023px) {
	.hv-sechead__title { font-size: 26px; }
	/* Business Impact: reduced bottom space + portrait SVG arc glow (cropped to its light
	   baseline) anchored at the section bottom so it fades into the light section beneath. */
	.hv-impact { padding-bottom: 100px; }
	/* These two belong with the mobile section paddings up in the first
	   max-width:1023 block, but they have to live here: their base rules are
	   declared LATER in this file at the same specificity, and a media query
	   adds none — so the earlier block's `.hv-platform { padding-bottom: 64px }`
	   never applied and both sections kept their desktop 120/160px on phones. */
	.hv-platform { padding-bottom: 64px; }
	.hv-adv { padding-bottom: 72px; }
	.hv-section-glow--desktop { display: none; }
	.hv-section-glow--mobile { display: block; width: 100%; min-width: 0; }
	/* frame lines hidden on mobile -> content uses full width (no desktop inset).
	   Stacked cards are sized by their own min-height, so the desktop
	   width-proportional row height has to come off. */
	.hv-bento, .hv-bento__row2, .hv-impact__cards { grid-template-columns: 1fr; width: 100%; }
	/* Stacked the card is full width, so the cqw ramp would shrink the type on a
	   narrow phone. Pinned back to the sizes this shipped with — the container
	   sizing exists for the three-column desktop grid, not for the stack. */
	.hv-impact__title { font-size: 22px; }
	.hv-impact__cap { font-size: 20px; }
	.hv-bento, .hv-bento__row2 { aspect-ratio: auto; min-height: 0; }
	/* Stacked cards are much narrower than the desktop cells, so the titles run to
	   three lines while the animation keeps its own height — a fixed 430 card can't
	   hold both and the art ends up under the text again. Let the card be as tall
	   as its two parts: title block in flow, animation after it (it precedes the
	   head in the DOM, hence the order swap). */
	.hv-bento__card { display: flex; flex-direction: column; min-height: 0; }
	.hv-bento__anim { position: static; order: 2; margin-top: auto; }
	/* advantages: label full-width, then TWO JOINED cells with corner+middle squares + left rail (Figma 87:43008) */
	.hv-adv__rows { gap: 32px; margin-top: 40px; padding-left: 18px; width: auto; }
	/* Left rail down the groups. This was overridden to a solid line, but the
	   Figma mobile frame (87:43008) keeps it dashed — measured off the frame at
	   ~13px dash / 10px gap. A border can't express that pitch (the browser's
	   own `dashed` on a 1.5px border draws ~4.5px dashes), so it's a repeating
	   gradient on a 1.5px-wide box instead. */
	.hv-adv__rows::before {
		left: 3px;
		top: 6px;
		bottom: 6px;
		border-left: 0;
		width: 1.5px;
		background: repeating-linear-gradient(
			to bottom,
			rgba(0, 0, 0, 0.12) 0 13px,
			transparent 13px 23px
		);
	}
	.hv-adv__row { position: relative; grid-template-columns: 1fr 1fr; column-gap: 0; row-gap: 14px; }
	/* Left-rail active segment (highlights the current group on scroll). It sits
	   at the same x as the rail above, so a solid fill painted straight over the
	   dashes and the rail read as one solid line while scrolling (TQ-3121).
	   Same dash pattern as the rail, faded in rather than swapped, so the line
	   stays dotted at every scroll position. */
	.hv-adv__row::after {
		content: "";
		position: absolute;
		left: -15px;
		top: 2px;
		bottom: 2px;
		width: 2px;
		background: repeating-linear-gradient(
			to bottom,
			#0a0a0a 0 13px,
			transparent 13px 23px
		);
		opacity: 0;
		transition: opacity 0.3s ease;
	}
	.hv-adv__row.is-active::after { opacity: 1; }
	/* mobile highlights per row, so the desktop progress rail is not drawn */
	.hv-adv__rows::after { display: none; }
	.hv-adv__label { grid-column: 1 / -1; padding: 0; font-size: 17px; }
	.hv-adv__cell { padding: 18px; gap: 40px; }
	.hv-adv__icon { width: 40px; height: 40px; }
	.hv-adv__cell-title { font-size: 16px; }
	/* full width on mobile (no desktop inset); subtitle wraps to multiple lines */
	.hv-compliance { width: auto; margin-top: 48px; }
	/* Figma 87:43107: 24/-0.48 over 16/-0.32, 12px apart */
	.hv-compliance__title { font-size: 24px; letter-spacing: -0.48px; margin-bottom: 12px; }
	.hv-compliance__sub { font-size: 16px; letter-spacing: -0.32px; max-width: 320px; }
	/* The same six cells reflow into 3 columns x 2 rows (Figma 87:43110, 353 x
	   282.66). The hatch tile is the desktop one scaled by 351.295/805.392, so its
	   pitch and stroke scale with it; markers drop to 6px and the ones that would
	   land mid-cell drop out, while the row divider's pair comes in. */
	.hv-compliance__strip {
		grid-template-columns: repeat(3, 1fr);
		aspect-ratio: 353 / 282.66;
		--hv-cmp-hatch-line: 0.81px;
		--hv-cmp-hatch-pitch: 8.33px;
		--hv-cmp-sq: 6px;
		--hv-cmp-sq-radius: 1.5px;
	}
	.hv-compliance__cell:nth-child(3n) { border-right: 0; }
	.hv-compliance__cell:nth-child(-n + 3) { border-bottom: 1.36px solid rgba(17, 17, 17, 0.1); }
	.hv-compliance__sq--mid { display: block; }
	.hv-compliance__sq--c1,
	.hv-compliance__sq--c3,
	.hv-compliance__sq--c5 { display: none; }
	/* frame lines hidden on mobile -> content uses full width (no desktop inset) */
	/* card on top, both arrows dropped to a centered row underneath */
	.hv-cases__wrap { flex-flow: row wrap; justify-content: center; align-items: center; width: auto; gap: 16px; }
	.hv-cases__stage { order: 0; flex: 1 1 100%; }
	/* Stacked: art row sized by the image, copy row takes the rest of the stage.
	   Without the explicit rows both rows stretched to share the slack, which
	   moved the image down by a different amount on every slide. */
	.hv-cases__card { order: 0; flex: 1 1 100%; grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
	.hv-cases__art { align-self: start; }
	.hv-cases__arrow { order: 1; width: 34px; height: 30px; }
	/* Section padding was left at the desktop 100/120px, which on a phone is
	   most of a screen of empty black above and below the closing CTA. Matches
	   the 64px rhythm .hv-proof already uses on mobile. */
	.hv-cases { padding-bottom: 56px; }
	.hv-cta { padding: 64px 0; }
	.hv-cta__banner { width: auto; }
	.hv-cta__title { font-size: 30px; }
	/* newsletter (now inside footer) */
	.hv-news { flex-direction: column; align-items: flex-start; padding: 40px 0; gap: 24px; }
	.hv-news__title { flex: 0 1 auto; font-size: 22px; letter-spacing: -0.3px; }
	.hv-news__side { flex: 0 1 auto; width: 100%; }
	.hv-news__form { width: 100%; }
	.hv-news__note { font-size: 13px; line-height: 18px; }
	.hv-footer__main { flex-wrap: wrap; gap: 28px 24px; padding: 48px 0 0; }
	.hv-footer__brand { flex: 1 1 100%; gap: 16px; }
	.hv-footer__tagline { font-size: 20px; letter-spacing: -0.3px; }
	.hv-footer__brand-logo { width: 44px; height: 44px; }
	.hv-footer__cols { flex: 1 1 100%; width: 100%; flex-wrap: wrap; gap: 28px 24px; justify-content: flex-start; }
	.hv-footer__col { width: calc(50% - 12px); gap: 12px; }
	.hv-footer__col a { font-size: 15px; line-height: 20px; }
	.hv-footer__sub { padding-left: 18px; font-size: 13px !important; line-height: 16px !important; }
	.hv-footer__col li:has(> .hv-footer__sub) { margin-top: -6px; }
	.hv-footer__strip { flex-direction: column; align-items: flex-start; gap: 20px; margin-top: 28px; padding: 0 0 28px; }
	.hv-footer__badges img { height: 34px; }
	.hv-footer__bottom { padding-top: 20px; }
	.hv-footer__copy { font-size: 13px; line-height: 16px; }
	.hv-footer__copy-mark { font-size: 16px; line-height: 16px; }
	.hv-footer__bottom-links { font-size: 14px; }
	/* The arc keeps its own aspect (393x356) and is anchored bottom-centre, so
	   the band crops it from the top — that is deliberate, it is what keeps the
	   curve tight under the content. The bug was the band being a FIXED 200px
	   while the artwork scales with width: at 390 it showed the bottom 57% of
	   a 353px arc, but at 900 only the bottom 25% of an 815px one, i.e. the
	   dome flattened out the wider the phone. Making the band track the width
	   (52vw ~= that same 57%) keeps the same crop at every size. The negative
	   margin lifts it under the strip's rule. */
	.hv-footer__glow { margin-top: -16px; min-height: clamp(180px, 52vw, 420px); padding-top: 16px; padding-bottom: 28px; overflow: hidden; justify-content: flex-end; background: url("../img/home-v2/footer/glow-mobile.webp") no-repeat bottom center; background-size: 100% auto; }
	.hv-footer__glow-bg { display: none; }
	.hv-footer__wordmark { width: 92%; margin-top: 16px; }
}

/* Mobile: dotted section headers go edge-to-edge. Use a viewport-based full-bleed
   so it works no matter what the shell gutter is (home uses 20px, product pages
   24px) — a hardcoded negative margin left them lopsided. */
@media (max-width: 1023px) {
	.hv-sechead,
	.hv-proof__head,
	.rp-head--dots, .rp-head--dots-dk, .rp-loyalty__head,
	.se-head--dots, .se-head--dots-dk,
	.cp-head--dots, .cp-head--dots-dk,
	.oiq-head--dots, .oiq-head--dots-dk,
	.en-head--dots, .en-head--dots-dk,
	.cbv-head--dots, .cbv-head--dots-dk {
		width: 100vw !important;
		max-width: 100vw !important;
		margin-left: calc(50% - 50vw) !important;
		margin-right: calc(50% - 50vw) !important;
		padding-left: 24px !important;
		padding-right: 24px !important;
	}
	/* tighter vertical padding on the header text too */
	.hv-sechead { padding-top: 32px !important; padding-bottom: 32px !important; }
}

/* =========================================================================
   FLUID DESKTOP BAND (901-1919) — shared + home-page sections.

   Everything here was frozen at its 1920 value down to 901px, so on a laptop
   the type and section rhythm stayed full-size while the artwork (which is
   width-driven) shrank around it. Max = the 1920 design value, so 1920 and
   above is byte-identical; min = the matching <=1023 mobile value already in
   this file, so the boundary is continuous; coefficient = design/19.2vw.
   Body copy and small UI are deliberately left fixed.

   .hv-impact's 400px foot is NOT scaled: it is the clearance for the natural
   1920x766 .hv-section-glow arc, and the note there records that closing that
   gap pooled light behind the cards and dropped copy to 1.9-3.1:1 contrast.

   .hv-sechead__title is the section heading every V2 page reuses, and no page
   stylesheet redeclares it, so scaling it here reaches all of them.
   ========================================================================= */
@media (min-width: 901px) and (max-width: 1919px) {
	/* Shared section heading */
	.hv-sechead__title { font-size: clamp(26px, 2.083vw, 40px); letter-spacing: -0.0225em; }

	/* Hero + proof */
	.hv-hero { padding-bottom: clamp(56px, 5.208vw, 100px); }
	.hv-proof { padding-block: clamp(56px, 7.292vw, 140px); }
	.hv-proof__head h2 { font-size: clamp(22px, 1.875vw, 36px); letter-spacing: -0.02em; }
	.hv-proof__stat-num { font-size: clamp(56px, 4.792vw, 92px); letter-spacing: -0.0202em; }
	.hv-proof__stat-label { font-size: clamp(16px, 1.25vw, 24px); }
	.hv-marquee { --hv-logo-gap: clamp(40px, 3.75vw, 72px); }

	/* Platform bento */
	.hv-platform { padding-bottom: clamp(64px, 6.25vw, 120px); }
	.hv-bento__title { font-size: clamp(20px, 1.458vw, 28px); }

	/* Advantage + compliance */
	.hv-adv { padding-block: 0 clamp(72px, 8.333vw, 160px); }
	.hv-adv__rows { gap: clamp(32px, 2.083vw, 40px); }
	.hv-adv__cell { gap: clamp(40px, 2.5vw, 48px); }
	.hv-compliance__title { font-size: clamp(24px, 1.875vw, 36px); letter-spacing: -0.02em; }
	.hv-compliance__sub { font-size: clamp(16px, 1.25vw, 24px); }

	/* Case studies */
	.hv-cases { padding-block: 0 clamp(56px, 5.208vw, 100px); }
	.hv-cases__card { gap: clamp(24px, 2.083vw, 40px); }
	.hv-cases__title { font-size: clamp(20px, 1.354vw, 26px); }
	/* The pager arrow is deliberately NOT scaled with the band: careers holds
	   .cr-tst__arrow at a flat 44x40 down to its own breakpoint, and these two
	   carousels are meant to read identically. */

	/* Closing CTA */
	.hv-cta { padding-block: clamp(64px, 6.25vw, 120px); }
	.hv-cta__title { font-size: clamp(30px, 2.448vw, 47px); letter-spacing: -0.0213em; }
}


/* The procedural dot field. Sits under the header's content (the parent sets
   `isolation: isolate`, so z-index:-1 stays inside that box) and never takes a
   pointer event. */
/* `canvas.` on purpose: every product page carries a `.xx-head > * { position:
   relative; z-index: 1 }` rule that loads after this file and would otherwise
   drop the canvas into the flow, pushing the band's own text down. */
canvas.hv-bgpattern {
	position: absolute;
	inset: 0;
	z-index: -1;
	display: block;
	width: 100%;
	height: 100%;
	pointer-events: none;
}

/* Every dotted band on the site — home, the five product pages, cerebra, about
   and careers — hosts one. `isolation` keeps the canvas's negative z-index
   inside the band (behind its text, above the section behind it), and inset:0
   means the field now runs edge to edge between the band's hairline borders
   instead of stopping where a fixed-width texture ran out. */
.hv-sechead,
.hv-proof__head,
[class*="-head--dots"],
.rp-loyalty__head,
.au-team__head {
	position: relative;
	isolation: isolate;
}
