/**
 * Central "Hilfe & Angebote" page (page-templates/hilfe-angebote.php).
 * Loaded only on that page. A continuation of the homepage's visual
 * language — same container, tokens, heading sizes, panel color and link
 * styles — just calmer. Eyebrow and the "Kontakt aufnehmen" link style are
 * shared with the homepage in sections.css.
 *
 * Editor-proof by design: no fixed text heights, no per-offer rules,
 * image treatment chosen from the upload's orientation, optional parts
 * collapse without gaps.
 */

.offers-page__inner {
	max-width: var(--container-max-width);
	margin-inline: auto;
	padding-inline: var(--container-padding);
}

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

/* The intro (photo, wash, eyebrow, title, lead) is the shared .page-intro
   component in components.css; the quick overview below runs inside it. */

/* ---------- Quick overview: one full-width frosted strip ---------- */

/*
 * A calm, page-wise carousel: a fixed number of complete entries per view
 * (--per-view; 1 on phones, never a peeking neighbour). The viewport is a
 * native horizontal scroller with mandatory snapping; from 600px it is
 * inset by --quick-gutter so the prev/next chevrons have their own space,
 * while the glass strip and photo keep running full width behind it.
 * assets/js/offers-quick.js adds circular prev/next, dots and status.
 */
.offers-quick {
	/* Upper limit of entries per view; fewer when the titles need the room
	   (--quick-fit below). */
	--per-view: 1;
	--quick-item-pad: var(--container-padding);
	--quick-gutter: 0px;
	/* Same air above the entries and below the dots (or the entries). */
	--quick-pad-y: var(--space-5);
	/* Room of the dots below the entries (only with more than one page). */
	--quick-dots-row: 0px;
	/* Equal air above and below each entry's text block (D-036). */
	--quick-pad-c: var(--quick-pad-y);
	/* Optical centring: the block's box ends below the last baseline
	   (descender and leading), so it moves down by this much — taken from
	   the bottom padding, so the sum and the strip's height stay the same. */
	--quick-pad-optical: 0.1875rem;
	--quick-title-size: clamp(1.25rem, 0.5vw + 1.1rem, 1.375rem);
	/* Georgia bold needs ≈0.55em per character; 0.6 keeps a reserve. */
	--quick-char: 0.6;
	position: relative;
	display: grid;
	grid-template-columns: var(--quick-gutter) minmax(0, 1fr) var(--quick-gutter);
	background-color: var(--glass-surface);
	-webkit-backdrop-filter: var(--glass-blur);
	backdrop-filter: var(--glass-blur);
	border-block: 1px solid var(--glass-edge);
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
	.offers-quick {
		background-color: var(--glass-surface-solid);
	}
}

@media (min-width: 600px) {
	.offers-quick {
		--per-view: 2;
		--quick-item-pad: var(--space-5);
		--quick-gutter: 64px;
		--quick-pad-y: var(--space-6);
	}
}

@media (min-width: 900px) {
	.offers-quick {
		--per-view: 3;
	}
}

/* Desktop: the gutter grows with the page so the entry text lines up with
   the container (and the heading) on wide screens. */
@media (min-width: 1024px) {
	.offers-quick {
		--quick-gutter: max(72px, calc((100vw - var(--container-max-width)) / 2 + var(--container-padding) - var(--quick-item-pad)));
	}
}

@media (min-width: 1280px) {
	.offers-quick {
		--per-view: 4;
		--quick-item-pad: var(--space-5);
	}
}

/*
 * Readability before count (D-032): the viewport is a size container whose
 * font size is the width one entry needs — the longest title on one line
 * (--quick-title-ch, from the template) plus the side padding. Container
 * queries in em then compare the available width with 2, 3, 4 such
 * entries, so the strip shows as many complete entries as fit, never more
 * than --per-view. Pure CSS: no measuring script, no jump after loading.
 *
 * Isolation: that font size is a pure calculation value of this scroll
 * wrapper (no padding, border or text of its own). Its only child, the
 * list, sets the real typography back explicitly; the chevrons, dots and
 * status are siblings outside the wrapper. No visible dimension depends
 * on it.
 */
.offers-quick__viewport {
	container: offers-quick / inline-size;
	grid-column: 2;
	grid-row: 1;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	/* Hides the 1px divider of the first visible entry at the left edge. */
	clip-path: inset(0 0 0 1px);
	font-size: calc(var(--quick-title-ch, 0) * var(--quick-char) * var(--quick-title-size) + 2 * var(--quick-item-pad));
}

.offers-quick__viewport::-webkit-scrollbar {
	display: none;
}

.offers-quick__list {
	display: flex;
	margin: 0;
	padding: 0;
	/* Real typography again (see the viewport above); the body's unitless
	   line-height is inherited as a factor, never as a calculated length. */
	font-size: 1rem;
	list-style: none;
	transition: opacity 0.18s ease;
}

