/**
 * BEATS GROUP — Baukasten section CSS.
 * Loaded automatically in both frontend AND editor iframe by
 * beats_group_enqueue_styles() (enqueue_block_assets, glob over
 * assets/css/*.css). Additive only (D-13): every rule below is a new
 * selector, nothing here changes an existing one. Besides .grid-auto-fit
 * this file also carries the minimal styling (D-12) of the three core
 * blocks widened into the palette in Plan 03-07 (D-11): table, details
 * and file.
 */

/* Card-row container that must carry 2, 3 or 4 cards without an empty
   trailing column (D-08). The existing .grid-3-lg/.grid-4-lg classes force a
   fixed repeat(N, …) column count, which leaves a blank column whenever a
   card-row baustein carries fewer cards than that fixed number — auto-fit
   sizes to however many cards are actually present instead.

   Uses the "body .is-layout-grid.<class>" prefix from base.css, not
   ":root :where(...)" — WordPress' generated ".wp-container-*" grid-template
   rules otherwise win the specificity fight and this rule never applies. */
body .is-layout-grid.grid-auto-fit {
	grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 48rem) {
	body .is-layout-grid.grid-auto-fit {
		grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
	}
}

/* core/table minimal styling (D-11/D-12): sand header row instead of the
   core default look. No existing pattern uses wp:table (see Plan 03-07
   verification), so this cannot reach any of the nine production pages -
   :root :where(...) keeps the specificity at 0,1,0 regardless. */
:root :where(.wp-block-table thead th) {
	background-color: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--ink);
	text-align: left;
	font-weight: 700;
}

:root :where(.wp-block-table td),
:root :where(.wp-block-table th) {
	padding: 0.75rem 1rem;
	border-bottom: 1px solid color-mix(in oklab, var(--wp--preset--color--ink) 12%, transparent);
}

/* core/details minimal styling (D-11/D-12): a bottom rule marks each row,
   the summary reads as a clickable line. No custom marker and no custom
   open/close behaviour — the core block already brings both. No existing
   pattern uses wp:details, same reach guarantee as above. */
:root :where(.wp-block-details) {
	padding-block: var(--wp--preset--spacing--30);
	border-bottom: 1px solid color-mix(in oklab, var(--wp--preset--color--ink) 12%, transparent);
}

:root :where(.wp-block-details summary) {
	font-weight: 600;
	cursor: pointer;
}

:root :where(.wp-block-details > :not(summary)) {
	margin-top: var(--wp--preset--spacing--30);
}

/* FAQ baustein (section-faq.php) card styling (D-12/D-14, Plan 04.1-03):
   inherits the surface-card look of the numbered-list/service cards
   (.service-list-card in section-numbered-list.php) instead of the
   core/details minimal row styling above — no pattern renders section-faq
   on a production page yet (same zero-reach guarantee as the rules
   above), so overriding it here for .faq-item specifically changes
   nothing visible on a live page. Values are copied from the
   already-measured list card, not invented: background-color/
   border-radius/padding from section-numbered-list.php, summary
   typography from .display-card (base.css), paragraph spacing from the
   card family (services.css, .service-list-card > *). border-bottom:none
   is required here even though it is not in the comparison-property list
   below — without it, the generic .wp-block-details bottom rule above
   would draw a straight line across the rounded card's bottom corners. */
:root :where(.faq-item) {
	background-color: var(--wp--preset--color--surface);
	border-radius: 1.5rem;
	border-bottom: none;
	padding: var(--wp--preset--spacing--card);
}

/* Same-scale gap as the numbered-list card grid's blockGap (var:preset|
   spacing|40), but via margin-top on the successor instead of gap:
   .faq-list sits in a constrained layout, and theme.json's blockGap:0px
   means WordPress distributes blockGap through margin-block-start on
   constrained-layout children, never through CSS gap (mechanism measured
   in Plan 04-04). */
:root :where(.faq-item + .faq-item) {
	margin-top: var(--wp--preset--spacing--40);
}

