/**
 * Homepage sections.
 *
 * Mobile-first. Breakpoints: 768px (tablet) and 1280px (desktop), matching nav.css.
 * Every value references a token — a raw hex or magic number here is a bug.
 */

/* ---- Shared section shell ----------------------------------------------- */

.oss-main {
	font-family: var(--oss-font);
	color: var(--oss-text);
}

.oss-section {
	position: relative;
}

/*
 * The shell carries the container plus its gutters. See the note in tokens.css: setting
 * max-width to the container alone and then adding padding double-counts the margin.
 */
.oss-hero__inner,
.oss-stats__inner {
	max-width: var(--oss-shell);
	margin: 0 auto;
	padding-inline: var(--oss-gutter-sm);
}

/* ---- Hero --------------------------------------------------------------- */

.oss-hero {
	padding-block: var(--oss-space-6) 0;
	background: var(--oss-surface);
}

.oss-hero__inner {
	display: flex;
	flex-direction: column;
	gap: var(--oss-space-6);
}

.oss-hero__brand {
	margin: 0 0 var(--oss-space-4);
	color: var(--oss-primary);
	font-size: clamp(26px, 6vw, var(--oss-fs-display));
	font-weight: var(--oss-fw-bold);
	line-height: var(--oss-lh-tight);
}

.oss-hero__headline {
	margin: 0 0 var(--oss-space-5);
	font-size: clamp(21px, 4.4vw, var(--oss-fs-h1));
	font-weight: var(--oss-fw-bold);
	line-height: var(--oss-lh-tight);
}

.oss-hero__line {
	display: block;
}

/* The design gives the closing line the brand colour. */
.oss-hero__line--accent {
	color: var(--oss-primary);
}

.oss-hero__lead {
	margin: 0 0 var(--oss-space-6);
	max-width: 60ch;
	color: var(--oss-text);
	font-size: var(--oss-fs-sm);
	line-height: var(--oss-lh-base);
}

.oss-hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--oss-space-3);
}

.oss-hero__actions .oss-btn {
	flex: 1 1 auto;
	min-width: 220px;
}

/* ---- Hero visual -------------------------------------------------------- */

.oss-hero__visual {
	position: relative;
}

/*
 * The <picture> wrapper is plumbing, not a box.
 *
 * `display: contents` removes it from the layout entirely, so the image stays the direct flex
 * item of .oss-hero__visual that every rule below was written against — the wrapper buys the
 * media-conditional download and changes nothing else.
 */
.oss-hero__picture {
	display: contents;
}

/*
 * Not shown on a phone.
 *
 * The artwork is a 2.2:1 banner whose left third is an almost empty pale wedge — deliberate on
 * a desktop, where the headline sits over it. On a narrow screen it is a tall block of mostly
 * nothing between the calls to action and the benefits, so it is dropped rather than cropped
 * and the phone reader reaches the substance sooner.
 *
 * Hidden with display, not with markup, so the same template serves every width. Note this
 * hides the picture but does not skip its download — the browser still fetches a display:none
 * image. Saving the bytes would mean art-directing it in the markup with <picture>.
 */
.oss-hero__image {
	display: none;
	width: 100%;
	height: auto;
	border-radius: var(--oss-radius);
	object-fit: cover;
}

/* ---- Hero benefits ------------------------------------------------------ */

.oss-hero__benefits {
	margin: var(--oss-space-4) 0 0;
	padding: var(--oss-space-4);
	list-style: none;
	background: var(--oss-primary);
	border-radius: var(--oss-radius-lg);
	color: var(--oss-surface);
}

.oss-hero__benefit {
	display: flex;
	gap: var(--oss-space-3);
	align-items: flex-start;
	padding-block: var(--oss-space-3);
}

/*
 * Separators between rows rather than around them, so the first and last rows sit flush
 * against the panel's padding however many benefits the editor adds.
 */
.oss-hero__benefit + .oss-hero__benefit {
	border-top: 1px solid rgba(255, 255, 255, 0.25);
}

.oss-hero__benefit-icon {
	flex: 0 0 auto;
	width: 32px;
	height: 32px;
	object-fit: contain;
}

.oss-hero__benefit-body {
	min-width: 0;
}

/*
 * Colour is declared on each text element rather than inherited from the panel.
 *
 * The parent theme has `body, p { color: #000000 }` in its stylesheet. An element selector
 * beats inheritance, so every <p> inside the teal panel rendered black on teal however the
 * panel itself was coloured. Anything placed on a coloured surface has to say so explicitly.
 */
.oss-hero__benefit-title {
	margin: 0 0 var(--oss-space-1);
	color: var(--oss-surface);
	font-size: var(--oss-fs-sm);
	font-weight: var(--oss-fw-bold);
	line-height: var(--oss-lh-snug);
}

.oss-hero__benefit-text {
	margin: 0;
	color: var(--oss-surface);
	font-size: var(--oss-fs-xs);
	line-height: var(--oss-lh-base);
	opacity: 0.92;
}

/* ---- Stats -------------------------------------------------------------- */

.oss-stats {
	padding-block: var(--oss-space-6);
	background: var(--oss-surface);
}

.oss-stats__inner {
	/* The band itself is the coloured element, inset within the page's gutters. */
}

.oss-stats__list {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--oss-space-4);
	margin: 0;
	padding: var(--oss-space-5) var(--oss-space-4);
	list-style: none;
	background: var(--oss-primary);
	border-radius: var(--oss-radius-lg);
	color: var(--oss-surface);
}

.oss-stats__item {
	display: flex;
	gap: var(--oss-space-4);
	align-items: center;
}

.oss-stats__icon {
	flex: 0 0 auto;
	width: 36px;
	height: 36px;
	object-fit: contain;
}

.oss-stats__body {
	min-width: 0;
}

.oss-stats__value {
	margin: 0 0 2px;
	color: var(--oss-surface);
	font-size: clamp(20px, 4.6vw, var(--oss-fs-stat));
	font-weight: var(--oss-fw-bold);
	line-height: 1.2;
}

.oss-stats__label {
	margin: 0;
	color: var(--oss-surface);
	font-size: 12px;
	line-height: 1.33;
	opacity: 0.95;
}

/* ---- Tablet ------------------------------------------------------------- */

@media (min-width: 768px) {
	.oss-hero__inner,
	.oss-stats__inner {
		padding-inline: var(--oss-gutter-md);
	}

	.oss-hero {
		padding-top: var(--oss-space-7);
	}

	.oss-hero__actions .oss-btn {
		flex: 0 0 auto;
	}


	/*
	 * Two benefits per row. Stacked, the panel ran nearly a screen tall on its own and pushed
	 * the stats band below the fold; there is width to spare here, so it is spent on halving
	 * the height. The row separators go with it — with two columns a border-top on every
	 * sibling but the first draws a line through the middle of the top row — and the grid gap
	 * does the separating instead.
	 */
	.oss-hero__benefits {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--oss-space-4) var(--oss-space-5);
		padding: var(--oss-space-5);
	}

	.oss-hero__benefit {
		padding-block: 0;
	}

	.oss-hero__benefit + .oss-hero__benefit {
		border-top: 0;
	}

	/* Two figures per row before the four-across desktop layout. */
	.oss-stats__list {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--oss-space-5);
		padding: var(--oss-space-6) var(--oss-space-5);
	}
}

/* ---- Hero artwork, tablet and narrow desktop ---------------------------- */

/*
 * A bounded range, which the rest of this file does not use.
 *
 * The artwork needs a text column beside it, and below about 900px there is not one to spare:
 * at 800 the copy fell to a 430px column, the brand line broke in two, the headline ran to four
 * lines and the two calls to action stacked. Better no picture than a squeezed page — which is
 * the phone's bargain, and it holds a little way past the phone.
 *
 * The upper bound is the desktop layout taking over at 1280, where the artwork is full-bleed and
 * the stats band is laid over it. Everything here is replaced there, not extended.
 */