.offers-quick__item {
	--quick-fit: 1;
	--quick-n: min(var(--per-view), var(--offers-count), var(--quick-fit));
	position: relative;
	display: flex;
	flex: 0 0 calc(100% / var(--quick-n));
	min-width: 0;
	/* The dots band belongs to the carousel, not to an offer: it lies in the
	   entry's own bottom padding, outside the link's hit area (D-036). */
	padding-bottom: var(--quick-dots-row);
	scroll-snap-align: start;
}

@container offers-quick (min-width: 2em) {
	.offers-quick__item {
		--quick-fit: 2;
	}
}

@container offers-quick (min-width: 3em) {
	.offers-quick__item {
		--quick-fit: 3;
	}
}

@container offers-quick (min-width: 4em) {
	.offers-quick__item {
		--quick-fit: 4;
	}
}

/* One or two offers: once they all fit (from 600px), a deliberate,
   centered group instead of stretched slots. On phones they stay two
   carousel pages with one complete entry each. */
@media (min-width: 600px) {
	.offers-quick__list.is-few {
		justify-content: center;
	}

	.offers-quick__list.is-few .offers-quick__item {
		max-width: 380px;
	}
}

/* Fine, low-contrast divider between entries, vertically centered on the
   entry's content (the dots' strip below it is left out, D-035). */
.offers-quick__item + .offers-quick__item::before {
	content: "";
	position: absolute;
	left: 0;
	top: calc((100% - var(--quick-dots-row)) * 0.22);
	width: 1px;
	height: calc((100% - var(--quick-dots-row)) * 0.56);
	background-color: var(--color-rule);
}

/*
 * The offer content area is the link: title and short text as one
 * left-aligned block, vertically centred with equal air above and below
 * (D-036). It ends above the dots band; its ::before paints the hover and
 * focus surface over the whole slot — down through the dots band — without
 * taking clicks there.
 */
.offers-quick__link {
	position: relative;
	isolation: isolate;
	flex: 1;
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: var(--space-2);
	padding: calc(var(--quick-pad-c) + var(--quick-pad-optical)) var(--quick-item-pad) calc(var(--quick-pad-c) - var(--quick-pad-optical));
	color: var(--color-text);
	text-decoration: none;
}

.offers-quick__link::before {
	content: "";
	position: absolute;
	inset: 0 0 calc(-1 * var(--quick-dots-row)) 0;
	z-index: -1;
	pointer-events: none;
	transition: background-color 0.2s ease;
}

/*
 * Offer names never break inside a word and are never cut: the strip gives
 * them room (fewer entries per view). Only when even one entry is too
 * narrow (small phones) the size steps down until the longest word
 * (--title-ch, from the template) fits.
 */
.offers-quick__title {
	font-family: var(--font-heading);
	font-size: min(var(--quick-title-size), calc((100cqi / var(--quick-n) - 2 * var(--quick-item-pad)) / (var(--title-ch, 1) * var(--quick-char))));
	font-weight: 700;
	line-height: 1.2;
	word-break: normal;
	overflow-wrap: normal;
	hyphens: none;
	/* The box starts at the cap height, so the air above the title is the
	   padding itself (the block is centred on its ink, not on its leading). */
	text-box: trim-start cap alphabetic;
	transition: color 0.2s ease;
}

/* Shown in full: the CMS keeps it to OWH_EHST_QUICK_TEXT_MAX characters;
   all entries share the height of the tallest one (one flex row). */
.offers-quick__text {
	/* Full text color: on the glass over the photo the muted tone drops
	   below 4.5:1 (measured). */
	color: var(--color-text);
	font-size: 0.9375rem;
	line-height: 1.45;
}

/*
 * Hover and keyboard focus light up the entry's whole slot — its full
 * width, from the strip's top to its bottom inner edge — as a subtle,
 * slightly more opaque ivory glass; no box, radius or shadow (D-035). Hover
 * only on devices that really hover, so nothing sticks after a tap.
 */
@media (hover: hover) and (pointer: fine) {
	.offers-quick__link:hover::before {
		background-color: rgba(252, 250, 246, 0.36);
	}

	.offers-quick__link:hover .offers-quick__title {
		color: var(--color-green-900);
	}
}

/* Keyboard: the same surface plus a clear ring around the whole slot. */
.offers-quick__link:focus-visible {
	outline: none;
}

.offers-quick__link:focus-visible::before {
	background-color: rgba(252, 250, 246, 0.36);
	outline: 3px solid var(--color-orange-600);
	outline-offset: -3px;
}

.offers-quick__link:focus-visible .offers-quick__title {
	color: var(--color-green-900);
}

/* ---------- Carousel controls (only with more than one page) ---------- */

/* The controls wrapper dissolves into the strip grid: chevrons in the side
   gutters, dots over the bottom of the entries (see below). */