/* Question typography reproduces .display-card (base.css) by hand: a
   core/details block has no sub-block for its <summary>, so a className
   attribute only ever reaches the outer <details> element, never the
   <summary> itself — the display-card class genuinely cannot be applied
   here via the block editor, unlike the Astro side (FaqSection.astro),
   which sets the class directly on <summary>.

   No `gap` here (Plan 04.5-07, FAQ-Flex-Gap): with exactly two flex
   children (question text, +/- marker) and justify-content:space-between,
   the free space between them already exceeds any gap value at every
   measured width — a WP-only before/after screenshot of .faq-list at
   375/768/1440 with `gap: 1rem` removed was byte-identical to the
   `gap: 1rem` original (max channel diff 0 across all three widths), so
   the declaration moved zero pixels and only inflated the DOM parity
   report's row-gap/column-gap findings (0px vs 16px, 606k Wucht across
   the four service pages). Confirmed a second time by the section-level
   diffbild via `qa/screenshot-compare.py --seite expansion`. */
:root :where(.faq-item > summary) {
	display: flex;
	align-items: center;
	justify-content: space-between;
	list-style: none;
	cursor: pointer;
	font-family: var(--wp--preset--font-family--archivo);
	font-variation-settings: "wdth" 110;
	font-weight: 800;
	font-size: var(--wp--preset--font-size--card);
	line-height: 1.05;
}

/* Diese drei Regeln standen bis zum 21.09.2026 als `:root :where(... ::after)`
   in der Datei und waren damit **wirkungslos**: `:where()` nimmt laut
   CSS-Selectors-Spezifikation kein Pseudoelement in seiner Selektorliste
   entgegen, der ganze Selektor ist ungueltig und die Regel greift nirgends.
   Zusammen mit `list-style: none` am summary (gueltig, greift) bedeutete das:
   gar kein Aufklappsymbol - weder das native Dreieck noch das gewollte +/-.
   Genau das hat der Kunde am 08.09.2026 gemeldet ("es waere hilfreich, wenn
   ein Symbol neben der Frage steht, damit der Besucher weiss dass die Antwort
   darunter steht"). Gemessen vor dem Fix: getComputedStyle(summary, '::after')
   meldete content:'none' lokal und auf der Staging.
   Dieselbe Falle steckt unveraendert in `.hero-gradient::after`
   (home.css, hero-cover.css) - dort bewusst nicht angefasst, weil die
   Hero-Deckkraft ohne den Verlauf kontrastgemessen wurde und ein
   Einschalten die Heros nachtraeglich abdunkeln wuerde. */
:root .faq-item > summary::-webkit-details-marker {
	display: none;
}

/* Plain "+"/"-" instead of the browser triangle — no en or em dash, same
   character rule as everywhere else in the project (customer requirement
   19./20.08.). */
:root .faq-item > summary::after {
	content: "+";
	flex-shrink: 0;
	font-weight: 700;
}

:root .faq-item[open] > summary::after {
	content: "-";
}

:root :where(.faq-item[open] > summary) {
	margin-bottom: 0.9rem;
}

/* Answer typography (Plan 04.1-13): FaqSection.astro's answer paragraph
   uses Tailwind's text-base (1rem/1.5rem) plus text-ink/75 — the same
   card-family override services.css already gives .service-list-card's
   own paragraphs. That selector list cannot reach .faq-item (a different
   component family, deliberately not one of the card classes it lists),
   so the answer fell back to the global theme.json body preset
   (1.125rem/1.6) at full ink color instead. Measured first on
   konzept-markenentwicklung (Plan 04.1-06, 1.6M Wucht) and confirmed on
   every subsequent FAQ-bearing page — not a per-page issue, a missing
   rule in the shared component CSS. Values copied verbatim from
   services.css's card-text rule, not re-derived. */
:root :where(.faq-item > :not(summary)) {
	font-size: 1rem;
	line-height: 1.5rem;
	color: color-mix(in oklab, var(--wp--preset--color--ink) 75%, transparent);
}

/* Case-proof baustein (section-case-proof.php) card spacing (D-12/D-14,
   Plan 04.1-04): unlike .faq-item, the card's surface/radius/padding come
   straight from block attributes in the pattern markup (same values as
   .service-reference-card in about-page.php), so no CSS is needed for
   those. Only what the attributes cannot carry lands here: even spacing
   between the three body paragraphs (.proof-body), following the same
   margin-top-on-successor convention as the card family in services.css
   (.service-list-card > * etc.), and a size cap for whatever logo a
   redakteur inserts - section-case-proof.php ships on up to four
   different pages with different customer logos or none, unlike
   about-page.php's single, permanently fixed 64px Coyote logo.
   1rem matches ProofCard.astro's `.proof-body` wrapper (Tailwind
   `space-y-4` = margin-top:1rem on every child but the first) - Plan
   04.5-12 corrected this from the original 0.9rem, which undershot the
   prototype by 1.6px per gap (3.28px cumulative by the third paragraph),
   measured live with Playwright on /expansion-franchise-lizenz/ at
   1440px (04.5-ENTSCHEIDUNGEN.md, Untergruppe 7). */
