/*
 * Visual enhancements — motion and decoration added on top of the ported design.
 *
 * Kept in a separate file on purpose. assets/style.css is the design system as
 * it was delivered and is verified byte-for-byte against the reference build;
 * everything added afterwards lives here, so it stays auditable and can be
 * removed in one line without touching the port.
 *
 * Three rules govern what is allowed in this file:
 *
 *   1. No JavaScript. The public site ships none, and the performance budget in
 *      the handover is measured against one stylesheet, one webfont and three
 *      lines of script.
 *   2. Nothing that delays Largest Contentful Paint. Elements that are LCP
 *      candidates — the hero heading and the portrait — animate with transform
 *      only. An element at opacity 0 counts as unpainted, so fading those in
 *      would push LCP back on the page that matters most.
 *   3. No layout shift. Decoration is drawn in pseudo-elements and transforms,
 *      never by moving anything in flow.
 */

/* ── entrance motion ─────────────────────────────────────────────────────── */

@keyframes oma-rise {
	from {
		opacity: 0;
		transform: translateY(14px);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

/* Transform only: used where the element is an LCP candidate. */
@keyframes oma-lift {
	from {
		transform: translateY(18px);
	}
	to {
		transform: none;
	}
}

@keyframes oma-portrait {
	from {
		transform: translateY(20px) scale(0.985);
	}
	to {
		transform: none;
	}
}

.sign h1 {
	animation: oma-lift 0.55s cubic-bezier(0.22, 0.68, 0.24, 1) both;
}

.sign .hero .lead {
	animation: oma-rise 0.55s cubic-bezier(0.22, 0.68, 0.24, 1) 0.08s both;
}

.sign .hero .btns {
	animation: oma-rise 0.55s cubic-bezier(0.22, 0.68, 0.24, 1) 0.16s both;
}

.heroportret {
	animation: oma-portrait 0.7s cubic-bezier(0.22, 0.68, 0.24, 1) both;
}

/* The stat row reads as a sequence, so it arrives as one. */
.sign .facts > div {
	animation: oma-rise 0.5s cubic-bezier(0.22, 0.68, 0.24, 1) both;
}
.sign .facts > div:nth-child(1) {
	animation-delay: 0.24s;
}
.sign .facts > div:nth-child(2) {
	animation-delay: 0.31s;
}
.sign .facts > div:nth-child(3) {
	animation-delay: 0.38s;
}
.sign .facts > div:nth-child(n + 4) {
	animation-delay: 0.45s;
}

/* ── hero decoration ─────────────────────────────────────────────────────── */

.sign {
	position: relative;
	overflow: hidden;
	isolation: isolate;
}

/* Keep the content above both decorative layers. */
.sign > .wrap {
	position: relative;
	z-index: 2;
}

/*
 * Concentric arcs radiating from the top-right corner: a quiet nod to reach and
 * signal, in the same ink as the text at low opacity so it never competes with
 * the copy. Inlined as a data URI — no extra request, nothing to cache-bust.
 */
.sign::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 0;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 420 420'%3E%3Cg fill='none' stroke='%230A0A0A' stroke-opacity='0.13' stroke-width='1.5'%3E%3Ccircle cx='420' cy='0' r='90'/%3E%3Ccircle cx='420' cy='0' r='155'/%3E%3Ccircle cx='420' cy='0' r='220'/%3E%3Ccircle cx='420' cy='0' r='285'/%3E%3Ccircle cx='420' cy='0' r='350'/%3E%3C/g%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: top right;
	background-size: min(46rem, 80%) auto;
	pointer-events: none;
}

/* A fine dot grid, faded out towards the right so the portrait stays clean. */
.sign::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 1;
	background-image: radial-gradient(rgba(10, 10, 10, 0.11) 1px, transparent 1px);
	background-size: 22px 22px;
	-webkit-mask-image: linear-gradient(100deg, rgba(0, 0, 0, 0.9) 0%, transparent 62%);
	mask-image: linear-gradient(100deg, rgba(0, 0, 0, 0.9) 0%, transparent 62%);
	pointer-events: none;
}

/* The portrait gets a soft halo so it lifts off the flat green. */
.heroportret {
	position: relative;
	z-index: 2;
	box-shadow: 0 18px 40px -18px rgba(10, 10, 10, 0.45);
}

/* ── the closing call-to-action band ─────────────────────────────────────── */

.cta-band {
	position: relative;
	overflow: hidden;
}