.offers-quick__controls:not([hidden]) {
	display: contents;
}

/* Chevrons and dots look like every carousel (.carousel__nav/__dots,
   components.css); here they are only placed. The chevrons sit in the
   middle of the whole strip (the entries span its full height). */
.offers-quick__nav {
	grid-row: 1;
	align-self: center;
}

.offers-quick__nav--prev {
	grid-column: 1;
	justify-self: end;
	margin-right: 8px;
}

.offers-quick__nav--next {
	grid-column: 3;
	justify-self: start;
	margin-left: 8px;
}

/*
 * The dots band: the dots sit --quick-pad-y above the strip's bottom edge,
 * over the entries' bottom padding (not in a row of their own), so every
 * slot's hover/focus surface reaches the strip's edge while the band itself
 * stays outside the links. The text block shares the former top and
 * bottom air equally, so the strip keeps its height (D-036).
 * Decorative only (aria-hidden).
 */
.offers-quick:has(.offers-quick__controls:not([hidden])) {
	--quick-dots-row: calc(6px + var(--quick-pad-y));
	--quick-pad-c: calc((var(--quick-pad-y) + var(--space-4)) / 2);
}

.offers-quick__dots {
	position: absolute;
	left: var(--quick-gutter);
	right: var(--quick-gutter);
	bottom: 0;
	z-index: 1;
	padding-bottom: var(--quick-pad-y);
	pointer-events: none;
}

/*
 * Phones (one offer per view): the active offer sits between the chevrons
 * in narrow side gutters. Title and short text are left-aligned.
 */
@media (max-width: 599px) {
	.offers-quick.is-paged {
		--quick-gutter: 44px;
		--quick-item-pad: var(--space-2);
	}

	.offers-quick__nav {
		width: 44px;
		height: 44px;
	}

	.offers-quick__nav--prev,
	.offers-quick__nav--next {
		justify-self: center;
		margin: 0;
	}

	.offers-quick__link {
		transition: transform 0.2s ease-out;
	}

	.offers-quick__text {
		text-wrap: pretty;
	}

	/* Fade-in timing of a page change (.carousel__track states). */
	.offers-quick__list {
		transition: opacity 0.2s ease-out;
	}
}

@media (prefers-reduced-motion: reduce) {
	.offers-quick__list {
		transition: none;
	}
}

/* ---------- Offer sections (D-022) ---------- */

/*
 * Calm editorial sections after docs/references/detail_reference_3.png:
 * a small letter-spaced eyebrow over a large serif title with a slim meta
 * line beside it, then — per offer — a wide image strip or a side image,
 * then the intro next to an icon list and secondary blocks. No cards and
 * no hard dividers between offers; the CSS-only aurora (four mirrored
 * variants) and generous spacing give the rhythm.
 */
.offer-section {
	/* Quieter aurora: glows sit in the middle of each section; the edges
	   between offers (and towards the planned-offers band below) fade to
	   the same cream, so the sections meet without a visible break. */
	--aurora-edges:
		linear-gradient(to bottom, var(--color-cream-100) 0, rgba(247, 243, 236, 0) 16%),
		linear-gradient(to top, var(--color-cream-100) 0, rgba(247, 243, 236, 0) 16%);
	padding-block: clamp(64px, 8vw, 128px);
	/* Clears the sticky header when an anchor is followed. */
	scroll-margin-top: var(--site-header-height);
	background:
		var(--aurora-edges),
		radial-gradient(ellipse 70% 55% at 12% 42%, var(--aurora-sage), transparent 70%),
		radial-gradient(ellipse 60% 55% at 88% 62%, var(--aurora-sage-soft), transparent 70%),
		radial-gradient(ellipse 45% 45% at 70% 34%, var(--aurora-apricot), transparent 70%),
		var(--color-cream-100);
}

/* Straight edge under the intro photo, as at "Geplante Angebote": the first
   section only fades out at the bottom. */
.offer-section:first-child {
	--aurora-edges: linear-gradient(to top, var(--color-cream-100) 0, rgba(247, 243, 236, 0) 16%);
}

.offer-section:nth-child(4n + 2) {
	background:
		var(--aurora-edges),
		radial-gradient(ellipse 70% 55% at 86% 40%, var(--aurora-sage), transparent 70%),
		radial-gradient(ellipse 60% 55% at 14% 64%, var(--aurora-sage-soft), transparent 70%),
		radial-gradient(ellipse 45% 45% at 32% 58%, var(--aurora-apricot), transparent 70%),
		var(--color-cream-100);
}

.offer-section:nth-child(4n + 3) {
	background:
		var(--aurora-edges),
		radial-gradient(ellipse 68% 58% at 18% 60%, var(--aurora-sage), transparent 70%),
		radial-gradient(ellipse 62% 52% at 82% 36%, var(--aurora-sage-soft), transparent 70%),
		radial-gradient(ellipse 46% 44% at 58% 66%, var(--aurora-apricot), transparent 70%),
		var(--color-cream-100);
}