:root :where(.proof-body) > * {
	margin-top: 1rem;
	margin-bottom: 0;
}

:root :where(.proof-body) > :first-child {
	margin-top: 0;
}

/* Answer typography (Plan 04.1-13): same missing rule as .faq-item above,
   for the same reason - Plan 04.1-04 Task 2 scoped its sections.css
   additions to paragraph spacing and the logo size cap only, so
   .proof-body's paragraphs fell back to the theme's global body preset
   (1.125rem/1.6/full ink) instead of ProofCard.astro's Tailwind
   text-base/text-ink-75. Documented at the time in 04.1-SEKTIONSTYPEN.md
   as a deliberate, protocolled gap rather than a design difference -
   closing it here removes the three matching entries from
   SEKTIONSTYP_BEABSICHTIGTE_ABWEICHUNGEN in
   qa/section-library-roundtrip.py, which previously asserted this gap as
   expected. */
:root :where(.proof-body p) {
	font-size: 1rem;
	line-height: 1.5rem;
	color: color-mix(in oklab, var(--wp--preset--color--ink) 75%, transparent);
}

/* "Weitere Fallbeispiele" below the case on the four service pages (SEO F6,
   internal link to /referenzen/). Same look as the prototype's text links:
   accent-text, 600, underline only on hover. */
:root :where(.proof-body .proof-mehr a) {
	color: var(--wp--preset--color--accent-text);
	font-weight: 600;
	text-decoration: none;
}

:root :where(.proof-body .proof-mehr a:hover) {
	text-decoration: underline;
}

/* Das Portraet einer Referenzkarte behaelt sein 96er Quadrat. Die Kopfzeile
   der Karte ist eine Flex-Reihe mit flexWrap:nowrap; ohne flex-shrink:0
   schrumpft die <figure>, sobald die Funktionszeile lang wird - bei
   "Geschaeftsfuehrer, Die Bausatzlokale Deutschland" auf 63,5px bei 375px
   Breite, waehrend "Inhaber Coyote Cafe Trier" daneben unversehrt blieb.
   Das Bild bekommt dann ueber max-width:100% die Breite der geschrumpften
   figure und wird schmal beschnitten. Im Prototyp tritt es nicht auf:
   QuoteCard.astro setzt Tailwinds h-24 w-24 direkt auf das <img>.
   Nur die Kopfzeile ist getroffen, das Firmenlogo steht ausserhalb der
   nowrap-Gruppe. */
:root :where(.service-reference-card .is-nowrap > .wp-block-image) {
	flex-shrink: 0;
}

:root :where(.proof-card .wp-block-image img) {
	max-width: 8rem;
	max-height: 3rem;
	width: auto;
	height: auto;
}

/* core/file minimal styling (D-11/D-12): the download-card look of the
   Phase-2 reference card (.service-reference-card) — surface fill, rounded
   corners, padding, accent-text link. The download button itself is never
   styled here because it is never rendered (see section-downloads.php,
   "showDownloadButton":false) — T-03-18. No existing pattern uses wp:file,
   same reach guarantee as above. */
:root :where(.wp-block-file) {
	background-color: var(--wp--preset--color--surface);
	border-radius: 1.5rem;
	padding: var(--wp--preset--spacing--card);
}

:root :where(.wp-block-file a) {
	color: var(--wp--preset--color--accent-text);
	font-weight: 600;
}