@media (min-width: 900px) and (max-width: 1279px) {
	/*
	 * The artwork returns below 1280, as the design's backdrop rather than as a column.
	 *
	 * The client works in a half-width window: "чи можна, щоб у звуженому вікні картинка
	 * відкривалась, а не була біла частина? Картинку видно лиш в повному вікні." Below 1280 the
	 * hero was a text column with white beside it.
	 *
	 * Boxing the picture into a right-hand column was tried first and looked wretched: the file
	 * is a 2:1 banner, and a third of a row is a portrait frame, so `cover` cropped it to a
	 * sliver of chimney. The artwork only works at its own proportion, with the copy laid over
	 * the pale wedge that is part of the picture — which is exactly what the desktop layout does.
	 * This is that composition, scaled down.
	 *
	 * `display: contents` on the visual is what lets one layout serve both halves: it drops the
	 * wrapper so the picture can be positioned against the row while the benefits panel stays in
	 * normal flow beneath. The panel needs the full width — its four benefits sit two-by-two here
	 * and would wrap to three lines each in a third of a row.
	 */
	.oss-hero__inner {
		display: grid;
		grid-template-columns: minmax(0, 1fr) minmax(0, 40%);
		/*
		 * The gap the client asked for: "can it just be the image beside with a little bit space
		 * underneath so it has space between stats and the image?"
		 *
		 * Laying the panel over the artwork's foot is the desktop's join, and it needs the
		 * desktop's height to read as one. Here the artwork is a column beside the copy, and the
		 * two met at a seam — worse the wider the window got, because the picture's height
		 * followed its width while the panel stayed where the copy ended. A row gap separates
		 * them instead, and the artwork is sized off the copy below so the seam cannot come back.
		 */
		row-gap: var(--oss-space-5);
		position: relative;
	}

	/*
	 * Still dropped from the layout: the benefits panel is inside it, and belongs to the row
	 * rather than to the artwork's column.
	 */
	.oss-hero__visual {
		display: contents;
	}

	/*
	 * The <picture> stops being plumbing here and becomes the artwork's cell.
	 *
	 * It is the only element that wraps the image alone — the visual around it also holds the
	 * benefits — so it is the one that can be a column and clip what overflows it. The artwork
	 * is far wider than the cell (55% of it is thrown away by the clip below), so it is hung
	 * inside rather than laid out by it, and the cell hides the rest. That keeps the picture off
	 * the copy at every width in the range, which positioning it against the whole row did not.
	 */
	.oss-hero__picture {
		display: block;
		grid-row: 1;
		grid-column: 2;
		position: relative;
		overflow: hidden;
	}

	/*
	 * The copy's own column, still held to the design's measure.
	 *
	 * Capped at the desktop column's 480px: past about 1000px the column alone let the copy run
	 * wider than the design's measure, and the headline's three lines started to fall
	 * differently at every width.
	 */
	.oss-hero__content {
		grid-row: 1;
		grid-column: 1;
		position: relative;
		z-index: 1;
		max-width: 480px;
		padding-block: var(--oss-space-5);
	}

	.oss-hero__image {
		display: block;
		/*
		 * Sized off the cell's width, and hung so that what survives the clip fills it exactly.
		 *
		 * The clip keeps the right 45% of the file, so a picture 100/45 = 222% of the cell wide,
		 * pulled left by the 122% it throws away, lands its kept part on the cell's own left and
		 * right edges. The artwork is then a fixed share of the row at every width in the range.
		 *
		 * Sizing it off the cell's HEIGHT instead was tried first, and shrank the picture as the
		 * window widened: the height it followed was the copy's, and the copy gets shorter as its
		 * lines stop wrapping — "can we make for this one just a bit wider".
		 */
		width: 222.3%;
		margin-left: -122.3%;
		max-width: none;
		height: auto;
		/* Square, like the desktop artwork: it meets the container's edge rather than floating. */
		border-radius: 0;
		/*
		 * The pale wash to the left of the photograph is cut away, on a straight edge.
		 *
		 * The designer baked the wedge into the file as alpha rather than leaving it empty: the
		 * left third carries the photograph at 1–14% opacity, which over a white page is a soft
		 * grey. At full width that wash sits behind the copy and reads as part of the
		 * composition. Anchored to the top of a smaller hero it became a grey rectangle with a
		 * hard top edge floating above white — "this white-grey gradient on the left of the
		 * image ... with it it looks odd".
		 *
		 * Cut at 55%, which is where the wash ends at its widest: the alpha boundary runs
		 * diagonally from 31.6% of the file's width at the top edge to 54.9% at the bottom, so
		 * anything short of 55% leaves a sliver of it behind at the foot. Following that diagonal
		 * instead was tried and rejected — it cut the picture on an angle, which the client did
		 * not want. A straight edge costs some photograph at the top; the wash costs the whole
		 * corner.
		 */
		clip-path: inset(0 0 0 55%);
	}

	/* The full width of the row, below both columns: its four benefits sit two-by-two here. */
	.oss-hero__benefits {
		grid-row: 2;
		grid-column: 1 / -1;
		position: relative;
		z-index: 1;
	}
}

/* ---- Desktop ------------------------------------------------------------ */