.offer-section:nth-child(4n + 4) {
	background:
		var(--aurora-edges),
		radial-gradient(ellipse 68% 58% at 82% 58%, var(--aurora-sage), transparent 70%),
		radial-gradient(ellipse 62% 52% at 16% 38%, var(--aurora-sage-soft), transparent 70%),
		radial-gradient(ellipse 46% 44% at 42% 30%, var(--aurora-apricot), transparent 70%),
		var(--color-cream-100);
}

/* Mobile-first: one column in DOM order — header, media, body. */
.offer-section__inner {
	max-width: var(--container-max-width);
	margin-inline: auto;
	padding-inline: var(--container-padding);
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	grid-template-areas:
		"head"
		"media"
		"body";
	row-gap: clamp(24px, 3.4vw, 48px);
}

.offer-section__head { grid-area: head; }
.offer-section__media { grid-area: media; }
.offer-section__body { grid-area: body; }

.offer-section__head,
.offer-section__media,
.offer-section__body,
.offer-section__lead,
.offer-section__details {
	min-width: 0;
}

/* ---------- Header: eyebrow, title, meta line ---------- */

.offer-section__head {
	display: flex;
	flex-direction: column;
	gap: var(--space-5);
}

/* .offer-section__eyebrow, __label and .offer-meta__label share the spaced
   label in components.css. */

.offer-section__eyebrow {
	margin-bottom: var(--space-3);
}

/* Size container for the title: its width decides how large a long name
   may be set (D-032). */
.offer-section__heading {
	container-type: inline-size;
}

/*
 * Offer names never break inside a word. Usually the fluid size applies;
 * a long word (--title-ch characters, from the template) caps it so that
 * the word fits the heading's width — Georgia bold with the tight tracking
 * needs ≈0.53em per character, 0.57 keeps a reserve. The size scales with
 * the reader's font (rem) as usual; 20px is only the lower safety floor for
 * an exceptionally long single word — fixed, so a larger default font
 * cannot push such a word past a narrow screen (D-035). A word of more
 * than ~27 characters would reach it on a 320px phone (editorial note, see
 * docs). Several words still wrap at spaces (balanced).
 */
.offer-section__title {
	margin: 0;
	color: var(--color-text);
	font-size: max(20px, min(clamp(1.875rem, 3.4vw + 1rem, 4.625rem), calc(100cqi / (var(--title-ch, 1) * 0.57))));
	font-weight: 700;
	line-height: 1.02;
	letter-spacing: -0.02em;
	word-break: normal;
	overflow-wrap: normal;
	hyphens: none;
	text-wrap: balance;
}

.offer-section__title:focus-visible {
	outline: 3px solid var(--color-orange-600);
	outline-offset: 6px;
}

/* Slim meta line: icon, letter-spaced label, summary, italic note. */
.offer-meta {
	display: grid;
	grid-template-columns: 28px minmax(0, 1fr);
	column-gap: var(--space-4);
	align-items: start;
	max-width: 340px;
	padding-block: var(--space-4);
	border-block: 1px solid var(--color-rule);
}

.offer-meta__icon {
	width: 26px;
	height: 26px;
	margin-top: 2px;
	color: var(--color-green-900);
}

.offer-meta__body {
	display: grid;
	gap: 4px;
}

.offer-meta__label {
	font-size: 0.6875rem;
	letter-spacing: 0.28em;
}

.offer-meta__text {
	margin: 0;
	color: var(--color-text);
	font-size: 0.9375rem;
	line-height: 1.45;
}

.offer-meta__note {
	margin: 0;
	color: var(--color-text-muted);
	font-size: 0.9375rem;
	font-style: italic;
	line-height: 1.45;
}

.offer-meta__trigger {
	display: inline-flex;
	align-items: center;
	justify-self: start;
	gap: 6px;
	min-height: 32px;
	margin-top: 2px;
	padding: 0;
	border: 0;
	background: none;
	color: var(--color-green-900);
	font: 500 0.875rem/1.4 var(--font-body);
	text-decoration: underline;
	text-decoration-color: color-mix(in srgb, var(--color-green-900) 35%, transparent);
	text-underline-offset: 4px;
	cursor: pointer;
	transition: text-decoration-color 0.2s ease;
}

.offer-meta__trigger svg {
	width: 14px;
	height: 14px;
	transition: transform 0.2s ease;
}

.offer-meta__trigger:hover {
	text-decoration-color: currentColor;
}

.offer-meta__trigger:hover svg {
	transform: translateX(2px);
}

.offer-meta__trigger:focus-visible {
	outline: 2px solid var(--color-orange-600);
	outline-offset: 4px;
}