/* section-hero-flat (gap-closure 03-13): the H1 font-size scales against the
   actual COLUMN width via a CSS container query, not against the viewport.
   Root cause: the shared .display-hero rule's font-size preset
   (clamp(2.5rem, 6vw, 5rem), theme.json) computes "6vw" against the
   viewport. In every OTHER Baustein/pattern .display-hero sits on a
   full-width hero, so that tracks the visible width closely enough - but
   here the H1 shares a two-column row with the image, so its real available
   width is only half the 69rem content column (~552px at 1440px viewport)
   while 6vw keeps growing with the viewport regardless, reaching 86px
   (capped at 80px) - far more than the column can hold, so long German
   compounds ("Systemgastronomie") got force-broken mid-word.

   Investigated in Plan 03-13 Task 1: .display-hero's own
   "overflow-wrap: normal" already wins correctly on the FRONTEND (a
   declaration on the element itself always beats an inherited one,
   regardless of selector specificity) - so overflow-wrap was never the
   actual frontend cause. The real frontend cause is "word-break:
   break-word", inherited from WordPress core's own
   ".wp-block-column { word-break: break-word; overflow-wrap: break-word; }"
   (wp-includes/css/dist/block-library/style.css) - nothing in the theme
   ever resets word-break, and per spec "word-break: break-word" forces
   anywhere-style breaking independently of whatever overflow-wrap resolves
   to. In the EDITOR CANVAS a second, independent cause stacks on top:
   Gutenberg's own ".block-editor-block-list__layout
   .block-editor-block-list__block" rule sets "overflow-wrap: break-word"
   DIRECTLY on the block wrapper (every block, including this H1) at
   specificity (0,2,0) - two plain classes, no :where() - which beats
   ":root :where(.display-hero)" at (0,1,0) outright, regardless of load
   order. Neither cause is fixable by raising specificity on a class shared
   with the production heroes (that would drag every other Baustein/page
   along and risk the exact regression base.css's own comment warns about),
   so this rule fixes the actual lever instead: a word that already FITS on
   one line never needs to invoke break-word/word-break's forced-break
   fallback at all, regardless of which of the two wrapping rules above
   wins the cascade. container-type: inline-size on .hero-flat-col turns it
   into a query container; a coefficient of the CONTAINER's inline size (not
   the viewport) keeps the longest sample word ("Systemgastronomie", 17
   chars) on one line at every measured breakpoint (375/768/1440px) with
   headroom below the empirically measured break point (~7.85% of the
   column width at font-weight 900/uppercase/wdth 118) - verified in the
   real browser via Range.getClientRects() per word, editor canvas and
   frontend both. Scoped to this Baustein only: .display-hero itself is
   untouched. Originally 7cqi (Plan 03-13, ~11% headroom below 7.85%); Plan
   03-14 raised it to 7.5cqi (~4.5% headroom) alongside widening the column
   itself - see the gap-closure 03-14 comment further below for why the
   widening alone did not clear the H1-vs-H2 condition and the coefficient
   had to move too. */
.hero-flat-col {
	container-type: inline-size;
}

.hero-flat-heading {
	font-size: clamp(1.5rem, 7.5cqi, 4rem);
}

/* section-hero-flat (gap-closure 03-14): widen the text column against the
   image column at the lg breakpoint, so the container query above has more
   room and the H1 can sit above the section H2 size again without breaking
   mid-word. 03-13 fixed the break but inverted the hierarchy: at the 50/50
   split base.css's .cols-lg rule produces (552px per column at 1440px),
   the H1 measured 38.64px against the section H2's 52px
   (.display-section, clamp(2rem, 4vw, 3.25rem) at its ceiling) - a third
   smaller than every heading beneath it. Customer decision (23.08.): widen
   the column instead of shrinking the type.

   base.css's ".cols-lg > .wp-block-column" rule spreads flex evenly
   (flex-basis:0 !important; flex-grow:1 !important each) at the same
   64rem breakpoint - both are three-class selectors (.wp-block-columns
   .cols-lg .wp-block-column vs. .wp-block-columns .cols-lg
   .hero-flat-col/-img-col), so this is a tie on specificity. It resolves
   through load order instead: sections.css is enqueued after base.css
   (glob() over assets/css/*.css sorts alphabetically, functions.php), so
   at equal specificity and equal !important weight the later-loaded rule
   wins - no specificity increase, no touch to base.css itself. Only
   flex-grow is redeclared; flex-basis stays the inherited 0 so the 65:35
   ratio below is exact instead of adding to a non-zero base width.

   65:35 is the smallest split that clears both plan conditions, measured
   live via getComputedStyle() against the real theme (Playwright, scratch
   page, deleted afterwards - not derived from source, per the
   container-query lesson in Plan 03-13). The 69rem/1104px content column
   carries no column gap (blockGap:0px, theme.json) - 65:35 nets exactly
   717.59px text / 386.41px image, i.e. the image column sits exactly on
   the ~35% floor the plan set, not below it.

   That widening ALONE was not enough: with the unchanged 7cqi from 03-13,
   717.59px still only produces a 50.23px H1 - short of the 52px H2, and
   short of the plan's own back-of-envelope estimate (~56px) for this
   split, which this measurement supersedes. Below the floor there is no
   split left to give away, so the container-query coefficient itself
   needed the "nachziehen" (follow-up) the task title calls for: raised
   from 7cqi to 7.5cqi, still comfortably under the 7.85%-of-column-width
   break point 03-13 established empirically (word-break risk starts
   there, independent of the column's absolute pixel width, since cqi is
   itself a percentage of the container - confirmed here by testing all
   six HERO_WORTBRUCH_TESTTEXTE at every breakpoint, unbroken). Real
   result at 1440px: H1 53.82px > H2 52px. At 768/375px the columns stack
   (single column, cols-lg breaks at 64rem) so the ratio below does not
   apply there and H1 trails H2 as before - the plan only requires the
   ordering at 1440px. */