@media (min-width: 1280px) {
	.oss-hero__inner,
	.oss-stats__inner {
		padding-inline: var(--oss-gutter);
	}

	.oss-hero {
		padding-top: var(--oss-space-3);
		padding-bottom: 0;
	}

	/*
	 * The band is laid over the artwork's lower edge, not placed below it.
	 *
	 * Design: artwork y 101..638, band y 536..639 — the band covers the artwork's bottom
	 * 100pt and stops 70pt short of its right edge, so the photograph shows above, below and
	 * to the right of it. That overlap is what makes the two read as one composition.
	 */
	.oss-stats {
		padding-top: 0;
		margin-top: calc(-1 * var(--oss-stats-overlap));
	}

	.oss-stats__list {
		position: relative;
		z-index: 2;
	}

	/*
	 * Text left, visual right. The design gives the copy a little under half the width; the
	 * benefits panel overlaps the image's right edge.
	 */
	/*
	 * The hero row is full-bleed on its right.
	 *
	 * The design's artwork runs off the edge of its 1500pt canvas. Constraining the row to the
	 * container reproduced that only at exactly 1500px wide — on anything wider the artwork
	 * stopped at the container and left a white margin beside it, which reads as a mistake
	 * rather than a banner.
	 *
	 * The left padding keeps the text column aligned with every other section: it matches the
	 * container's own centring, and falls back to the plain gutter once the viewport is
	 * narrower than the container.
	 */
	.oss-hero__inner {
		/* Back to flex: the tablet grid above is replaced here, not extended. */
		display: flex;
		flex-direction: row;
		align-items: center;
		/*
		 * The design's text runs x 79..540 while the artwork begins at x 520 — they overlap by
		 * 20pt, with the artwork's pale wedge passing behind the last of the text. A flex gap
		 * cannot express that, so the gap is zero and the artwork is pulled left instead.
		 *
		 * The text column is a fixed width, not a percentage. As a percentage of a full-bleed
		 * row it grew with the viewport: measured at 2000px it reached 584px, pushing the
		 * artwork right and away from the design's proportions.
		 *
		 * The row is capped at the design's own 1500pt canvas and centred. Above that width
		 * the layout stops growing, so the artwork bleeds to the canvas edge exactly as drawn
		 * and the proportions between text, artwork and panel never drift. The alternative —
		 * running the artwork to the viewport edge — made the hero grow out of step with every
		 * section below it, which read as lopsided on a wide screen.
		 *
		 * The artwork still ends 80pt to the right of the stats band, because in the design it
		 * reaches the canvas edge at 1500 while the band stops at 1420.
		 */
		gap: 0;
		padding-left: var(--oss-gutter);
		padding-right: 0;
		/* The artwork is positioned against this row, and the row keeps its measured height. */
		position: relative;
		min-height: var(--oss-hero-art);
	}

	/*
	 * Measured from the design, on its 1500pt canvas:
	 *   text          x  79 ..  540   (461pt — the brand line's own measured width)
	 *   artwork       x 520 .. 1500   (980pt, bleeding 80pt past the content column)
	 *   artwork       y 101 ..  539   (438pt tall, so a 2.24:1 box)
	 *
	 * The design lets the artwork's pale wedge slide behind the text's last 20pt. Flex cannot
	 * overlap, so the split is 36/64: enough for the brand line to stay on one line, with the
	 * artwork starting slightly left of where the design places it.
	 */
	.oss-hero__content {
		position: relative;
		/* Above the artwork, which is pulled left to overlap this column's right edge. */
		z-index: 1;
		/*
		 * 480 at every desktop width — the design's text column is 461pt on its 1500pt canvas.
		 *
		 * Not a proportion: narrowing it on a smaller desktop broke the brand line onto two
		 * lines and stacked the two calls to action, neither of which the design does. The
		 * benefits panel is held at its own measured width instead of competing for this space.
		 */
		flex: 0 0 480px;
		display: flex;
		flex-direction: column;
		justify-content: center;
		padding-block: var(--oss-space-6);
		/*
		 * The text column centres on the artwork MINUS the strip the stats band covers.
		 *
		 * Without this the column centred on the full artwork height and its lower half — both
		 * calls to action — disappeared behind the band. In the design the buttons end at y 497
		 * and the band starts at 537, so the copy is centred in the clear region above it.
		 *
		 * A bottom margin rather than padding: the margin box stays shorter than the artwork,
		 * so the row's height is still the artwork's and the artwork is not pushed off-centre.
		 */
		margin-bottom: var(--oss-stats-overlap);
	}

	/*
	 * Height is set here rather than inherited from the row, so the artwork keeps the design's
	 * proportion instead of stretching to whatever the text column happens to need.
	 *
	 * The design's artwork is 536pt tall on a 1500pt canvas — the full height, down to where
	 * the stats band ends, not just the part visible above the band. Measuring it to the band's
	 * top instead left the hero 100pt short: the band then had nothing but text column beneath
	 * it to overlap, and it swallowed the calls to action.
	 *
	 * The height is flat rather than scaled with the viewport. Scaling it kept the design's
	 * proportion below 1500 but shortened the benefits panel faster than its text shrank, and
	 * the panel clipped. The artwork is object-fit: cover, so a fixed height simply crops it a
	 * little more tightly on a narrower desktop — a far cheaper trade than lost content.
	 */
	/*
	 * The artwork is the row's backdrop, not a column beside the text.
	 *
	 * Held to the right half it covered 980 of the row's 1500 and stopped at a hard vertical
	 * edge behind the copy. In the design there is no such edge: the picture runs the full
	 * width and its own pale wedge is what clears space for the headline. So the visual is
	 * taken out of the flex flow and stretched across the row, with the text laid over it.
	 */
	/*
	 * The artwork lies behind the row, at its own proportions.
	 *
	 * As a flex column it was a 980pt panel with a hard vertical edge behind the copy; stretched
	 * across the row with object-fit: cover it filled the width but only by cropping, which
	 * pushed the composition off its marks. It is now taken out of the flow and anchored to the
	 * row's right edge at full height, so its width follows from the design's own 1035 x 536
	 * and the text sits over the pale wedge that is already part of the picture.
	 *
	 * Width is 1359 of the design's 1500 — 95.7% here, because a percentage resolves against
	 * the row's content box, which the 80pt left padding has already narrowed to 1420 — and
	 * not the artwork's own
	 * proportion. The file's left 345px of 1090 are transparent: the pale wedge is baked in as
	 * alpha, so a third of the picture's box renders as page white. Sizing the box by the
	 * file's height therefore drew the photograph a quarter smaller than the design, starting
	 * at x 795 where the design starts it at 571. At 1359 the scale matches, the transparent
	 * wedge runs on behind the copy where it costs nothing, and the overflow clips the top and
	 * bottom exactly as the design's own frame does.
	 */
	/*
	 * The artwork ends on the container's right edge, with the stats band and the card row.
	 *
	 * The design runs it off the canvas, but the canvas IS the viewport there. Here the row is
	 * capped at the shell, so "off the edge" became a 80pt stub hanging past every other
	 * section with white beyond it — a bleed that stops short reads as a mistake. Letting it
	 * grow to the viewport edge instead would widen the box by a fifth on a large screen, and
	 * object-fit: cover would scale a 1090px source up by that much again and crop the
	 * composition off its marks. Sharing one right edge with the band costs 5% of scale and
	 * nothing else.
	 */
	.oss-hero__visual {
		/* Undoes the tablet `display: contents`, which absolute positioning cannot apply to. */
		display: block;
		position: absolute;
		inset: 0 var(--oss-gutter) 0 auto;
		/*
		 * The gutter comes off the width, not off the left edge: pulling the box left instead
		 * carried the whole picture with it, and the photograph closed on the headline that the
		 * pale wedge is supposed to keep clear of. Trimming the width holds the left edge where
		 * it was and costs 6% of scale.
		 */
		width: calc(95.7% - var(--oss-gutter));
		overflow: hidden;
		display: flex;
		align-items: stretch;
	}

	.oss-hero__image {
		/*
		 * Shown only from here up, where the design's side-by-side composition begins and the
		 * headline sits over the artwork's pale wedge. In the stacked layout below this width
		 * that wedge is a full-width band of nothing, so the artwork stays hidden.
		 *
		 * Fills its box and is cropped top and bottom, which is what the design does: its frame
		 * is wider than the file's own proportion, so the picture is scaled to the width and
		 * loses about 170pt of sky and foreground. Fitting it by height instead left it a
		 * quarter too small with white where the design has photograph.
		 */
		display: block;
		width: 100%;
		height: 100%;
		object-fit: cover;
		/*
		 * 980 x 537pt in the design. The artwork runs from y 101 to y 638 — well below the
		 * stats band's top edge at 536 — because the band is laid OVER its lower portion
		 * rather than sitting beneath it. Measured at x 1440-1495, past the band's right
		 * edge, the artwork is still photograph down to y 638.
		 */
		min-height: 0;
		/*
		 * No clip-path: the diagonal is already part of the designer's artwork. Applying one
		 * here cut the same shape a second time.
		 *
		 * If the editor swaps this image for a plain photograph, the composition loses its
		 * diagonal — which is the correct trade. The alternative is a clip that mangles the
		 * supplied artwork today in order to flatter a hypothetical replacement.
		 */
		object-position: center;
		/* Square, because the artwork runs off the page edge. */
		border-radius: 0;
	}

	/* The benefits panel sits over the image's right side, as drawn. */
	/*
	 * Anchored top and bottom rather than centred with a transform.
	 *
	 * Centring on 50% let the panel grow past the image in both directions once the four
	 * benefits exceeded the image height — the first and last rows were clipped. Insets bound
	 * it to the visual, and the content scrolls in the rare case an editor adds enough
	 * benefits to exceed even that.
	 */
	/*
	 * The panel sits on the photograph and lands on the stats band: rounded at the top, square
	 * at the bottom, so the two teal shapes read as one continuous column.
	 */
	.oss-hero__benefits {
		position: absolute;
		/*
		 * Design: panel x 1134..1432, y 130..538 on the 1500pt canvas — 298 wide, starting 28
		 * below the artwork's top edge and ending exactly on the stats band's top, so the two
		 * teal shapes meet and read as one.
		 *
		 * Anchored at the bottom only. Pinning both edges fixed the panel's height, which meant
		 * any benefit that wrapped one line further than the design's — a longer title, a
		 * larger text size, a fifth entry — overflowed and the panel grew a scrollbar. Growing
		 * upwards from the band instead, it is always exactly as tall as its contents.
		 */
		bottom: var(--oss-stats-overlap);
		/*
		 * Flush with the artwork's own right edge — which now lands on the container line, so
		 * the panel, the picture, the stats band and the card row all share it.
		 */
		right: 0;
		/*
		 * Held at the design's 298pt on every desktop rather than tracking the artwork's width.
		 * Letting it shrink cost it the text column its four benefits need, and they wrapped to
		 * three lines each and overflowed the panel's fixed height.
		 */
		width: min(298px, 38%);
		margin: 0;
		padding: 11px 26px;
		display: flex;
		flex-direction: column;
		/* Back to separator lines, not the tablet grid's gap. */
		gap: 0;
		background: var(--oss-overlay);
		backdrop-filter: blur(2px);
		/*
		 * Square along the bottom, where the panel meets the stats band.
		 *
		 * The design's two teal shapes butt together into one column; rounding the panel's lower
		 * corners left a pair of notches on that seam and broke the join.
		 */
		border-radius: var(--oss-radius-lg) var(--oss-radius-lg) 0 0;
	}

	/*
	 * Sized so four benefits — the number the design shows — fit the panel without scrolling.
	 * A fifth scrolls rather than being clipped, which is the acceptable degradation.
	 */
	/*
	 * Item metrics measured from the design: 102pt pitch, 71pt of content, 40pt icon, 20pt
	 * gap between icon and text, title 15.5px/1.31, body 12.4px/1.27.
	 */
	/*
	 * Scaled with the viewport rather than fixed, because the panel's height is fixed by the
	 * artwork it sits in. At the design's 1500 these clamps land on the measured values; below
	 * it the panel is both shorter and narrower, and at 1280 the fixed values overflowed — the
	 * first benefit's icon and title were cut off at the top edge.
	 */
	/*
	 * Row metrics measured off the design's four benefits: a 102pt pitch made of 71pt of text
	 * and 31pt of air, a 44pt icon 18pt clear of the text, titles 15.5px/1.25 and bodies
	 * 12.3px/1.25. Set smaller than this, the four rows only filled two thirds of the panel and
	 * floated in the middle of it.
	 */
	.oss-hero__benefit {
		gap: 18px;
		padding-block: 15px;
	}

	.oss-hero__benefit + .oss-hero__benefit {
		border-top: 1px solid rgba(255, 255, 255, 0.25);
	}

	.oss-hero__benefit-icon {
		width: 44px;
		height: 44px;
	}

	.oss-hero__benefit-title {
		margin-bottom: 1px;
		font-size: 15.5px;
		line-height: 1.25;
	}

	.oss-hero__benefit-text {
		font-size: 12.3px;
		line-height: 1.25;
	}

	.oss-stats__list {
		/*
		 * Square where the benefits panel lands on it.
		 *
		 * The design rounds this corner, but there the artwork carries on past the band and
		 * fills it. Here the picture stops on the same line, so a rounded corner under a
		 * square-bottomed panel cut a notch of page white out of the seam.
		 */
		border-top-right-radius: 0;
		grid-template-columns: repeat(4, minmax(0, 1fr));
		gap: var(--oss-space-5);
		/*
		 * Even top and bottom. The design's own 16/27 split came from its labels sitting on one
		 * line more than ours do; copied literally it just read as a band pinned too high.
		 */
		padding: 22px var(--oss-space-6);
	}

	.oss-stats__item {
		gap: 28px;
	}

	/* A quarter larger than the design's 48, so the figures carry across the band's width. */
	.oss-stats__icon {
		width: 60px;
		height: 60px;
	}

	/* Hairline dividers between figures, matching the design. */
	.oss-stats__item + .oss-stats__item {
		border-left: 1px solid rgba(255, 255, 255, 0.28);
		padding-left: var(--oss-space-5);
	}
}

/* ---- Service cards ------------------------------------------------------ */

.oss-services {
	padding-block: var(--oss-space-6);
	background: var(--oss-surface);
}

.oss-services__inner {
	max-width: var(--oss-shell);
	margin: 0 auto;
	padding-inline: var(--oss-gutter-sm);
}

/*
 * Auto-fit rather than a fixed five columns.
 *
 * The design shows five, but the count is editorial: the grid takes as many as fit at a
 * sensible minimum width and wraps the rest, so four or six read as deliberate instead of
 * broken (FR-012).
 */
.oss-services__list {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--oss-gap-sm);
	margin: 0;
	padding: 0;
	list-style: none;
}