/* Without JavaScript the trigger can't open anything; the hours render as a
   plain block at the end of the section instead. */
html:not(.has-js) .offer-meta__trigger {
	display: none;
}

/* ---------- Body: intro, key points, secondary blocks ---------- */

.offer-section__body {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: clamp(36px, 4vw, 56px);
}

.offer-section__label {
	margin-bottom: var(--space-4);
}

.offer-section__intro {
	margin: 0;
	color: var(--color-text);
	font-family: var(--font-heading);
	font-size: clamp(1.375rem, 1vw + 1.1rem, 1.875rem);
	font-weight: 400;
	line-height: 1.3;
	text-wrap: pretty;
}

.offer-section__more {
	max-width: 52ch;
	margin: var(--space-5) 0 0;
	color: var(--color-text-muted);
	font-size: 1rem;
	line-height: 1.6;
}

/* Running text wraps at spaces; a single word that is wider than the column
   (a long name in large type with a larger default font) breaks only as a
   last resort instead of overflowing the page (D-035). */
.offer-section__lead,
.offer-section__details {
	word-break: normal;
	overflow-wrap: break-word;
	hyphens: manual;
}

.offer-section__legacy {
	max-width: 62ch;
	color: var(--color-green-900);
	line-height: 1.65;
}

.offer-section__legacy > * {
	margin-block: 0 var(--space-4);
}

.offer-section__legacy > :last-child {
	margin-bottom: 0;
}

.offer-section__legacy a {
	overflow-wrap: anywhere;
}

/* Key points: icon rows with hairline separators, no cards. */
.offer-points {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	column-gap: clamp(24px, 3vw, 48px);
	margin: 0;
	padding: 0;
	list-style: none;
}

.offer-points__item {
	display: grid;
	grid-template-columns: 40px minmax(0, 1fr);
	column-gap: var(--space-4);
	align-items: center;
	min-height: 64px;
	padding-block: var(--space-3);
	border-bottom: 1px solid var(--color-rule);
	color: var(--color-green-900);
	font-size: 0.9375rem;
	line-height: 1.45;
}

.offer-points__icon,
.offer-extra__icon {
	display: grid;
	place-items: center;
	width: 40px;
	height: 40px;
	border-radius: 50%;
	background-color: color-mix(in srgb, var(--color-beige-200) 62%, transparent);
	color: var(--color-green-900);
}

.offer-points__icon svg,
.offer-extra__icon svg {
	width: 20px;
	height: 20px;
}

/* "Ohne Icon": a short orange dash instead of the round field. */
.offer-points__icon.is-dash,
.offer-extra__icon.is-dash {
	background: none;
}

.offer-points__icon.is-dash::before,
.offer-extra__icon.is-dash::before {
	content: "";
	width: 14px;
	height: 2px;
	background-color: var(--color-orange-600);
}

/* Secondary blocks: icon, small serif heading, quieter text. */
.offer-extra {
	display: grid;
	grid-template-columns: 40px minmax(0, 1fr);
	column-gap: var(--space-4);
	align-items: start;
	margin-top: clamp(28px, 3vw, 40px);
}

.offer-section__points + .offer-extra {
	margin-top: clamp(28px, 3vw, 40px);
}

.offer-extra + .offer-extra {
	margin-top: var(--space-6);
}

.offer-extra__title {
	margin: 6px 0 var(--space-2);
	color: var(--color-text);
	font-family: var(--font-heading);
	font-size: 1.25rem;
	font-weight: 600;
	line-height: 1.3;
}

.offer-extra__text {
	margin: 0;
	max-width: 64ch;
	color: var(--color-text-muted);
	font-size: 0.9375rem;
	line-height: 1.6;
}

.offer-extra__icon + .offer-extra__body .offer-extra__text:first-child {
	padding-top: 8px;
}

/* "Kontakt aufnehmen →": light editorial link, deepened orange (≥ 4.5:1). */
.offer-section__contact {
	display: inline-flex;
	align-items: baseline;
	gap: var(--space-2);
	margin-top: clamp(24px, 2.6vw, 36px);
	color: var(--color-accent-text);
	font-size: 1.0625rem;
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
}

.offer-section__contact-label {
	padding-bottom: 3px;
	border-bottom: 1px solid color-mix(in srgb, currentColor 45%, transparent);
	transition: border-color 0.2s ease;
}

.offer-section__contact:hover .offer-section__contact-label,
.offer-section__contact:focus-visible .offer-section__contact-label {
	border-bottom-color: currentColor;
}

.offer-section__contact > span[aria-hidden="true"] {
	transition: transform 0.15s ease;
}

.offer-section__contact:hover > span[aria-hidden="true"] {
	transform: translateX(3px);
}

.offer-section__contact:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 6px;
}