@media (min-width: 64rem) {
	body .wp-block-columns.cols-lg > .hero-flat-col {
		flex-grow: 65 !important;
	}

	body .wp-block-columns.cols-lg > .hero-flat-img-col {
		flex-grow: 35 !important;
	}
}

/* ------------------------------------------------------------------ */
/* section-logo-band (G-03-C1, gap-closure 03-18): quantity-driven grid   */
/* ------------------------------------------------------------------ */

/* base.css's ".logo-band" rule (lines ~173/182/202) is a FIXED grid
   (3/4/6 columns at 0/40rem/64rem) built for exactly 12 logos
   (home-logoband.php). The baustein's inserter description promises
   3 to 12 logos, but inherits that fixed grid regardless of count - at
   7 logos and 1440px that left a 940px gap and a lone logo in row two
   (see plan objective). base.css and home-logoband.php are NOT touched:
   this rule lives entirely in a second, additive class,
   ".logo-band-auto", carried ONLY by the baustein
   (section-logo-band.php), never by the home page's band.

   Recipe: column count follows a fixed formula, not auto-fit/auto-fill -
   auto-fit balances the FIRST rows but not the last one (9 logos in an
   auto-fit grid capped at 8 tracks produces 8+1, still a lone logo). Given
   a per-breakpoint column cap Cmax (3/4/6, same caps as .logo-band above),
   rows = ceil(N / Cmax), columns = ceil(N / rows). That keeps the last row
   as full as the cap allows for any N - and at N=12 it reproduces the
   existing fixed grid (6/4/3) exactly, which is why the two classes can
   coexist safely: the formula generalises the accepted prototype, it does
   not contradict it.

   Selector: "body .is-layout-grid.logo-band.logo-band-auto" (three
   classes) beats "body .is-layout-grid.logo-band" (two classes) on
   specificity alone, independent of the alphabetic glob() load order in
   functions.php - the same body-prefix trick as .logo-band itself, for
   the same reason (WordPress' generated .wp-container-* rules otherwise
   win the fight).

   Counting: quantity rules match on
   ":has(> figure:nth-of-type(N):last-of-type)" - the Nth *figure* child
   that is also the *last* figure child, i.e. exactly N wp:image figures.
   Deliberately NOT ":nth-child"/":last-child": with templateLock:false the
   editor appends its own "insertion point" element as the last DOM child
   of the container, which would shift a :last-child count off by one.
   ":last-of-type" scoped to "figure" ignores that non-figure element, so
   the same rule counts correctly in both the editor canvas and the
   frontend.

   --lb-cols carries the column count; the base rule below just reads it
   with a fallback of 3 (the class's own default for out-of-range counts,
   e.g. 2 logos -> one row of 2, per plan). Quantity rules only ever set
   this one custom property - the grid-template-columns declaration itself
   stays a single rule. */
body .is-layout-grid.logo-band.logo-band-auto {
	grid-template-columns: repeat(var(--lb-cols, 3), minmax(0, 1fr));
}

/* N=7 (Task 1 tracer case - today's worst offender, see plan objective):
   375px Cmax=3 -> rows=ceil(7/3)=3, cols=ceil(7/3)=3 (3+3+1);
   768px Cmax=4 -> rows=ceil(7/4)=2, cols=ceil(7/2)=4 (4+3);
   1440px Cmax=6 -> rows=ceil(7/6)=2, cols=ceil(7/2)=4 (4+3, same value as
   768px - no 64rem override needed, the 40rem value carries through). */