.oss-services__item {
	display: flex;
}

.oss-service {
	position: relative;
	display: flex;
	flex-direction: column;
	width: 100%;
	padding: var(--oss-space-4);
	overflow: hidden;
	background: var(--oss-bg);
	border-radius: var(--oss-radius);
	color: var(--oss-text);
	text-decoration: none;
	transition: transform var(--oss-transition), box-shadow var(--oss-transition);
}

a.oss-service:hover,
a.oss-service:focus-visible {
	transform: translateY(-2px);
	box-shadow: var(--oss-shadow-raised);
}

/*
 * The photograph sits behind the text, anchored to the card's foot as in the design.
 *
 * Not shown below the tablet breakpoint. One card per row makes the card wide and short, and
 * the picture's 70% then starts above the description — grey text on a grey photograph, for
 * five cards' worth of screen. Narrow layouts get the card as text only: icon, title,
 * description, and the reader gets through all five in one screen.
 *
 * Same trade-off as the hero artwork above: hidden with display, so one template serves every
 * width, at the cost of the browser still downloading the image.
 */
.oss-service__bg {
	display: none;
	position: absolute;
	inset-inline: 0;
	bottom: 0;
	width: 100%;
	height: 70%;
	object-fit: cover;
	object-position: center bottom;
	pointer-events: none;
}

/*
 * Icon beside the title, description beneath both — as drawn.
 *
 * Measured from the design: the icon sits at the card's left padding with the two-line title
 * starting 14pt to its right on the same rows, and the description runs the card's full width
 * below them. Stacking the icon above the title, as this first did, made every card a good
 * 60pt taller than the design's 201.
 *
 * A grid rather than a nested row, so no wrapper element is needed around icon and title.
 */
.oss-service__body {
	position: relative;
	display: grid;
	grid-template-columns: auto 1fr;
	align-items: center;
	column-gap: var(--oss-gap-sm);
	row-gap: var(--oss-space-2);
}

.oss-service__icon {
	grid-column: 1;
	width: 44px;
	height: 44px;
	object-fit: contain;
}

/*
 * Spans the card when there is no icon, so an iconless card reads as deliberate rather than
 * indented past an empty column.
 */
.oss-service__title {
	grid-column: 1 / -1;
	/*
	 * Body size, not the 17px card-title size: measured off the design, "Підтримка громад" is
	 * 151pt wide in a 156pt column, which is 15px Montserrat Bold. At 17px that title took a
	 * third line and the card grew past the design's height.
	 */
	font-size: var(--oss-fs-base);
	font-weight: var(--oss-fw-bold);
	line-height: var(--oss-lh-snug);
	color: var(--oss-primary);
}

/*
 * Keyed off the card having an icon rather than the title following one.
 *
 * The site's lazy-loading plugin inserts a <noscript> fallback after every image, so the icon
 * and the title are no longer adjacent siblings in the delivered markup and `+` never matched.
 * Anything in this theme that depends on two elements being adjacent has the same trap.
 */
.oss-service__body:has(.oss-service__icon) .oss-service__title {
	grid-column: 2;
}

.oss-service__text {
	grid-column: 1 / -1;
	font-size: var(--oss-fs-xs);
	line-height: var(--oss-lh-base);
	color: var(--oss-text);
}

@media (min-width: 768px) {
	.oss-services__inner {
		padding-inline: var(--oss-gutter-md);
	}

	/*
	 * Cap the card width so a lone service does not stretch across the whole row.
	 *
	 * With auto-fit, a single item's track expands to the full container: tested with one
	 * service, the card spanned 1280px with its text stranded at the left. The cap is above
	 * the ~248px five cards occupy at 1440px, so the design's layout is untouched — it only
	 * takes effect when there are too few cards to fill the row.
	 */
	.oss-service {
		max-width: 340px;
		min-height: 220px;
		padding: var(--oss-space-5);
	}

	.oss-services__list {
		grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
	}

	.oss-service__bg {
		display: block;
		height: 62%;
	}
}

@media (min-width: 1280px) {
	/*
	 * No padding above: the design leaves 27pt between the stats band and the cards, and the
	 * band's own bottom padding already supplies it. A full section's worth here left the cards
	 * floating a hundred points below the band.
	 */
	.oss-services {
		padding-block: 0 var(--oss-space-8);
	}

	.oss-services__inner {
		padding-inline: var(--oss-gutter);
	}

	/* Design: 260 x 201pt cards on a 20pt inset. */
	.oss-service {
		min-height: 200px;
		padding: var(--oss-space-5) 20px;
	}

	/*
	 * Icon and title scale with the row, for the same reason as the hero panel: five cards in
	 * one row leave each title a column that narrows with the viewport, and at 1280 the fixed
	 * sizes pushed every title to four lines. These land on the measured values at 1500.
	 */
	.oss-service__body {
		column-gap: clamp(10px, 0.93vw, var(--oss-gap-sm));
	}

	.oss-service__icon {
		width: clamp(34px, 2.9vw, 44px);
		height: clamp(34px, 2.9vw, 44px);
	}

	.oss-service__title {
		font-size: clamp(13px, 1vw, var(--oss-fs-base));
	}

	.oss-service__bg {
		height: 36%;
	}

	/*
	 * A 200px floor so the design's five cards fit one row at 1440px, where the content
	 * column is 1280px and five cards plus four 24px gaps leave 236px each. At the 240px
	 * tablet floor the fifth card wrapped to a row of its own.
	 *
	 * Still auto-fit rather than a fixed five: a sixth card wraps deliberately instead of
	 * squeezing the row past legibility.
	 */
	.oss-services__list {
		grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
	}
}

/* ---- Promotional strip -------------------------------------------------- */

/*
 * No vertical padding of its own.
 *
 * The service cards above already end with theirs and the news row below begins with its own, so
 * a third measure here would open a gap the page has nowhere else. It also means the section can
 * vanish — which is its normal state — without the two neighbours moving a pixel closer than
 * they sit today.
 */
.oss-promo-strip {
	padding-block: 0;
	background: var(--oss-surface);
}

.oss-promo-strip__inner {
	max-width: var(--oss-shell);
	margin: 0 auto;
	padding-inline: var(--oss-gutter-sm);
}

/*
 * The frame, not the picture: the radius is here so it clips whatever artwork arrives, whatever
 * its own corners look like.
 */
.oss-promo-strip__banner {
	display: block;
	overflow: hidden;
	border-radius: var(--oss-radius);
	transition: box-shadow var(--oss-transition);
}

a.oss-promo-strip__banner:hover,
a.oss-promo-strip__banner:focus-visible {
	box-shadow: var(--oss-shadow-raised);
}

/*
 * The banner keeps its own proportions rather than being cropped to a band this theme chose.
 * An advertiser's layout is composed to its edges, and a fixed height with object-fit would cut
 * the wording off one side of it.
 */
.oss-promo-strip__image {
	display: block;
	width: 100%;
	height: auto;
}

@media (min-width: 768px) {
	.oss-promo-strip__inner {
		padding-inline: var(--oss-gutter-md);
	}
}

@media (min-width: 1280px) {
	.oss-promo-strip__inner {
		padding-inline: var(--oss-gutter);
	}
}

/* ---- News and events row ------------------------------------------------ */

/*
 * The bottom padding is deliberately smaller than the top, here and at every breakpoint below.
 * This row and the publications row beneath it sit on the same surface colour, so their two
 * paddings add up to a single stretch of empty page rather than reading as a boundary between
 * two sections. The client saw the sum, twice, and it is her page.
 */
.oss-news-events {
	padding-block: var(--oss-space-6) var(--oss-space-5);
	background: var(--oss-surface);
}

.oss-news-events__inner {
	max-width: var(--oss-shell);
	margin: 0 auto;
	padding-inline: var(--oss-gutter-sm);
	display: flex;
	flex-direction: column;
	gap: var(--oss-gap);
}

/*
 * Both panels are the same object: a grey rounded card with a heading row and an "all …" link.
 * Only their contents differ, so the shared parts are styled once here.
 */
.oss-panel {
	min-width: 0;
	padding: var(--oss-space-5) var(--oss-space-4);
	background: var(--oss-bg);
	border-radius: var(--oss-radius-lg);
}

/*
 * The "all …" link centres on the heading rather than sharing its baseline.
 *
 * Baseline alignment lines the two up by their feet, and since the heading is 26px against the
 * link's 14px, that left the link sitting visibly below the heading's middle. The design centres
 * them.
 */
.oss-panel__head,
.oss-section__head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--oss-space-3);
	margin-bottom: var(--oss-space-5);
}

/*
 * The heading row is the same object whether it heads a panel inside a row or a section across
 * the page — a title on the left, an "all …" link on the right, centred on one another. Only
 * the container differs, so the two share these rules rather than repeating them.
 */
.oss-panel__title,
.oss-section__title {
	margin: 0;
	color: var(--oss-primary);
	font-size: clamp(20px, 4.4vw, var(--oss-fs-h2));
	font-weight: var(--oss-fw-bold);
	line-height: var(--oss-lh-tight);
	text-transform: uppercase;
}

/*
 * The nudge is optical, not geometric.
 *
 * Flex centring lines up the two line boxes, but the heading is uppercase — no descenders — so
 * its ink sits above the middle of its own box, while the link's descenders pull its ink down.
 * Raising the link by a pixel and a half puts the two runs of ink on the same centre, which is
 * what the eye reads as centred. It is a transform so it costs the row no height.
 */