.cta-band > .wrap {
	position: relative;
	z-index: 1;
}

.cta-band::before {
	content: '';
	position: absolute;
	inset: 0;
	background-image: radial-gradient(rgba(255, 255, 255, 0.07) 1px, transparent 1px);
	background-size: 20px 20px;
	-webkit-mask-image: radial-gradient(70% 120% at 85% 0%, #000 0%, transparent 70%);
	mask-image: radial-gradient(70% 120% at 85% 0%, #000 0%, transparent 70%);
	pointer-events: none;
}

/* ── micro-interactions ──────────────────────────────────────────────────── */

/* The service rows already tint on hover; let the cue slide to suggest travel. */
.row .go {
	transition: transform 0.18s ease;
}

.row:hover .go,
.row:focus-visible .go {
	transform: translateX(4px);
}

.row {
	transition: background 0.15s ease;
}

/* Pricing cards and blog entries acknowledge the pointer without jumping. */
.plan {
	transition:
		transform 0.18s ease,
		box-shadow 0.18s ease;
}

.plan:hover {
	transform: translateY(-3px);
	box-shadow: 0 14px 30px -18px rgba(10, 10, 10, 0.4);
}

.postlist li {
	transition: background 0.15s ease;
}

.postlist li:hover {
	background: var(--signal-lt);
}

.postlist h3 a {
	transition: color 0.15s ease;
}

/* FAQ disclosure arrows turn rather than snap. */
.faq summary {
	transition: color 0.15s ease;
}

/* ── inner-page headers ──────────────────────────────────────────────────── */

/*
 * Every page that is not the home page opens with .pagehead — breadcrumb,
 * heading, lead — on the pale mint background. It gets the same choreography as
 * the hero and the same arc motif, drawn in the house green rather than ink so
 * it reads against the lighter panel.
 *
 * The heading is the LCP element on these pages (there is no hero image), so it
 * animates with transform only, exactly as .sign h1 does.
 */

.pagehead {
	position: relative;
	overflow: hidden;
}

.pagehead > .wrap {
	position: relative;
	z-index: 2;
}

.pagehead::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 0;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 420 420'%3E%3Cg fill='none' stroke='%2349C2AB' stroke-opacity='0.45' stroke-width='1.5'%3E%3Ccircle cx='420' cy='0' r='90'/%3E%3Ccircle cx='420' cy='0' r='155'/%3E%3Ccircle cx='420' cy='0' r='220'/%3E%3Ccircle cx='420' cy='0' r='285'/%3E%3C/g%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: top right;
	background-size: min(34rem, 70%) auto;
	pointer-events: none;
}

.pagehead::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 1;
	background-image: radial-gradient(rgba(73, 194, 171, 0.42) 1px, transparent 1px);
	background-size: 20px 20px;
	-webkit-mask-image: linear-gradient(105deg, rgba(0, 0, 0, 0.85) 0%, transparent 55%);
	mask-image: linear-gradient(105deg, rgba(0, 0, 0, 0.85) 0%, transparent 55%);
	pointer-events: none;
}

.pagehead .crumbs {
	animation: oma-rise 0.45s cubic-bezier(0.22, 0.68, 0.24, 1) both;
}

.pagehead h1 {
	animation: oma-lift 0.5s cubic-bezier(0.22, 0.68, 0.24, 1) both;
}

.pagehead .lead {
	animation: oma-rise 0.5s cubic-bezier(0.22, 0.68, 0.24, 1) 0.1s both;
}

/* The date and author line on a blog post sits after the lead. */
.pagehead .lead ~ .crumbs {
	animation-delay: 0.18s;
}

/* The full-bleed band under the home hero arrives with the content above it. */
.bandbeeld {
	animation: oma-fade 0.7s ease 0.2s both;
}

@keyframes oma-fade {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}

/* ── touch targets ───────────────────────────────────────────────────────── */

/*
 * The footer link lists are the only targets on the site below the 24x24 CSS
 * pixel minimum in WCAG 2.5.8 (AA): short place names like "Zele" render 30x21.
 * Widening the line box lifts them clear.
 *
 * Applied at every width rather than only on narrow screens, because the
 * success criterion is about pointer accuracy in general, not touch alone. It
 * costs a few pixels of footer height and moves nothing else.
 */
footer.site ul a,
.legal a {
	display: inline-block;
	padding-block: 0.3rem;
}

/* ── legibility ──────────────────────────────────────────────────────────── */