body .is-layout-grid.logo-band.logo-band-auto:has(> figure:nth-of-type(7):last-of-type) {
	--lb-cols: 3;
}

/* N=4 (Task 2, full 3-12 rollout): 375px Cmax=3 -> rows=ceil(4/3)=2,
   cols=ceil(4/2)=2 (2+2). This is the ONLY quantity in 3-12 whose 375px
   Sollwert (2) differs from the class's own default (3, --lb-cols
   fallback) - every other N below resolves correctly at 375px through
   that fallback alone and gets no separate un-media-queried rule here
   ("kompakt halten" per plan: N=3/5/6/7/8/9/10/11/12 all target 3 tracks
   at 375px, i.e. Cmax itself, which is already the fallback). */
body .is-layout-grid.logo-band.logo-band-auto:has(> figure:nth-of-type(4):last-of-type) {
	--lb-cols: 2;
}

@media (min-width: 40rem) {
	body .is-layout-grid.logo-band.logo-band-auto:has(> figure:nth-of-type(7):last-of-type) {
		--lb-cols: 4;
	}

	/* N=4/8/10/11/12 (Task 2): rows=ceil(N/4), cols=ceil(N/rows) all land
	   on 4 tracks at 768px (Cmax=4) - 4 as a single full row, 8 as 4+4,
	   10 as 4+4+2, 11 as 4+4+3, 12 as 4+4+4. N=3/5/6/9 need no rule here -
	   their 768px Sollwert (3) already matches the fallback, unchanged
	   since no default-level rule touches them either. */
	body .is-layout-grid.logo-band.logo-band-auto:is(
		:has(> figure:nth-of-type(4):last-of-type),
		:has(> figure:nth-of-type(8):last-of-type),
		:has(> figure:nth-of-type(10):last-of-type),
		:has(> figure:nth-of-type(11):last-of-type),
		:has(> figure:nth-of-type(12):last-of-type)
	) {
		--lb-cols: 4;
	}
}

@media (min-width: 64rem) {
	/* N=5/9/10 (Task 2): rows=ceil(N/6), cols=ceil(N/rows) all land on 5
	   tracks at 1440px (Cmax=6) - 5 as a single row, 9 as 5+4, 10 as 5+5.
	   N=3/4/7/8 need no rule here - the 768px value from above carries
	   through this breakpoint unchanged (same value at 1440px). */
	body .is-layout-grid.logo-band.logo-band-auto:is(
		:has(> figure:nth-of-type(5):last-of-type),
		:has(> figure:nth-of-type(9):last-of-type),
		:has(> figure:nth-of-type(10):last-of-type)
	) {
		--lb-cols: 5;
	}

	/* N=6/11/12 (Task 2): same formula, 6 tracks - 6 fills the row
	   exactly, 11 lands on 6+5, and 12 reproduces the accepted FIXED
	   .logo-band grid (6/4/3, see class comment above) - the formula
	   generalises the prototype's own grid rather than contradicting it. */
	body .is-layout-grid.logo-band.logo-band-auto:is(
		:has(> figure:nth-of-type(6):last-of-type),
		:has(> figure:nth-of-type(11):last-of-type),
		:has(> figure:nth-of-type(12):last-of-type)
	) {
		--lb-cols: 6;
	}
}

/* Quantities outside 3-12 (customer spec in the inserter description, not a
   gap): no quantity rule matches, --lb-cols stays at the base selector's
   fallback (3). 2 logos -> one row with 2 (repeat(3, ...) with only two
   children leaves the third track empty, but it stays ONE row); more than
   12 -> also the default value 3, no dedicated quantity rule computed. */

/* "Anschluss" block style (D-01, Family A): marks a section that immediately
   follows the previous content section, whose own bottom padding already
   carries the visual gap — this section's top padding would otherwise stack
   on top of it and double the gap. Section padding is rendered as an inline
   style="padding-top:..." attribute (specificity 1,0,0,0), generated from the
   block attribute style.spacing.padding — a plain class selector always loses
   against an inline style attribute, so !important is not a style choice
   here, it is the only way this rule can ever win. */
:root :where(.is-style-anschluss) {
	padding-top: 0 !important;
}