.oss-panel__more,
.oss-section__more {
	color: var(--oss-muted);
	font-size: var(--oss-fs-sm);
	text-decoration: none;
	transform: translateY(-1.5px);
	transition: color var(--oss-transition);
}

.oss-panel__more:hover,
.oss-panel__more:focus-visible,
.oss-section__more:hover,
.oss-section__more:focus-visible {
	color: var(--oss-primary);
	text-decoration: underline;
}

/* ---- Carousel and news cards -------------------------------------------- */

/*
 * The carousel scaffolding — viewport, track, item, arrows — is named for what it is rather
 * than for the news panel it was first written for, because the initiatives row now pages the
 * same way. The card inside it stays `oss-news-card`: both rows show news posts, and an
 * initiative is one of them, filed under its own category.
 */

/*
 * The viewport is what the arrows sit against.
 *
 * They are placed outside the cards, as drawn, so the padding here is what reserves their room
 * — without it an absolutely positioned arrow would sit on top of the first card's thumbnail.
 */
.oss-carousel__viewport {
	position: relative;
}

/*
 * The room is reserved only where there are arrows to put in it.
 *
 * The class is set by the script when it pages the track, and removed when the cards already
 * fit — a section with one card would otherwise sit inset from a heading that is not, which
 * reads as a misalignment rather than as a carousel with nothing to scroll.
 *
 * The arrows live in this padding at every width. Overlaid on the cards instead they sat on
 * the thumbnail and, on a phone, on the second and third lines of the title.
 */
.oss-carousel__viewport--paged {
	padding-inline: 30px;
}

/*
 * Before Slick initialises — and permanently, if it never does — the cards are a plain stack.
 * Slick replaces this with its own track, so nothing here may depend on the children being
 * direct siblings.
 */
/*
 * Scoped away once Slick takes over.
 *
 * The child theme's stylesheet loads after the parent's vendor.css, and `.oss-carousel__list` and
 * `.slick-slider` have the same specificity — so an unscoped `display: flex` here wins and the
 * initialised track collapses. The negation hands the element back to Slick the moment it is
 * initialised, while keeping the readable stack for the no-script case.
 */
.oss-carousel__list:not(.slick-initialized) {
	display: flex;
	flex-direction: column;
	gap: var(--oss-gap-sm);
}

.oss-carousel__item {
	min-width: 0;
	padding: var(--oss-space-2);
}

/*
 * One page's worth, while the carousel is still on its way.
 *
 * Slick cannot run before jQuery has loaded from the footer, and until it does the stylesheet
 * lays every card out — eight of them, two rows deep — which then snapped to one row on init.
 * Showing only what the first page will hold makes the arrival of the carousel invisible.
 *
 * The counts mirror CAROUSEL_SHAPES in home.js: four to a page from 1200px, two from 768, one
 * below. Both carousels page the same number at the same widths, so one set of rules serves
 * them; if the two ever diverge, these become per-section.
 *
 * Three conditions, each load-bearing: `.oss-js` so a browser without scripting keeps every
 * card, `--ready` for the case where scripting is on but Slick never arrived, and
 * `:not(.slick-initialized)` to hand the track back the moment it is paged.
 */
.oss-js .oss-carousel__list:not(.slick-initialized):not(.oss-carousel__list--ready) .oss-carousel__item:nth-child(n+2) {
	display: none;
}

@media (min-width: 768px) {
	.oss-js .oss-carousel__list:not(.slick-initialized):not(.oss-carousel__list--ready) .oss-carousel__item:nth-child(n+3) {
		display: none;
	}
}

@media (min-width: 1200px) {
	.oss-js .oss-carousel__list:not(.slick-initialized):not(.oss-carousel__list--ready) .oss-carousel__item:nth-child(n+5) {
		display: none;
	}
}

/*
 * Stacked on a phone, side by side from the tablet up.
 *
 * The design's card is a thumbnail beside three lines of text. At 375 that leaves the text
 * about 130px once the carousel's arrows have taken their room, and the title broke after one
 * word per line. Putting the picture above the text costs vertical space the phone has and
 * gives the title the card's full width.
 */
.oss-news-card {
	display: flex;
	flex-direction: column;
	gap: var(--oss-space-3);
	align-items: stretch;
	color: var(--oss-text);
	text-decoration: none;
}

/* Full width above the text on a phone; the design's fixed thumbnail from the tablet up. */
.oss-news-card__thumb {
	flex: 0 0 auto;
	width: 100%;
	height: 160px;
	object-fit: cover;
	border-radius: var(--oss-radius-sm);
	background: var(--oss-surface);
}

/*
 * Drawn, not fetched: a news item with no featured image keeps the row's height and alignment
 * without a placeholder file to ship, and without ever rendering a broken image (Edge Cases).
 */
.oss-news-card__thumb--empty {
	display: block;
	border: 1px solid var(--oss-border);
	background: linear-gradient(135deg, var(--oss-surface), var(--oss-bg-alt));
}

.oss-news-card__body {
	display: flex;
	flex-direction: column;
	gap: var(--oss-space-2);
	min-width: 0;
}

.oss-news-card__category {
	color: var(--oss-primary);
	font-size: var(--oss-fs-xs);
	font-weight: var(--oss-fw-bold);
	line-height: var(--oss-lh-snug);
	text-transform: uppercase;
}

/*
 * Clamped to three lines.
 *
 * News titles on this site run to 180 characters. Left to wrap, one long title made its card
 * twice the height of the three beside it and broke the 2x2 grid the design draws (Edge Cases).
 * Clamping keeps every row the same height and costs only the tail of an unusually long title,
 * which the card is a link to anyway.
 */
.oss-news-card__title {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	overflow: hidden;
	font-size: var(--oss-fs-sm);
	font-weight: var(--oss-fw-bold);
	line-height: var(--oss-lh-snug);
}

.oss-news-card:hover .oss-news-card__title,
.oss-news-card:focus-visible .oss-news-card__title {
	color: var(--oss-primary);
}

.oss-news-card__date {
	color: var(--oss-muted);
	font-size: var(--oss-fs-xs);
	line-height: var(--oss-lh-snug);
}

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

/*
 * Real buttons rather than Slick's default markup, so they are in the tab order, carry a
 * translated label, and show a focus ring like every other control in the redesign.
 */
.oss-carousel__arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: var(--oss-surface);
	box-shadow: var(--oss-shadow-card);
	color: var(--oss-primary);
	line-height: 1;
	cursor: pointer;
	transition: background var(--oss-transition), color var(--oss-transition);
}

/* Half the button, so the mark sits in the circle with even air around it. */
.oss-carousel__chevron {
	display: block;
	width: 50%;
	height: 50%;
}

.oss-carousel__arrow:hover {
	background: var(--oss-primary);
	color: var(--oss-surface);
}

/*
 * Slick disables rather than hides an arrow at either end of a finite carousel. Dimming it
 * rather than removing it keeps the control's position stable and the tab order unchanged.
 */
.oss-carousel__arrow.slick-disabled {
	opacity: 0.35;
	cursor: default;
}

/*
 * Offsets are measured from the track, not from the viewport.
 *
 * Slick appends its arrows to the element it initialises and gives that element
 * `position: relative`, so it — not `.oss-carousel__viewport` — is what an absolute offset here
 * resolves against, whatever this stylesheet declares as positioned. On a narrow screen there
 * is no room beside the track, so the arrows sit on its edges; the desktop rule below pulls
 * them out into the viewport's padding, where the design draws them clear of the cards.
 */
.oss-carousel__arrow--prev {
	left: -30px;
}

.oss-carousel__arrow--next {
	right: -30px;
}

/* ---- Events ------------------------------------------------------------- */

.oss-events__list {
	display: flex;
	flex-direction: column;
	gap: var(--oss-gap-sm);
	margin: 0;
	padding: 0;
	list-style: none;
}

.oss-event {
	display: flex;
	gap: var(--oss-space-4);
	align-items: stretch;
	color: var(--oss-text);
	text-decoration: none;
}

/*
 * The date block is the panel's one piece of solid colour, as in the design. It is a <time>,
 * so the day and month it splits across two lines are still one machine-readable date.
 */
.oss-event__date {
	flex: 0 0 auto;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	width: 84px;
	padding: var(--oss-space-3) var(--oss-space-2);
	background: var(--oss-primary);
	border-radius: var(--oss-radius);
	color: var(--oss-surface);
	text-align: center;
}

.oss-event__day {
	color: var(--oss-surface);
	font-size: var(--oss-fs-display);
	font-weight: var(--oss-fw-bold);
	line-height: 1.05;
}

.oss-event__month {
	color: var(--oss-surface);
	font-size: var(--oss-fs-sm);
	line-height: var(--oss-lh-snug);
}

.oss-event__body {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--oss-space-2);
	min-width: 0;
}

.oss-event__badge {
	padding: var(--oss-space-1) var(--oss-space-3);
	background: var(--oss-accent);
	border-radius: var(--oss-radius-sm);
	color: var(--oss-primary-dark);
	font-size: var(--oss-fs-xs);
	font-weight: var(--oss-fw-bold);
	line-height: var(--oss-lh-snug);
	text-transform: uppercase;
}