/*
 * The client-name caption on the logo wall was .72rem, which computes to 11.5px.
 * It is a caption rather than body copy, but on touch devices it is shown
 * permanently rather than on hover, so it is read rather than glanced at.
 * Nudged to 12px: the smallest change that clears the legibility floor, and
 * indistinguishable from the original at a glance.
 */
.logonaam {
	font-size: 0.75rem;
}

/* ── reduced motion ──────────────────────────────────────────────────────── */

/*
 * style.css already flattens durations globally. This block goes further and
 * removes the transforms themselves, so nothing arrives mid-flight or shifts
 * under a pointer for someone who asked for stillness.
 */
@media (prefers-reduced-motion: reduce) {
	.sign h1,
	.sign .hero .lead,
	.sign .hero .btns,
	.sign .facts > div,
	.heroportret,
	.pagehead .crumbs,
	.pagehead h1,
	.pagehead .lead,
	.bandbeeld {
		animation: none;
		opacity: 1;
		transform: none;
	}

	.row:hover .go,
	.row:focus-visible .go,
	.plan:hover {
		transform: none;
	}
}

/* ── blog images ─────────────────────────────────────────────────────────── */

/*
 * A post's image is optional and was never rendered before, so these rules only
 * ever apply to posts where an editor has chosen one. Posts without an image are
 * untouched, which is every post that exists today.
 */
.postbeeld {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 19 / 10;
	object-fit: cover;
	border-radius: var(--r);
	margin-bottom: 2rem;
}

.postlist li.met-beeld {
	display: grid;
	grid-template-columns: 160px 1fr;
	gap: 1.2rem;
	align-items: start;
}

.postthumb {
	width: 160px;
	height: 120px;
	object-fit: cover;
	border-radius: var(--r);
}

@media (max-width: 620px) {
	.postlist li.met-beeld {
		grid-template-columns: 1fr;
	}
	.postthumb {
		width: 100%;
		height: auto;
		aspect-ratio: 4 / 3;
	}
}

/* ── hero met tekst over het beeld ───────────────────────────────────────────
 *
 * The homepage opens on the header image with the title over it, instead of a
 * green band with a banner underneath. The image is a real <img> rather than a
 * background so it stays the discoverable LCP element; it is pulled behind the
 * text with z-index, and a scrim carries the contrast, because the photo is
 * black and white and its top half is bright sky.
 *
 * Scoped to .herohead, which the homepage only sets when a header image exists.
 * Without one it stays the plain green head it was.
 */

.herohead {
	position: relative;
	isolation: isolate;
	background: var(--ink);
	overflow: hidden;
}

/* The ink arcs behind the green head are decoration for a flat colour; over a
   photograph they are just noise, and invisible anyway. */
.herohead::before {
	display: none;
}

/* The entrance animations keyed off .hero, which the photo hero replaces. */
.herohead .heroover .lead {
	animation: oma-rise 0.55s cubic-bezier(0.22, 0.68, 0.24, 1) 0.08s both;
}

.herohead .heroover .btns {
	animation: oma-rise 0.55s cubic-bezier(0.22, 0.68, 0.24, 1) 0.16s both;
}

.herohead .herobeeld {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center 40%;
	z-index: -2;
}

/*
 * Dark at the right where the text sits, clearing towards the left — plus a
 * second wash rising from the bottom. The photo's lower half is a sunlit road
 * and a zebra crossing, near-white, and the figures row sits right on it.
 *
 * The text is on the right for the sake of the photograph. Its subject walks
 * across the whole frame, so an overlay anywhere covers someone; on the left it
 * covered Niels, who is the point of the picture. Keeping the left side light
 * leaves him visible and puts the scrim over the emptying road instead.
 */
.herohead::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: -1;
	/*
	 * .sign::after above is the dot grid, and it masks itself out towards the
	 * right. That is the same pseudo-element as this one, so without clearing
	 * the mask the scrim faded out across the page — which is precisely where
	 * the photo is brightest and the figures row sits.
	 */
	-webkit-mask-image: none;
	mask-image: none;
	background:
		linear-gradient(
			to left,
			rgba(10, 10, 10, 0.92) 0%,
			rgba(10, 10, 10, 0.72) 42%,
			rgba(10, 10, 10, 0.28) 100%
		),
		linear-gradient(
			to top,
			rgba(10, 10, 10, 0.6) 0%,
			rgba(10, 10, 10, 0.42) 22%,
			rgba(10, 10, 10, 0) 52%
		);
}