/* Card fill wrapper (Plan 04.5-05, D-04): pushes a trailing element (the
   "Termin buchen" button) to the card's bottom edge, regardless of how much
   bio text precedes it. Live-probed in 04.5-RASTERPROBE.md: the surrounding
   .grid-3-lg row already stretches every card to equal height by itself
   (CSS Grid's "align-items: normal" behaves as "stretch" for non-replaced
   block boxes, no explicit layout.alignItems attribute needed or even
   offered by this WordPress version's editor UI) - what was still missing
   was fill behaviour INSIDE an already-equal-height card. The card itself
   switched from layout:constrained to layout:{"type":"flex",
   "orientation":"vertical"} (the same native mechanism
   .service-membership-card already uses further down this same pattern),
   and this class wraps only the bio paragraphs in a middle child that
   grows into the leftover space, mirroring the PoC's TeamCard.astro
   flex-1 wrapper. Deliberately NOT the mechanism Plan 04-07 rolled back
   (display:flex + flex-grow directly on the bio paragraph, which replaced
   the row's own layout and broke the 768px column count) - the row's grid
   container (.grid-3-lg, body .is-layout-grid.grid-3-lg) is untouched
   here; this rule only affects content flow inside one already-sized grid
   cell and cannot reach the column breakpoints. No specificity fight
   against a WordPress-generated .wp-container-* rule exists at this
   nesting level, so a plain :where() selector is enough.

   Second use (Plan 04.5-10, D-07): the four home-services-4.php
   Leistungskarten reuse the same class TWICE per card, one nesting
   level deeper than the team cards. ServiceCard.astro's card body is
   itself flex-1 (grows within the outer card) AND flex-col (its own
   text paragraph grows within it, pushing "Mehr erfahren" to the
   bottom) - two flex layers, not one. The theme mirrors both: the
   outer .service-card switched to layout:flex,vertical (measured
   already grid-stretched to equal row height beforehand, same
   mechanism as above), its card-sm-padded body wrapper carries
   card-fill (grows to fill the leftover height in the now-flex outer
   card) AND is itself layout:flex,vertical, and the intro paragraph
   inside it carries card-fill a second time (grows to fill the
   leftover height in that body, pushing the CTA to its bottom edge).
   Live-measured: with identical text, identical font metrics and an
   identical 3-line wrap in both trees, the PoC's paragraph box was
   96px tall against the theme's 72px - the PoC's own flex-1 was
   already stretching it to match the row's taller sibling; the theme
   had no equivalent, leaving unused space below the CTA instead. */
:root :where(.card-fill) {
	flex: 1 1 auto;
}

/* ------------------------------------------------------------------ */
/* Breakpoint-bound card grids (Plan 04.5-06, D-06)                    */
/* ------------------------------------------------------------------ */

/* Replaces .grid-auto-fit on containers whose card count is FIXED (the
   four service pages' Leistungskarten and Methodenschritte grids), where the
   exact PoC breakpoints and column count are known ahead of time and a
   continuous auto-fit formula is no longer needed. .grid-auto-fit itself
   stays in this file (see above) because five other, still-unconverted
   containers keep it - see 04.5-RASTERPROBE.md "Rasterbestand".

   grid-4-md-lg: the ListCard.astro Leistungskarten grid on all four service
   pages (md:grid-cols-2 lg:grid-cols-4, i.e. 48rem/64rem). Deliberately NOT
   the existing .grid-4-lg (base.css, 40rem/64rem) - that class's 40rem step
   would show two columns between 640-768px, where the PoC is still single-
   column (D-06, RESEARCH.md Pitfall 6). Same "body .is-layout-grid.<class>"
   specificity idiom as every other grid class in this project - without the
   body prefix, WordPress' generated .wp-container-* column rules win the
   specificity fight and this rule never applies. */