/* Clamped for the same reason as the news titles, and to the two lines the design shows. */
.oss-event__title {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	overflow: hidden;
	font-size: var(--oss-fs-md);
	font-weight: var(--oss-fw-bold);
	line-height: var(--oss-lh-snug);
}

.oss-event:hover .oss-event__title,
.oss-event:focus-visible .oss-event__title {
	color: var(--oss-primary);
}

/*
 * One fragment per line on a phone, where the design's single line does not fit.
 *
 * The separator goes with it: a pipe only means something between two things on the same line,
 * and every attempt to keep it while wrapping left it stranded at the end of one line or the
 * start of the next.
 */
.oss-event__meta {
	display: flex;
	flex-direction: column;
	color: var(--oss-muted);
	font-size: var(--oss-fs-sm);
	line-height: var(--oss-lh-snug);
}

.oss-event__sep {
	display: none;
	color: var(--oss-border);
}

@media (min-width: 768px) {
	.oss-news-events__inner {
		padding-inline: var(--oss-gutter-md);
	}

	.oss-panel {
		padding: var(--oss-space-6) var(--oss-space-5);
	}

	.oss-news-card {
		flex-direction: row;
		align-items: flex-start;
		gap: var(--oss-space-4);
	}

	.oss-news-card__thumb {
		width: 160px;
		height: 100px;
	}

	.oss-carousel__arrow {
		width: 36px;
		height: 36px;
	}

	/* Room for the design's single line, so the separator earns its place again. */
	.oss-event__meta {
		flex-direction: row;
		flex-wrap: wrap;
	}

	.oss-event__sep {
		display: inline;
		margin-inline: var(--oss-space-3);
	}
}

/*
 * Side by side only from the desktop breakpoint.
 *
 * Below it the events panel's date block, badge and price line have to share a column with the
 * news thumbnails, and both panels lose more than the row saves — so they stack, which is what
 * research R8 specifies for this row.
 *
 * Flex rather than a two-column grid: when one panel finds no content and returns early, the
 * other takes the whole row instead of leaving a hole where its neighbour would have been.
 */
@media (min-width: 1200px) {
	.oss-news-events__inner {
		flex-direction: row;
		align-items: flex-start;
		gap: var(--oss-gap);
	}

	/* Roughly the design's 2:1 split, measured off its two panels at 800pt and 385pt wide. */
	.oss-news {
		flex: 2 1 0;
	}

	.oss-events {
		flex: 1 1 0;
	}

	/*
	 * The padding is the room the arrows occupy; they are then pulled into it by their own
	 * width plus a little air, so the cards keep their full width and nothing overlaps.
	 */
	.oss-carousel__viewport--paged {
		padding-inline: 44px;
	}

	.oss-carousel__arrow--prev {
		left: -42px;
	}

	.oss-carousel__arrow--next {
		right: -42px;
	}
}

@media (min-width: 1280px) {
	.oss-news-events__inner {
		padding-inline: var(--oss-gutter);
	}
}

/* ---- Publications ------------------------------------------------------- */

/* Top padding kept in step with the news row's bottom — see the note there. */
.oss-publications {
	padding-block: var(--oss-space-5) var(--oss-space-6);
	background: var(--oss-surface);
}

.oss-publications__inner {
	max-width: var(--oss-shell);
	margin: 0 auto;
	padding-inline: var(--oss-gutter-sm);
}

/*
 * Auto-fit for the same reason the service cards use it: five is what the designer drew, not a
 * structural number. The minimum is set by the cover — below about 190px a magazine cover stops
 * being legible as a cover — so the row drops to four, three, two rather than shrinking past
 * that (FR-012).
 */
.oss-publications__list {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
	gap: var(--oss-gap-sm);
	margin: 0;
	padding: 0;
	list-style: none;
}

.oss-publications__item {
	display: flex;
	min-width: 0;
}

/*
 * The card is the white panel; the book stands on it, not inside it.
 *
 * The design draws a cover floating above a rounded panel whose top edge crosses the foot of the
 * book. Built as one box with the picture inset at the top — which is what this was — the cover
 * became a picture in a frame, and the row read as five tiles rather than as five books. So the
 * card itself carries no background or border: those belong to the body below, and the cover
 * sits free above it.
 */
.oss-publication {
	display: flex;
	flex-direction: column;
	width: 100%;
	/*
	 * A ceiling, not a size. With five cards the track is narrower than this and the cap never
	 * applies; with one it stops a single issue from stretching its cover across the full 1340px
	 * column, which is what an unbounded `1fr` track did (FR-012, Edge Cases).
	 */
	max-width: 320px;
}

/*
 * A fixed proportion rather than the cover's own.
 *
 * The 46 issues were photographed and scanned over four years and their aspect ratios differ by
 * a third; left to themselves the five cards in a row ended at five different heights. Fixing
 * the frame and cropping into it is what keeps the row a row.
 */
/*
 * A frame of fixed proportion with the picture stretched inside it.
 *
 * The 46 issues were photographed over four years and their files differ in shape by a third;
 * left to themselves the five cards in a row ended at five different heights. The ratio is held
 * by padding rather than by `aspect-ratio` because the site's lazy-loading plugin swaps each
 * `src` for an inline SVG placeholder carrying the file's own dimensions, and that placeholder
 * won the ratio back — the covers rendered portrait however the property was declared.
 *
 * 80% of the width is the design's 5:4 cover frame.
 */
/*
 * The frame is the book's height plus the room the badge needs above it.
 *
 * The artwork is 936x1260, and it is drawn at 72% of the card's width — so the book itself is
 * 97% of that width tall. A frame cut to the cover's own 134.6% therefore left a quarter of its
 * height as empty grey above the book, which is the gap the client spotted. 104% is the book
 * plus the badge's row, and nothing else.
 *
 * It was 80% — a landscape window — which cropped every portrait cover to a band across its
 * middle and lost both the masthead and the year. The client caught it against the PDF: "а
 * вертикально обкладинки не можна? вони будуть зрізатись?"
 */
.oss-publication__cover {
	position: relative;
	padding-top: 104%;
	/*
	 * A grey panel behind the book, rounded like the white one below it.
	 *
	 * The design puts the cover on a tinted rectangle rather than on the page: it separates the
	 * artwork from the section's white background, and it gives the cut-out mockups — which have
	 * no background of their own — something to stand against. Its foot is hidden by the body.
	 */
	background: var(--oss-bg);
	border-radius: var(--oss-radius);
}

/*
 * Contained rather than cropped.
 *
 * The covers are not all the same shape — the designer's are 0.74 wide to tall, the guides
 * already published are 0.71 — and `cover` would trim the difference off the bottom of a real
 * one, which is where the year sits. Contained, the odd cover leaves a couple of per cent of
 * background at its sides and nothing is ever cut off.
 */
/*
 * The book stands in the middle of the card, not across it.
 *
 * At the full width of the card the covers crowded their own row and left no page between them;
 * the design gives each one a wide margin of the grey panel on both sides, and drops the type
 * badge onto the book's top-left corner. The width is measured off the PDF.
 */
/*
 * Makes the whole cover panel a link to the publication (client request: open on the cover, not
 * only the "Докладніше" link). Transparent and z-index 1, so it sits under the badge (z-index 2,
 * still visible and on top) and over the panel, catching a click anywhere on the book or its grey
 * margin. The book image lives inside it and positions exactly as before.
 */
.oss-publication__cover-link {
	position: absolute;
	inset: 0;
	z-index: 1;
	display: block;
	border-radius: var(--oss-radius);
}

.oss-publication__image {
	position: absolute;
	inset: 0;
	display: block;
	width: 72%;
	height: 100%;
	margin-inline: auto;
	object-fit: contain;
	object-position: center bottom;
	transition: opacity var(--oss-transition);
}

.oss-publication__cover-link:hover .oss-publication__image {
	opacity: 0.9;
}

.oss-publication__image--empty {
	background: var(--oss-bg);
	border-radius: var(--oss-radius-sm);
}

/*
 * A pill, the size the design draws it, sitting over the head of the book.
 *
 * It reads as a label attached to the publication rather than as a corner sticker on a tile,
 * which is what a small square badge inside a framed picture looked like.
 */
.oss-publication__badge {
	position: absolute;
	/* Above the cover, which fills the same frame and would otherwise paint over it. */
	z-index: 2;
	top: var(--oss-space-2);
	left: 0;
	padding: var(--oss-space-2) var(--oss-space-4);
	background: var(--oss-primary);
	border-radius: 999px;
	color: var(--oss-surface);
	font-size: var(--oss-fs-xs);
	font-weight: var(--oss-fw-bold);
	letter-spacing: 0.02em;
}

/*
 * The panel, overlapping the foot of the cover.
 *
 * The overlap is what makes the book stand on the card instead of floating above a separate
 * tile; it is also what hides the mockup's own bottom shadow, which otherwise ends in mid-air.
 * Twelve pixels, not twenty-four: deeper than that and the panel starts eating the year printed
 * at the foot of a guide's cover.
 */
.oss-publication__body {
	position: relative;
	z-index: 1;
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: var(--oss-space-2);
	margin-top: calc(var(--oss-space-3) * -1);
	padding: var(--oss-space-4);
	background: var(--oss-surface);
	border: 1px solid var(--oss-border);
	border-radius: var(--oss-radius);
	transition: box-shadow var(--oss-transition);
}