.herohead .wrap {
	position: relative;
	min-height: clamp(360px, 42vw, 540px);
	display: flex;
	flex-direction: column;
	justify-content: center;
}

.herohead .heroover {
	max-width: 46rem;
}

/*
 * Above the narrow breakpoint the whole overlay column sits right, figures row
 * included — half of it moving and half staying would read as a mistake. Below
 * it the photo is cropped to almost nothing either side and the scrim is a flat
 * vertical wash, so the text goes back to the left like every other page.
 */
@media (min-width: 701px) {
	.herohead .heroover,
	.herohead .facts {
		margin-left: auto;
		text-align: right;
	}

	.herohead h1,
	.herohead .lead {
		margin-left: auto;
	}

	.herohead .btns,
	.herohead .facts {
		justify-content: flex-end;
	}
}

/*
 * A shadow as well as the scrim. The header image is editable, so the next one
 * could be bright anywhere; a gradient tuned to this photo would not survive
 * that, and this keeps the text legible whatever is behind it.
 */
.herohead h1,
.herohead .lead,
.herohead .facts {
	text-shadow: 0 1px 3px rgba(10, 10, 10, 0.55);
}

.herohead h1 {
	color: #fff;
	max-width: 18ch;
	text-wrap: balance;
}

.herohead .lead {
	color: rgba(255, 255, 255, 0.9);
	max-width: 48ch;
}

/* The green head's buttons are dark-on-green; over the photo they need to read
   against a dark scrim instead. */
.herohead .btn {
	background: #fff;
	border-color: #fff;
	color: var(--ink);
}
.herohead .btn:hover {
	background: var(--signal);
	border-color: var(--signal);
	color: var(--ink);
}
.herohead .btn-ghost {
	background: transparent;
	border-color: #fff;
	color: #fff;
}
.herohead .btn-ghost:hover {
	background: #fff;
	border-color: #fff;
	color: var(--ink);
}

.herohead .facts {
	border-top-color: rgba(255, 255, 255, 0.28);
}
.herohead .facts div {
	color: rgba(255, 255, 255, 0.92);
}
.herohead .facts b {
	color: #fff;
}

@media (max-width: 700px) {
	.herohead .wrap {
		min-height: 0;
	}
	/* Narrow screens crop the photo to almost nothing either side of the
	   subject, so lean harder on the scrim rather than on the image. */
	.herohead::after {
		background: linear-gradient(
			to bottom,
			rgba(10, 10, 10, 0.78) 0%,
			rgba(10, 10, 10, 0.88) 55%,
			rgba(10, 10, 10, 0.93) 100%
		);
	}
	.herohead h1 {
		max-width: none;
	}
}

/* ── portret naast de tekst ──────────────────────────────────────────────────
 *
 * {{portret}} is folded into the prose that follows it (see foldPortrait), so
 * this floats inside that same block and the paragraphs wrap around it.
 */

/*
 * A prose block that spans the whole container rather than stopping at the
 * measure.
 *
 * Only the layout widens. p, ul and ol carry their own max-width: var(--prose)
 * in style.css, so the lines stay exactly as long as they were — which is the
 * point: 68ch is already at the top of the comfortable range, and the full
 * 1140px would be around 134 characters, well past where the eye starts losing
 * its place on the way back. What this buys is the float reaching the outer
 * edge, instead of being boxed inside the text column with the rest of the
 * container empty beside it.
 */
.prose-wide {
	max-width: none;
}

.prose-portret {
	float: right;
	width: min(300px, 38%);
	margin: 0.4rem 0 1.4rem 2rem;
	shape-outside: margin-box;
}

.prose-wide .prose-portret {
	width: min(340px, 32%);
	margin-left: clamp(2rem, 4vw, 3.5rem);
}

.prose-portret img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var(--r);
	background: #fff;
	box-shadow: 0 10px 30px rgba(10, 10, 10, 0.14);
}

/* A float this wide leaves slivers of text beside it; below that, stack. */
@media (max-width: 720px) {
	.prose-portret {
		float: none;
		width: min(240px, 60%);
		margin: 0 0 1.4rem;
	}
}

/* ── afbeeldingen in de lopende tekst ────────────────────────────────────────
 *
 * Images placed in a body with the editor's Afbeelding button. Block, full
 * column width: the prose column is already narrow, and on a page like /contact
 * it sits next to a form, where a float would leave nothing usable either side.
 */