body .is-layout-grid.grid-4-md-lg {
	grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 48rem) {
	body .is-layout-grid.grid-4-md-lg {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 64rem) {
	body .is-layout-grid.grid-4-md-lg {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

/* grid-3-md-lg: same breakpoints as grid-4-md-lg above (48rem/64rem), three
   columns instead of four. Introduced on the customer's instruction of
   2026-09-08: at four columns the Leistungskarten are 258px wide, and German
   compounds in the card titles break two and three times each
   ("Markenposi-tionierung und -kom-munikation"). Peter Zimmermann: "Wäre es
   nicht besser statt 4 Kacheln 3 pro Zeile zu machen, so dass man weniger
   trennen muss. getrennte Worte lassen sich schlechter lesen."

   Kept as its own class rather than switching the four pages to the existing
   .grid-3-sm-lg (40rem/64rem): that class's 40rem step would put two columns
   on screens between 640 and 768px, where these grids are deliberately
   single-column - the same reason grid-4-md-lg exists separately from
   .grid-4-lg (see the comment above). */
body .is-layout-grid.grid-3-md-lg {
	grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 48rem) {
	body .is-layout-grid.grid-3-md-lg {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 64rem) {
	body .is-layout-grid.grid-3-md-lg {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

/* grid-3-sm-lg: MethodSteps.astro's 3-column variant (sm:grid-cols-2
   lg:grid-cols-3, i.e. 40rem/64rem) - used on the two service pages whose
   dark-stage section has exactly 3 steps and is rendered with the
   PoC's `columns={3}` prop (digital, operations). Same breakpoints as the
   existing .grid-4-lg (base.css), capped at 3 columns instead of 4 so a
   3-step page never shows an empty fourth track (D-08) - the reason
   .grid-4-lg itself cannot be reused here, unlike the two 4-step/5-step
   pages below which DO reuse it (see 04.5-RASTERPROBE.md). */
body .is-layout-grid.grid-3-sm-lg {
	grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 40rem) {
	body .is-layout-grid.grid-3-sm-lg {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 64rem) {
	body .is-layout-grid.grid-3-sm-lg {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

/* Fallbeispiel card title font-size/line-height (Plan 04.5-07, Schriftgröße-
   Restbefund): ProofCard.astro overrides .display-card's clamped font-size
   (theme.json "card" preset, clamp(1.25rem,2vw,1.625rem) -> 20px..26px) back
   down to a fixed text-lg (1.125rem/18px font-size, 1.75rem/28px
   line-height) for this one title - unlike FAQ questions or
   service-list-card titles, which keep the growing size. section-case-
   proof.php's <h3> carries has-body-font-size for NEW pages created from
   this pattern (the "body" preset is 1.125rem too), but the four already-
   created service pages hold their own copy of this markup from page
   creation time with real case-study text (Mangal, Wienerwald, …) - editing
   the pattern source does not reach them, and re-running create-pages.php
   would overwrite that real content with the pattern's placeholder text.
   This rule reaches both: it does not depend on the class being present. No
   theme.json typography.lineHeight support is enabled (the block editor's
   line-height control stays off project-wide), so line-height needs its own
   declaration rather than a block attribute. */
:root :where(.proof-card h3) {
	font-size: var(--wp--preset--font-size--body);
	line-height: 1.75rem;
}

/* USP stage on /warum-mit-uns-arbeiten/ (customer feedback Z94/Z95: "optisch
   nicht prominent genug", "das Wichtigste auf der gesamten Seite, unser
   USP!"). The nine differentiators now sit on the dark stage, so the ink/80
   tone .dash-list li inherits from home.css:518 would be dark on dark. Same
   specificity (0,1,0) on both sides - sections.css is enqueued after
   home.css (functions.php globs alphabetically), so the later source wins.
   Font-size/line-height mirror the prototype's text-xl. */
:root :where(.usp-stage .dash-list li) {
	color: color-mix(in oklab, var(--wp--preset--color--on-dark) 85%, transparent);
	font-size: 1.25rem;
	line-height: 1.75rem;
}

/* Kachel-Waise: ten Leistungskacheln in three columns leave the tenth alone
   in the last row (3+3+3+1) - exactly the look Peter Zimmermann marked on
   the Prüffelder ("die 05 stand allein in der zweiten Reihe"). The lone card
   moves into the middle column, so the last row reads as intentional instead
   of broken off. Only in the three-column stage: at two columns (48rem) ten
   cards divide evenly, at one column there is no row to balance. The rule
   fires solely when exactly one card is left over (count ≡ 1 mod 3) and does
   nothing otherwise - the five Prüffelder (3+2) keep their layout.
   Counterpart: site/src/styles/global.css. */
@media (min-width: 64rem) {
	body .is-layout-grid.kachel-raster > :last-child:nth-child(3n + 1) {
		grid-column: 2;
	}
}