.oss-publication:hover .oss-publication__body {
	box-shadow: var(--oss-shadow-card);
}

/*
 * Clamped to four lines, like the news card and for the same reason.
 *
 * The design's cards are issue numbers — "ЗМІСТ № 7/2026", three words — and nothing needed
 * constraining. The pinned guides carry their full published names instead: "ІНТЕРАКТИВНИЙ
 * ПОСІБНИК «Екологічна документація у зразках та формах»" runs to five lines in a 190px card and
 * pushed its neighbour's actions a row further down. Four lines is where the longest of the four
 * guides the site sells still reads as a title rather than as a paragraph.
 */
.oss-publication__title {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 4;
	line-clamp: 4;
	overflow: hidden;
	margin: 0;
	font-size: var(--oss-fs-md);
	font-weight: var(--oss-fw-bold);
	line-height: var(--oss-lh-snug);
}

.oss-publication__title a {
	color: var(--oss-primary);
	text-decoration: none;
}

.oss-publication__title a:hover,
.oss-publication__title a:focus-visible {
	text-decoration: underline;
}

.oss-publication__meta {
	margin: 0;
	color: var(--oss-muted);
	font-size: var(--oss-fs-sm);
}

/*
 * The actions are pushed to the foot by the auto margin, so cards whose titles run to one line
 * and cards whose titles run to three still line their buttons up with one another.
 */
.oss-publication__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--oss-space-1);
	margin-top: auto;
	padding-top: var(--oss-space-3);
}

/*
 * Smaller than a hero CTA, because it has to share a 190px card with its own "Докладніше".
 * At the default button size the two never fitted on one line and every second card wrapped,
 * which left the row of five with its buttons on two different baselines.
 */
.oss-publication__actions .oss-btn {
	padding: var(--oss-space-2);
	font-size: var(--oss-fs-xs);
}

.oss-publication__more {
	color: var(--oss-muted);
	/* The same size as its neighbouring button's label, so the two read as one row of actions. */
	font-size: var(--oss-fs-xs);
	white-space: nowrap;
	text-decoration: none;
	transition: color var(--oss-transition);
}

.oss-publication__more:hover,
.oss-publication__more:focus-visible {
	color: var(--oss-primary);
	text-decoration: underline;
}

/* ---- Initiatives -------------------------------------------------------- */

.oss-initiatives {
	/*
	 * No padding above: the featured issue this row follows already ends with its own, and the
	 * two together read as a gap rather than as a break between sections. Below it is the
	 * footer, which needs the full measure.
	 */
	padding-block: 0 var(--oss-space-7);
	background: var(--oss-surface);
}

.oss-initiatives__inner {
	max-width: var(--oss-shell);
	margin: 0 auto;
	padding-inline: var(--oss-gutter-sm);
}

/*
 * The card stays stacked here at every width.
 *
 * From 768px up a news card puts its 160px thumbnail beside its text, which is right in a panel
 * a third of the page wide showing one card per row. Across the page the same card is one of
 * four, about 300px each, and the side-by-side arrangement leaves the title 120px — the shape
 * the phone layout exists to avoid.
 */
/*
 * Unpaged — one screenful of cards, or no script at all — the row is a plain grid.
 *
 * Fixed tracks rather than auto-fit: with two cards auto-fit gives each half the page, and the
 * pair reads as a different section from the four the row usually holds. Fixed tracks keep a
 * card the same size whatever the count, and a short row simply ends early (FR-012).
 */
.oss-initiatives .oss-carousel__list:not(.slick-initialized) {
	display: grid;
	grid-template-columns: 1fr;
	gap: 0;
}

@media (min-width: 768px) {
	.oss-initiatives .oss-carousel__list:not(.slick-initialized) {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (min-width: 1200px) {
	.oss-initiatives .oss-carousel__list:not(.slick-initialized) {
		grid-template-columns: repeat(4, 1fr);
	}
}

.oss-initiatives .oss-news-card {
	flex-direction: column;
	align-items: stretch;
	gap: var(--oss-space-3);
}

.oss-initiatives .oss-news-card__thumb {
	width: 100%;
	height: 180px;
}

@media (min-width: 768px) {
	.oss-initiatives__inner {
		padding-inline: var(--oss-gutter-md);
	}
}

@media (min-width: 1280px) {
	.oss-initiatives__inner {
		padding-inline: var(--oss-gutter);
	}
}

/* ---- Promotional cells -------------------------------------------------- */

/*
 * The row that closes the page. It takes the bottom measure the initiatives above gave up to it:
 * that section ends flush because the footer used to follow it directly, so the space before the
 * footer is supplied here instead — and returns to the initiatives untouched when no campaign is
 * running and this section does not render.
 */
.oss-promos {
	padding-block: 0 var(--oss-space-7);
	background: var(--oss-surface);
}

.oss-promos__inner {
	max-width: var(--oss-shell);
	margin: 0 auto;
	padding-inline: var(--oss-gutter-sm);
}

/*
 * A centred flex row rather than the auto-fit grid the rest of the page uses.
 *
 * Three is what the client asked for, not a structural number, and campaigns expire one at a
 * time — so two live cells is the ordinary state, not the exception. Under auto-fit the row
 * kept its three tracks: two cards clung to the left with a third of the page empty beside
 * them, which reads as a card that failed to load rather than as a row of two (FR-012).
 *
 * Flex items grow into what is there and the row centres what is left, so two cells sit as a
 * pair and one sits alone in the middle. The cap below is what stops them growing without end.
 */
.oss-promos__list {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--oss-gap);
	margin: 0;
	padding: 0;
	list-style: none;
}

.oss-promos__item {
	display: flex;
	flex: 1 1 300px;
	min-width: 0;
}

.oss-promo {
	display: flex;
	flex: 1;
	flex-direction: column;
	overflow: hidden;
	background: var(--oss-bg);
	border-radius: var(--oss-radius);
	color: var(--oss-text);
	text-decoration: none;
	transition: transform var(--oss-transition), box-shadow var(--oss-transition);
}

a.oss-promo:hover,
a.oss-promo:focus-visible {
	transform: translateY(-2px);
	box-shadow: var(--oss-shadow-raised);
}

.oss-promo__media {
	position: relative;
	display: block;
}

/*
 * Cropped, unlike the strip above: three cells side by side have to agree on where their text
 * starts, and an uploaded picture of any proportion will not do that by itself.
 *
 * A ratio rather than a height, because the cell's width depends on how many campaigns are
 * running. At a fixed 180px a lone 640px cell was a letterbox slot 3.5:1 wide, which cropped
 * everything but the middle of the picture; the ratio keeps the same shape at every count.
 */
/*
 * `height: auto` is load-bearing, not tidiness. The template writes width and height attributes
 * so the browser can reserve the box before the file arrives (FR-022), and those attributes are
 * presentational hints: they set a used height, and `aspect-ratio` only takes effect when one
 * dimension is auto. Without this line the ratio was computed and ignored, and a 1205x803 upload
 * rendered 803px tall inside a 346px card — the picture spilling out from under its own text.
 */
.oss-promo__image {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 9;
	object-fit: cover;
}

.oss-promo__badge {
	position: absolute;
	top: var(--oss-space-3);
	left: var(--oss-space-3);
	padding: var(--oss-space-1) var(--oss-space-3);
	background: var(--oss-accent);
	border-radius: var(--oss-radius-sm);
	color: var(--oss-primary-dark);
	font-size: var(--oss-fs-xs);
	font-weight: var(--oss-fw-bold);
	line-height: var(--oss-lh-snug);
	text-transform: uppercase;
}

/* Without a picture there is no corner to sit in, so the badge leads the text instead. */
.oss-promo__badge--inline {
	position: static;
	align-self: flex-start;
	margin-bottom: var(--oss-space-1);
}

.oss-promo__body {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: var(--oss-space-2);
	padding: var(--oss-space-4);
}

.oss-promo__title {
	font-size: var(--oss-fs-md);
	font-weight: var(--oss-fw-bold);
	line-height: var(--oss-lh-snug);
}

a.oss-promo:hover .oss-promo__title,
a.oss-promo:focus-visible .oss-promo__title {
	color: var(--oss-primary);
}

.oss-promo__text {
	color: var(--oss-muted);
	font-size: var(--oss-fs-sm);
	line-height: var(--oss-lh-base);
}

@media (min-width: 768px) {
	.oss-promos__inner {
		padding-inline: var(--oss-gutter-md);
	}

	/*
	 * The cap, set so that a short row still fills the page.
	 *
	 * Two cells at 640 plus the gap come to 1304 of the 1340 column — a pair that reads as the
	 * whole row rather than as two thirds of one. Three cells reach about 430 each and never
	 * meet the cap. A single cell stops at 640 in the middle of the page, which is a feature
	 * card; without a cap it would stretch to 1340 and become a band.
	 */
	.oss-promos__item {
		max-width: 640px;
	}

	.oss-promo__body {
		padding: var(--oss-space-5);
	}
}

@media (min-width: 1280px) {
	.oss-promos__inner {
		padding-inline: var(--oss-gutter);
	}
}

/* ---- Featured issue ----------------------------------------------------- */

.oss-featured {
	padding-block: var(--oss-space-6) var(--oss-space-7);
	background: var(--oss-surface);
}

.oss-featured__inner {
	display: flex;
	flex-direction: column;
	gap: var(--oss-gap);
	max-width: var(--oss-shell);
	margin: 0 auto;
	padding-inline: var(--oss-gutter-sm);
}

.oss-featured__issue {
	display: flex;
	flex-direction: column;
	gap: var(--oss-space-5);
	padding: var(--oss-space-5);
	background: var(--oss-surface);
	border-radius: var(--oss-radius-lg);
	box-shadow: var(--oss-shadow-raised);
}

/*
 * On a phone the cover is centred and the badge sits on its top-right corner.
 *
 * Beside the cover — which is what the wider layout does — the pair is left-aligned in a column
 * the width of the screen, and the artwork ends up hard against the left margin with a stub of
 * badge beside it. Centred, the cover is the block's own object; the badge then has nowhere to
 * go but onto it, and the top right is the corner this magazine keeps clear (the masthead runs
 * along the left edge).
 */
.oss-featured__cover {
	position: relative;
	width: 100%;
	max-width: 230px;
	margin-inline: auto;
}

.oss-featured__image {
	display: block;
	width: 100%;
	max-width: 230px;
	height: auto;
	border-radius: var(--oss-radius-sm);
}

.oss-featured__image--empty {
	aspect-ratio: 3 / 4;
	background: var(--oss-bg);
}

.oss-featured__badge {
	position: absolute;
	z-index: 1;
	top: var(--oss-space-2);
	right: var(--oss-space-2);
	flex: none;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--oss-space-1);
	width: 74px;
	padding: var(--oss-space-2);
	background: var(--oss-badge-bg);
	border-radius: var(--oss-radius);
	color: var(--oss-highlight);
	text-align: center;
}