.prose img {
	display: block;
	max-width: 100%;
	/*
	 * Capped by height, not width. A portrait photograph at full column width
	 * runs about a screen tall and pushes everything after it below the fold —
	 * the office photo on /contact was 69% of that column on its own. Landscape
	 * images are untouched: 16:9 in this column comes out near 380px and never
	 * reaches the cap, so this only bites on the shape that causes the problem.
	 */
	max-height: 440px;
	width: auto;
	height: auto;
	border-radius: var(--r);
	margin: 1.6rem auto;
}

/* The portrait fills its figure, which is already what constrains it. */
.prose-portret img {
	width: 100%;
	max-height: none;
	margin: 0;
}

/* ── blogoverzicht als raster ────────────────────────────────────────────────
 *
 * Cards rather than a stacked list, and no dates (see BlogIndex). The base
 * list rules live in style.css, which is verified byte-for-byte against the
 * reference build, so the grid is layered over them here.
 */

.postlist.postgrid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(clamp(240px, 30%, 320px), 1fr));
	gap: clamp(1.4rem, 3vw, 2.2rem);
	border-top: 0;
	margin-top: 2rem;
}

.postlist.postgrid li,
.postlist.postgrid li.met-beeld {
	display: flex;
	flex-direction: column;
	gap: 0;
	border-bottom: 0;
	padding: 0;
	border: 1px solid var(--line);
	border-radius: var(--r);
	overflow: hidden;
	background: var(--paper);
	transition: border-color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
}

.postlist.postgrid li:hover {
	border-color: var(--line-dark);
	box-shadow: 0 10px 28px rgba(10, 10, 10, 0.08);
	transform: translateY(-2px);
}

@media (prefers-reduced-motion: reduce) {
	.postlist.postgrid li {
		transition: none;
	}
	.postlist.postgrid li:hover {
		transform: none;
	}
}

.postlist.postgrid .postthumb {
	width: 100%;
	height: auto;
	aspect-ratio: 3 / 2;
	border-radius: 0;
	object-fit: cover;
}

.postlist.postgrid li > div {
	padding: 1.1rem 1.2rem 1.4rem;
	display: flex;
	flex-direction: column;
	gap: 0.35rem;
}

/* Reused for the category now that the date is gone. */
.postlist.postgrid .date {
	text-transform: uppercase;
	letter-spacing: 0.06em;
	/* 0.74rem came out at 11.8px, below the 12px floor the responsiveness
	   audit holds the site to. */
	font-size: 0.8rem;
	font-weight: 600;
	color: var(--signal-dk);
}

.postlist.postgrid h3 {
	margin: 0;
	font-size: 1.08rem;
	line-height: 1.35;
}

.postlist.postgrid h3 a {
	text-decoration: none;
}