/* Intro only (no points, no secondary blocks): one calm column. */
.offer-section--lead-only .offer-section__lead {
	max-width: 720px;
}

/* ---------- Strip layout (default) ---------- */

@media (min-width: 768px) {
	/* More than three points: two aligned columns in the strip layout. */
	.offer-section--strip.offer-section--many-points .offer-points,
	.offer-section--no-image.offer-section--many-points .offer-points {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 1024px) {
	.offer-section__head {
		display: grid;
		grid-template-columns: minmax(0, 1fr) minmax(240px, 340px);
		align-items: end;
		column-gap: clamp(32px, 5vw, 96px);
	}

	/* Without a meta line the title takes the whole width (no empty
	   column beside it). */
	.offer-section__head:not(:has(.offer-meta)) {
		grid-template-columns: minmax(0, 1fr);
	}

	.offer-meta {
		align-self: end;
	}

	.offer-section--strip .offer-section__body,
	.offer-section--no-image .offer-section__body {
		grid-template-columns: minmax(0, 38fr) minmax(0, 62fr);
		column-gap: clamp(40px, 5.5vw, 96px);
		align-items: start;
	}

	/* Intro only: one calm column, no empty right column. */
	.offer-section--lead-only .offer-section__body {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* ---------- Side layouts: image left / right ---------- */

/* Below ~920px both stack: the media block is centered and held to a calm
   width (portrait 440px, other formats 560px) with whitespace around it.
   The stored focal point still decides the crop inside the frame. */
.offer-section--side-left .offer-section__media,
.offer-section--side-right .offer-section__media {
	justify-self: center;
	width: 100%;
	max-width: 560px;
}

.offer-section--side-left .offer-section__media:has(.offer-gallery.is-portrait),
.offer-section--side-right .offer-section__media:has(.offer-gallery.is-portrait) {
	max-width: 440px;
}

.offer-section--side-left .offer-section__media .offer-gallery__frame,
.offer-section--side-right .offer-section__media .offer-gallery__frame,
.offer-section--side-left .offer-section__media .offer-gallery__dots,
.offer-section--side-right .offer-section__media .offer-gallery__dots {
	margin-inline: auto;
}

@media (min-width: 920px) {
	.offer-section--side-left .offer-section__inner,
	.offer-section--side-right .offer-section__inner {
		column-gap: clamp(40px, 5vw, 88px);
		align-items: start;
	}

	.offer-section--side-left .offer-section__inner {
		grid-template-columns: minmax(0, 42fr) minmax(0, 58fr);
		grid-template-areas:
			"head  head"
			"media body";
	}

	.offer-section--side-right .offer-section__inner {
		grid-template-columns: minmax(0, 58fr) minmax(0, 42fr);
		grid-template-areas:
			"head head"
			"body media";
	}

	.offer-section--side-left .offer-section__media,
	.offer-section--side-right .offer-section__media,
	.offer-section--side-left .offer-section__media:has(.offer-gallery.is-portrait),
	.offer-section--side-right .offer-section__media:has(.offer-gallery.is-portrait) {
		justify-self: stretch;
		max-width: none;
	}
}


/* ---------- Offer media stage ---------- */

/* The gallery itself (.offer-gallery) is shared with posts and lives in
   components.css (D-029); the side layouts above only size it. */

/* ---------- Opening hours dialog ---------- */

/*
 * The dialog is opened with showModal(), so it lives in the top layer: the
 * pinned stage's `overflow: hidden` can never clip it, Escape and the focus
 * trap are native, and the slide's height is untouched.
 */
.offer-hours-dialog {
	width: min(420px, calc(100vw - 2 * var(--container-padding)));
	max-height: min(560px, calc(100svh - 2 * var(--space-7)));
	padding: 0;
	border: 0;
	color: var(--color-green-900);
	background: transparent;
	overflow: visible;
}

/* Softly dimmed and blurred — the offer behind must stay perceptible. */
.offer-hours-dialog::backdrop {
	background: color-mix(in srgb, var(--color-green-900) 14%, transparent);
	-webkit-backdrop-filter: blur(3px) saturate(1.02);
	backdrop-filter: blur(3px) saturate(1.02);
}

/*
 * A translucent warm glass surface that belongs to the page, not an app-style
 * modal card: no radius, a fine translucent border and only the faintest lift
 * instead of a heavy drop shadow.
 */
.offer-hours-dialog__panel {
	padding: var(--space-6) var(--space-6) var(--space-5);
	background: color-mix(in srgb, var(--color-cream-100) 78%, transparent);
	-webkit-backdrop-filter: blur(18px) saturate(1.2);
	backdrop-filter: blur(18px) saturate(1.2);
	border: 1px solid color-mix(in srgb, var(--color-white) 45%, transparent);
	box-shadow: 0 2px 18px rgba(18, 63, 56, 0.08);
}

.offer-hours-dialog__head {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--space-4);
	margin-bottom: var(--space-4);
}

.offer-hours-dialog__title {
	display: flex;
	align-items: center;
	gap: var(--space-2);
	margin: 0;
	color: var(--color-text);
	font-family: var(--font-heading);
	font-size: 1.1875rem;
	line-height: 1.3;
}

.offer-hours-dialog__icon {
	width: 20px;
	height: 20px;
	color: var(--color-orange-600);
	flex: 0 0 auto;
}

/* Receives focus on open (offer-hours.js) so the title is announced first;
   it is not interactive, so no focus ring. */
.offer-hours-dialog__title:focus {
	outline: none;
}

/* Only a thin dark-green X, no surface. The button itself is the 44x44 hit
   area; the negative margin keeps the glyph and the head height where the
   20px icon sits. */
.offer-hours-dialog__close {
	display: grid;
	place-items: center;
	flex: 0 0 auto;
	width: 44px;
	height: 44px;
	margin: -12px -12px -12px 0;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: var(--color-text);
	cursor: pointer;
	transition: color 0.2s ease, background-color 0.2s ease;
}

.offer-hours-dialog__close svg {
	width: 20px;
	height: 20px;
}

.offer-hours-dialog__close:hover {
	background-color: color-mix(in srgb, var(--color-orange-600) 7%, transparent);
	color: var(--color-accent);
}

.offer-hours-dialog__close:focus-visible {
	outline: 2px solid var(--color-text);
	outline-offset: -2px;
}

.offer-hours-dialog__list {
	display: grid;
	/* No column gap: the hairline under a row has to read as one line, not as
	   two separate rules with a break in the middle. */
	grid-template-columns: auto 1fr;
	margin: 0;
}

.offer-hours-dialog__day,
.offer-hours-dialog__time {
	margin: 0;
	padding-block: var(--space-2);
	border-bottom: 1px solid var(--color-rule-soft);
	font-size: 0.9375rem;
	line-height: 1.45;
}

.offer-hours-dialog__day:nth-last-child(2),
.offer-hours-dialog__time:last-child {
	border-bottom: 0;
}

.offer-hours-dialog__day {
	padding-inline-end: var(--space-5);
	font-weight: 600;
	color: var(--color-text);
}

.offer-hours-dialog__time {
	text-align: right;
}

/* Closed days differ by the word "geschlossen" and the regular weight of
   the day name. Full text color: on the glass panel the muted tone drops
   below 4.5:1 (measured). */
.offer-hours-dialog__time.is-closed,
.offer-hours-dialog__day.is-closed {
	color: var(--color-text);
	font-weight: 400;
}

/*
 * Scroll locking is handled in JS by swallowing scroll gestures, not with
 * `overflow: hidden` here: making <html> non-scrollable breaks the sticky
 * stage and throws the whole story out of view while the dialog is open.
 */
.offer-hours-dialog__panel {
	overscroll-behavior: contain;
	overflow-y: auto;
	max-height: inherit;
}

/*
 * Without JavaScript the trigger can't open anything, so the same markup is
 * rendered as a plain visible block instead — the hours are never lost.
 */
html:not(.has-js) .offer-hours-dialog {
	display: block;
	position: static;
	width: auto;
	max-width: 420px;
	max-height: none;
	margin: var(--space-4) 0 0;
}

html:not(.has-js) .offer-hours-dialog__close {
	display: none;
}

/* ---------- Reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
	.offer-section__contact > span[aria-hidden="true"],
	.offer-section__contact-label,
	.offer-meta__trigger,
	.offer-meta__trigger svg {
		transition: none;
	}

	.offer-section__contact:hover > span[aria-hidden="true"],
	.offer-meta__trigger:hover svg {
		transform: none;
	}
}


.offers-page__empty {
	margin: 0;
	padding-bottom: var(--space-9);
	color: var(--color-green-900);
}

/* ---------- Planned offers ("In Arbeit") ---------- */

/*
 * Atmospheric section: the botanical bokeh photo band (.photo-band--botanical,
 * components.css — softened photo, cream wash behind the intro) and one
 * shared frosted-glass banner carrying all planned entries.
 */
.offers-planned {
	padding-block: var(--space-9) clamp(var(--space-9), 9vw, 150px);
}

.offers-planned__intro {
	max-width: 640px;
	margin-bottom: var(--space-7);
}

.offers-planned__heading {
	margin: 0 0 var(--space-3);
	color: var(--color-text);
	font-size: clamp(1.75rem, 2vw + 1.25rem, 2.5rem);
	line-height: 1.15;
}

.offers-planned__lead {
	margin: 0;
	color: var(--color-green-900);
}

/* The one shared banner: full width, frosted white, hairline edges. */
.offers-planned__banner {
	position: relative;
	padding-block: var(--space-5);
	background-color: rgba(255, 255, 255, 0.58);
	-webkit-backdrop-filter: blur(12px) saturate(1.1);
	backdrop-filter: blur(12px) saturate(1.1);
	border-block: 1px solid rgba(255, 255, 255, 0.75);
	overflow-x: auto;
	scrollbar-width: none;
}

.offers-planned__banner::-webkit-scrollbar {
	display: none;
}

.offers-planned__banner:focus-visible {
	outline: 3px solid var(--color-orange-600);
	outline-offset: -3px;
}

.offers-planned__track {
	display: flex;
	width: max-content;
	/* Static state (1 entry, no JS, reduced motion): centered while it fits. */
	margin-inline: auto;
	padding-inline: var(--container-padding);
}

.offers-planned__list {
	display: flex;
	align-items: center;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* An entry sits directly in the banner — no border, no own surface. */
.planned-offer {
	position: relative;
	flex: 0 0 auto;
	box-sizing: border-box;
	/* Wide enough that valid content (title ≤ 40, text ≤ 100 characters)
	   shows in full; the clamp below is only a visual safeguard. */
	width: clamp(380px, 34vw, 460px);
	display: flex;
	align-items: center;
	gap: var(--space-4);
	padding-inline: clamp(var(--space-5), 2.5vw, var(--space-6));
}

/* Fine vertical divider between entries. */
.planned-offer::after {
	content: "";
	position: absolute;
	top: 50%;
	right: 0;
	width: 1px;
	height: 52px;
	transform: translateY(-50%);
	background-color: var(--color-rule-strong);
}

/* Static row: no divider after the last entry. */
.offers-planned__banner:not(.is-marquee) .planned-offer:last-child::after {
	display: none;
}

.planned-offer__icon {
	flex: 0 0 52px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	border-radius: 50%;
	background-color: color-mix(in srgb, var(--color-green-900) 6%, rgba(255, 255, 255, 0.8));
	color: var(--color-green-900);
}

.planned-offer__icon svg {
	width: 26px;
	height: 26px;
}

.planned-offer__body {
	min-width: 0;
}

/* Lighter, more refined treatment of the site's body font. Clamped only
   as a visual safeguard (title 2, text 3 lines); valid CMS content fits. */
.planned-offer__title,
.planned-offer__text {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	overflow: hidden;
}

.planned-offer__text {
	-webkit-line-clamp: 3;
	line-clamp: 3;
}

.planned-offer__title {
	margin: 0;
	color: var(--color-text);
	font-family: var(--font-body);
	font-size: 1.0625rem;
	font-weight: 500;
	line-height: 1.3;
	letter-spacing: 0.005em;
}

.planned-offer__text {
	margin: var(--space-1) 0 0;
	/* Full text color: on the band's sage wash the muted tone drops below
	   4.5:1 (measured). */
	color: var(--color-text);
	font-family: var(--font-body);
	font-size: 0.9375rem;
	font-weight: 400;
	line-height: 1.45;
}

/* Single entry: placed calmly in the centre of the banner. */
.offers-planned__banner.is-single .planned-offer {
	width: auto;
	max-width: min(520px, 100%);
}

/* Marquee (2+ entries, set by planned-offers-band.js). */
.offers-planned__banner.is-marquee {
	overflow: hidden;
}

.offers-planned__banner.is-marquee .offers-planned__track {
	margin-inline: 0;
	padding-inline: 0;
	animation: owh-planned-marquee var(--marquee-duration, 60s) linear infinite;
	will-change: transform;
}

.offers-planned__banner.is-paused .offers-planned__track {
	animation-play-state: paused;
}

@keyframes owh-planned-marquee {
	to {
		transform: translateX(calc(-1 * var(--marquee-shift, 0px)));
	}
}

@media (max-width: 599px) {
	.planned-offer {
		width: calc(100vw - 48px);
		gap: var(--space-3);
		padding-inline: var(--space-4);
	}

	.planned-offer__title {
		font-size: 1rem;
	}

	/* Narrow phones: one more line so valid text still shows in full. */
	.planned-offer__text {
		font-size: 0.875rem;
		-webkit-line-clamp: 4;
		line-clamp: 4;
	}

	.planned-offer__icon {
		flex-basis: 38px;
		width: 38px;
		height: 38px;
	}

	.planned-offer__icon svg {
		width: 20px;
		height: 20px;
	}
}

/* Very narrow phones: room for the longest valid title and text. */
@media (max-width: 359px) {
	.planned-offer__title {
		-webkit-line-clamp: 3;
		line-clamp: 3;
	}

	.planned-offer__text {
		-webkit-line-clamp: 5;
		line-clamp: 5;
	}
}

/* No automatic movement at all when reduced motion is requested. */
@media (prefers-reduced-motion: reduce) {
	.offers-planned__banner.is-marquee .offers-planned__track {
		animation: none;
	}
}