/*
 * From the tablet up the badge steps off the artwork and stands beside it.
 *
 * There is room for it there, and on a cover it cannot be guaranteed to miss anything: the
 * corner it occupies is clear on this issue and may not be on the next one. The overlay is a
 * phone-width compromise, not the intended arrangement.
 */
@media (min-width: 768px) {
	.oss-featured__cover {
		display: flex;
		align-items: flex-start;
		gap: var(--oss-space-3);
		max-width: none;
		margin-inline: 0;
	}

	.oss-featured__badge {
		position: static;
	}
}

/*
 * The two buttons share the width on a narrow screen, then take their own width once there is
 * room; the tertiary links ride on the same line after them (see .oss-featured__links).
 */
.oss-featured__actions .oss-btn {
	flex: 1 1 0;
	justify-content: center;
}

@media (min-width: 768px) {
	.oss-featured__actions .oss-btn {
		flex: 0 1 auto;
	}
}

.oss-featured__badge-text {
	color: var(--oss-text);
	font-size: 10px;
	font-weight: var(--oss-fw-bold);
	line-height: var(--oss-lh-tight);
}

.oss-featured__body {
	display: flex;
	flex-direction: column;
	gap: var(--oss-space-3);
	min-width: 0;
}

.oss-featured__title {
	margin: 0;
	font-size: clamp(20px, 3.6vw, 28px);
	font-weight: var(--oss-fw-bold);
	line-height: var(--oss-lh-tight);
}

.oss-featured__title a {
	color: var(--oss-primary);
	text-decoration: none;
}

.oss-featured__title a:hover,
.oss-featured__title a:focus-visible {
	text-decoration: underline;
}

.oss-featured__meta {
	margin: 0;
	color: var(--oss-text);
	font-size: var(--oss-fs-lg);
}

.oss-featured__intro {
	margin: 0;
	color: var(--oss-primary);
	font-size: var(--oss-fs-base);
	font-weight: var(--oss-fw-bold);
}

.oss-featured__contents {
	margin: 0;
	padding-left: var(--oss-space-5);
	color: var(--oss-text);
	font-size: var(--oss-fs-base);
	line-height: var(--oss-lh-base);
}

.oss-featured__contents li::marker {
	color: var(--oss-primary);
}

/*
 * Pushed to the foot of the column, level with the contacts' own button.
 *
 * The design puts all three actions on one line, which happens by itself only when the contents
 * list runs to the five entries it was drawn with. An issue with two left its buttons halfway up
 * a column whose neighbour ended at the bottom, and the block read as unfinished rather than as
 * short. Following the list instead of the column made the ragged case the normal one.
 */
.oss-featured__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--oss-space-3) var(--oss-space-5);
	margin-top: auto;
	padding-top: var(--oss-space-4);
}

/*
 * The journal's own navigation, sitting by the meta line — small and muted so it reads as a
 * caption near the title, not a second row of actions competing with the CTA footer
 * (visual-hierarchy). A middot separates the two only when both are present.
 */
.oss-featured__nav {
	margin: 0;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	line-height: 1.6;
}

.oss-featured__link {
	color: var(--oss-muted);
	font-size: var(--oss-fs-sm);
	text-decoration: none;
}

.oss-featured__link:hover,
.oss-featured__link:focus-visible {
	color: var(--oss-primary);
	text-decoration: underline;
}

.oss-featured__link + .oss-featured__link::before {
	content: "·";
	display: inline-block;
	margin: 0 var(--oss-space-2);
	color: var(--oss-muted);
}

.oss-featured__contacts {
	display: flex;
	flex-direction: column;
	gap: var(--oss-space-4);
	font-size: var(--oss-fs-sm);
	line-height: var(--oss-lh-base);
}

.oss-featured__contact-title {
	margin: 0 0 var(--oss-space-1);
	font-weight: var(--oss-fw-bold);
}

.oss-featured__contact-lines {
	margin: 0;
	padding-left: var(--oss-space-5);
	/*
	 * Long addresses break mid-word rather than widening the column past its share of the row.
	 * These are email addresses and phone numbers, which have no spaces to wrap at.
	 */
	overflow-wrap: anywhere;
}

.oss-featured__contact-lines li::marker {
	color: var(--oss-primary);
}

/* Full width on a phone, where two buttons side by side leave neither its own label's room. */
.oss-featured__editorial {
	margin-top: auto;
	text-align: center;
}

/* ---- Icons in buttons --------------------------------------------------- */

.oss-btn--icon {
	gap: var(--oss-space-2);
	font-weight: var(--oss-fw-bold);
}

/*
 * An icon sits beside its label and does not shrink to make room for it.
 *
 * Position and margin are restated deliberately: the parent's unscoped `svg` rule below 450px
 * would otherwise throw this icon off the screen. That correction now covers every SVG in the
 * theme and is explained in full in tokens.css; this rule keeps its own copy so the cart and the
 * flame stay correct even if the icon is ever rendered outside an `oss-` element.
 */
.oss-icon {
	flex: none;
	position: static;
	margin: 0;
}

@media (min-width: 768px) {
	.oss-publications__inner,
	.oss-featured__inner {
		padding-inline: var(--oss-gutter-md);
	}

	/*
	 * The columns stretch rather than sitting at their own heights, so that the auto margins
	 * inside them have a full-height column to push against — that is what puts the copy's
	 * actions and the contacts' button on the same line.
	 */
	.oss-featured__issue {
		display: grid;
		grid-template-columns: auto 1fr;
		align-items: stretch;
		gap: var(--oss-space-6);
		padding: var(--oss-space-6);
	}

	/*
	 * The contacts sit below the copy until the row is wide enough for a third column, and span
	 * both of the ones above them so they are not squeezed into the cover's width.
	 */
	.oss-featured__contacts {
		grid-column: 1 / -1;
		padding-top: var(--oss-space-4);
		border-top: 1px solid var(--oss-border);
	}

	.oss-featured__editorial {
		align-self: flex-start;
	}
}

/*
 * The design's three columns, at the width they were drawn for.
 *
 * Below this the contacts column is under 240px, which breaks every address across three lines,
 * so it goes underneath instead — the same threshold the news and events row uses.
 */
@media (min-width: 1200px) {
	.oss-featured__issue {
		grid-template-columns: auto minmax(0, 1fr) 340px;
	}

	.oss-featured__contacts {
		grid-column: auto;
		height: 100%;
		padding-top: 0;
		padding-left: var(--oss-space-6);
		border-top: 0;
		border-left: 1px solid var(--oss-border);
	}
}

@media (min-width: 1280px) {
	/*
	 * Publications split off from featured here to keep the tightened top padding that pairs
	 * with the news row above it. The rest of the page's rhythm is left alone — the client
	 * pointed at one seam, not at the spacing scale.
	 */
	.oss-publications {
		padding-block: var(--oss-space-5) var(--oss-space-8);
	}

	.oss-featured {
		padding-block: var(--oss-space-6) var(--oss-space-8);
	}

	.oss-publications__inner,
	.oss-featured__inner {
		padding-inline: var(--oss-gutter);
	}

	.oss-publications__list {
		gap: var(--oss-gap);
	}
}

/*
 * Below the design's canvas the artwork is held back off the copy.
 *
 * Its left third is the transparent wedge, so where the photograph starts follows from the box's
 * width: the wider the box, the further left the picture begins. At 1280 the design's proportion
 * put the refinery about 90px inside the headline's column — the diagonal cut across the last
 * word instead of clearing it. Narrowing the box moves the picture right, since it stays anchored
 * to the container's right edge, and costs about a tenth of its scale.
 */
@media (min-width: 1280px) and (max-width: 1439.98px) {
	.oss-hero__visual {
		width: calc(84% - var(--oss-gutter));
	}
}