/* Intros vary from two lines to ten; clamped so the cards read as a row. */
.postlist.postgrid p {
	margin: 0;
	font-size: 0.94rem;
	display: -webkit-box;
	-webkit-line-clamp: 4;
	line-clamp: 4;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* ── long words in running text ──────────────────────────────────────────────
 *
 * "www.gegevensbeschermingsautoriteit.be" in the privacy policy is a single
 * 38-character token. On a 320px screen it is wider than the viewport, and
 * because it overflows its paragraph rather than widening it, it pushed the
 * whole page sideways without any element measuring too wide. Breaking only
 * when a word genuinely does not fit leaves ordinary text alone.
 */

.prose,
.prose p,
.prose li,
.prose h1,
.prose h2,
.prose h3,
.pagehead .lead {
	overflow-wrap: break-word;
}

/* ── offerteformulier ────────────────────────────────────────────────────────
 *
 * The quote form asks follow-up questions only for the services that were
 * ticked. The site ships no JavaScript, so the reveal is done by :has() on the
 * form: a block is shown when its checkbox is checked.
 *
 * Gated behind @supports on purpose, and the right way round. Without :has()
 * nothing is hidden, so every question is visible — a long form, but a complete
 * and working one. Hiding by default and revealing with :has() would leave the
 * questions unreachable in a browser that lacks it.
 */

.offerteform {
	max-width: none;
}

.offerteform .offertestap {
	border: 0;
	border-top: 2px solid var(--ink);
	margin: 2.4rem 0 0;
	padding: 1.6rem 0 0;
}

.offerteform legend {
	display: flex;
	align-items: center;
	gap: 0.7rem;
	padding: 0;
	font-size: 1.28rem;
	font-weight: 700;
	letter-spacing: -0.02em;
}

.offerteform .stapnr {
	display: inline-grid;
	place-items: center;
	width: 1.9rem;
	height: 1.9rem;
	border-radius: 100px;
	background: var(--ink);
	color: #fff;
	font-size: 0.95rem;
	line-height: 1;
}

.offerteform h3 {
	font-size: 1rem;
	margin: 0 0 0.8rem;
}

/* The service checkboxes read as a list of choices, not a wall of text. */
.offerteform .keuzes {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
	gap: 0.55rem 1.6rem;
	margin-top: 1.2rem;
}

.offerteform .checkline {
	padding: 0.55rem 0.8rem;
	border: 1px solid var(--line);
	border-radius: var(--r);
	background: #fff;
}

/*
 * Only inside a group, where the grid gap does the spacing. Applying it to
 * every .checkline also stripped the margin from the standalone privacy line,
 * which then sat flush against the submit button.
 */
.offerteform .keuzes .checkline,
.offerteform .keuzelijst .checkline {
	margin: 0;
}

/* The budget choices are a stack, not a grid, so they need their own gap. */
.offerteform .keuzelijst {
	display: grid;
	gap: 0.55rem;
}

.offerteform .privacyveld {
	margin: 1.8rem 0 0;
}

.offerteform button[type='submit'] {
	margin-top: 1.5rem;
}

.offerteform .checkline label {
	margin: 0;
	cursor: pointer;
}

.offerteform .checkline:has(input:checked) {
	border-color: var(--signal);
	background: var(--signal-lt);
}

/* Two columns for the short contact fields; one on a phone. */
.offerteform .tweeluik {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
	gap: 0 1.4rem;
	margin-top: 1.2rem;
}

/*
 * Keep the boxes on a row in line with each other. "Btw-nummer (voor op de
 * offerte)" wraps to two lines where "Naam" does not, and without this its
 * input sits a line lower than its neighbours — which reads as a broken grid
 * rather than a longer label.
 */
.offerteform .tweeluik .field {
	display: flex;
	flex-direction: column;
}

.offerteform .tweeluik .field input {
	margin-top: auto;
}

/* A single-column select or textarea stretched across the whole container
   reads as a mistake; the two-column fields are already narrower than this. */
.offerteform .field > input,
.offerteform .field > select,
.offerteform .field > textarea {
	max-width: 34rem;
}

.offerteform .veldkop {
	font-weight: 600;
	font-size: 0.92rem;
	margin: 0 0 0.35rem;
}

.offerteform .alsdan {
	/* Its fields are capped, so a panel spanning the whole container would be
	   mostly empty tint. */
	max-width: 42rem;
	margin: 1.6rem 0;
	padding: 1.2rem 1.3rem;
	border-left: 4px solid var(--signal);
	background: var(--paper-2);
	border-radius: 0 var(--r) var(--r) 0;
}

.offerteform .alsdan .field:last-child {
	margin-bottom: 0;
}

@supports selector(:has(*)) {
	.offerteform .alsdan {
		display: none;
	}

	.offerteform:has(#d-website:checked) .als-website,
	.offerteform:has(#d-branding:checked) .als-branding,
	.offerteform:has(#d-social:checked) .als-social,
	.offerteform:has(#d-vindbaarheid:checked) .als-vindbaarheid,
	.offerteform:has(#d-email:checked) .als-email,
	.offerteform:has(#d-fotovideo:checked) .als-fotovideo,
	.offerteform:has(#d-drukwerk:checked) .als-drukwerk {
		display: block;
	}
}

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

/* ── the brand green on the main calls to action ─────────────────────────────
 *
 * Green is the brand, so the primary button is green wherever it appears: the
 * header, the hero, the free scan, the service and article pages, and the
 * thirty-minute band. btn-green is the delivered design system's own class in
 * style.css — this is not a new colour, only a wider use of it.
 *
 * Two contexts need help. The photo hero repaints .btn white so it reads
 * against the scrim, and `.herohead .btn` is more specific than `.btn-green`,
 * so it would win. And on a dark background the stock hover to ink leaves a
 * black button on a black band: it reads as the button disappearing. Lifting to
 * white instead keeps the shape and says "pressed".
 */

.herohead .btn-green,
.cta-band .btn-green {
	background: var(--signal);
	border-color: var(--signal);
	color: var(--ink);
}

.herohead .btn-green:hover,
.cta-band .btn-green:hover {
	background: #fff;
	border-color: #fff;
	color: var(--ink);
}
