/*
 * CTA-Band — structure ported 1:1 from the standalone mockup
 * (home-mockup.BACKUP-liked-version.html); the .nn-cta button styling is shared with the
 * Hero (see hero.css) — token block below is a duplicate of hero.css's, not a shared
 * include, since .nn-cta-band isn't a descendant of .nn-hero and custom properties don't
 * cascade sideways between sibling sections.
 *
 * Background effect: a dot-particle field ("Chaos links, Ordnung rechts"), ported from
 * hero-mockup.html (Patrick's mockup, chaosCanvas) — see assets/js/cta-chaos-field.js.
 * This is deliberately NOT the Hero's blurred colour-ramp noise-field; the two sections
 * now use two different animated backgrounds on purpose.
 *
 * Grosse Screens (ab ca. 1900px, z. B. 2560x1440): die clamp()-Obergrenzen fuer Padding
 * und Ueberschrift wurden angehoben, der vw/vh-Koeffizient blieb dabei jeweils
 * unveraendert — gleiche Technik wie in cro.css (siehe dessen Kommentarblock dort).
 * Canvas/Scrim-Positionierung (JS-gesteuert) ist davon unberuehrt.
 *
 * 2026-08-28: .nn-cta-band selbst hat keinen eigenen Container (voll fluid), aber die
 * umliegenden Homepage-Sektionen (leistungen.css/warum-wir.css/team-teaser.css) wurden auf
 * eine 2200px-Spalte angehoben, um mit den CRO-Familien-Seiten gleichzuziehen — die
 * clamp()-Obergrenzen hier um denselben Faktor (~1,257) mitskaliert, damit das Band
 * proportional zur neuen, breiteren Umgebung wirkt statt vergleichsweise eng.
 */
.nn-cta-band,
.nn-cta-band *,
.nn-cta-band *::before,
.nn-cta-band *::after {
	box-sizing: border-box;
}

.nn-cta-band {
	/* --ground/--paper match the page's plain default background (body/Leistungen/
	   Team-Teaser never set one, Team-Teaser's own --paper-2 is #fff too), not the
	   slightly-off-white the Hero uses for its own separate paper tone. Since the Footer
	   got its own light background tint (--paper in footer.css, #f7f9f7/#0f1512 — same
	   convention as .section--paper on the Leistungsseiten), the CTA-Band no longer matches
	   the Footer pixel-for-pixel at the seam — deliberate, same soft section-boundary look
	   the Leistungsseiten already use between --bg and --paper sections, not a bug. */
	--ground: #0b0c0c;
	--ink: #e7e9ec;
	--jade: #288760;
	--paper: #ffffff;
	--ink-on-paper: #12211a;

	/* light is the unconditional default — see the "Light/Dark-Konvention" comment in
	   nav.css for why only the dark variant ever needs a guard/override below */
	--particle-base: 92, 168, 124;
	--particle-spark: 26, 81, 64;
	--scrim-rgb: 255, 255, 255;
	--hero-bg: var(--paper);
	--hero-ink: var(--ink-on-paper);
	--hero-text-shadow: rgba(255, 255, 255, 0.5);
	/* solid black in light mode as requested — but black-on-black would vanish once the
	   background flips dark, so the dark-mode override below keeps it at --ink instead */
	--bracket-ink: #000000;

	position: relative;
	overflow: hidden;
	isolation: isolate;
	background: var(--hero-bg);
	color: var(--hero-ink);
	padding: clamp(4rem, 12vh, 11.63rem) clamp(1.5rem, 5vw, 6.6rem);
	text-align: center;
	margin: 0;
}

@media (prefers-color-scheme: dark) {
	html:not([data-theme="light"]) .nn-cta-band {
		--particle-base: 40, 135, 96;
		--particle-spark: 255, 255, 255;
		--scrim-rgb: 11, 12, 12;
		--hero-bg: var(--ground);
		--hero-ink: var(--ink);
		--hero-text-shadow: rgba(0, 0, 0, 0.45);
		--bracket-ink: var(--ink);
	}
}
html[data-theme="dark"] .nn-cta-band {
	--particle-base: 40, 135, 96;
	--particle-spark: 255, 255, 255;
	--scrim-rgb: 11, 12, 12;
	--hero-bg: var(--ground);
	--hero-ink: var(--ink);
	--hero-text-shadow: rgba(0, 0, 0, 0.45);
	--bracket-ink: var(--ink);
}

.nn-chaos-canvas {
	position: absolute;
	inset: 0;
	z-index: 0;
	width: 100%;
	height: 100%;
	display: block;
	pointer-events: none;
}

.nn-chaos-scrim {
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	background: radial-gradient(48% 42% at 50% 50%, rgba(var(--scrim-rgb), 0.55) 0%, transparent 75%);
}

/* h2/.nn-actions need an explicit stacking context (position:relative + z-index above the
   canvas/scrim) or they'd paint UNDER the z-index:0/1 layers despite coming later in the DOM. */
.nn-cta-band .wp-block-heading {
	position: relative;
	z-index: 2;
	font-weight: 900;
	letter-spacing: -0.03em;
	font-size: clamp(2rem, 5vw, 5.66rem);
	margin: 0 0 2rem;
	text-wrap: balance;
	text-shadow: 0 1px 12px var(--hero-text-shadow);
	/* Auf Wunsch reines Schwarz statt var(--hero-ink) (#12211a, das grün-getönte Standard-Ink)
	   — nur im Light Mode: der Hintergrund ist dort weiß, Schwarz bleibt lesbar. Im Dark Mode
	   bleibt die Schrift bei --ink (hell), sonst wäre sie auf dem fast-schwarzen Hintergrund
	   praktisch unsichtbar — siehe Dark-Override direkt darunter. */
	color: #000000;
}
@media (prefers-color-scheme: dark) {
	html:not([data-theme="light"]) .nn-cta-band .wp-block-heading {
		color: var(--ink);
	}
}
html[data-theme="dark"] .nn-cta-band .wp-block-heading {
	color: var(--ink);
}

/* Eingebettetes Kontaktformular (patterns/kontakt-formular-embed.php, seit 2026-08-28 in
   den Leistungsseiten-CTAs statt eines reinen Wegführ-Buttons) — braucht dieselbe
   Stacking-Behandlung wie oben, sonst verschwindet es hinter Canvas/Scrim. Bekommt hier
   außerdem text-align:left zurück, weil .nn-cta-band selbst zentriert ist, das Formular
   aber linksbündige Labels/Inputs braucht. */
.nn-cta-band .nn-kfe {
	position: relative;
	z-index: 2;
	text-align: left;
}

/* Wort-Rotator, adapted from hero-mockup.html's #rot (same bracket-swap mechanic, slowed
   down per request — see assets/js/cta-word-rotator.js for the timing). The visible phrase
   is aria-hidden and swapped by JS; .nn-sr-only carries the equivalent static text for
   screen readers/no-JS instead. */
.nn-sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
}
.nn-rot-group {
	white-space: nowrap;
}
.nn-bracket {
	color: var(--bracket-ink);
	font-weight: 300;
	margin: 0 0.12em;
}
.nn-rot {
	display: inline-grid;
	vertical-align: baseline;
	transition: width 0.55s cubic-bezier(0.2, 0.85, 0.25, 1);
}
.nn-rot > span {
	grid-area: 1 / 1;
	justify-self: start;
	width: max-content;
	color: var(--jade);
	white-space: nowrap;
	opacity: 0;
	transform: translateY(0.65em);
	transition: opacity 0.42s ease, transform 0.55s cubic-bezier(0.2, 0.85, 0.25, 1);
}
.nn-rot > span.is-active {
	opacity: 1;
	transform: translateY(0);
}
.nn-rot > span.is-leaving {
	opacity: 0;
	transform: translateY(-0.65em);
}
/* justify-content:center explizit gesetzt statt sich auf .nn-cta-band's text-align:center zu
   verlassen — text-align wirkt nicht auf einen Flex-Container wie .wp-block-buttons (WP-Core-
   Default hierfür ist justify-content:normal, faktisch flex-start), der Button säße sonst
   links statt mittig. Bis 2026-08-31 kam die Zentrierung zufällig durch eine unscoped Regel
   in hero.css zustande (siehe deren Kommentar) — jetzt hier explizit, wo sie hingehört. */
.nn-cta-band .nn-actions.wp-block-buttons {
	position: relative;
	z-index: 2;
	display: flex;
	justify-content: center;
}

/* Below ~600px the fixed 2rem heading floor (see the h2 clamp() above) no longer shrinks,
   so the longest rotator phrase ("less noise. more impact.") stays wider than the
   available column and used to get sliced off by .nn-cta-band's own overflow:hidden — the
   nowrap/max-content/JS-measured-width mechanic above exists only to make the width tween
   between phrases look smooth on desktop, where every phrase already fits on one line.
   Overriding it back to auto (with !important, since word-rotator.js sets width inline on
   every swap) lets the active phrase wrap onto its own lines instead of overflowing;
   grid-area stacking still keeps only the active phrase visible during the crossfade.

   The brackets (and the trailing "?", same reasoning — see nn-q below) move from sibling
   spans to ::before/::after on the phrase span. Reason: .nn-rot is one atomic inline-grid
   box — once its wrapped content needs the full line width (which multi-line phrases do
   here), a SIBLING element has no room left on that last line and gets pushed onto a line
   of its own, detached from the text it's supposed to hug. A pseudo-element glued to the
   phrase's own span wraps as part of the exact same text run, so it always touches the
   phrase's first/last letter no matter where the line breaks fall. The "?" is folded into
   the same ::after as "]" (one generated string, "]?") rather than getting a pseudo-element
   of its own on a still-separate .nn-q — two independent trailing fragments would just
   recreate the original detachment risk between them. Cost: "?" loses its bold weight here
   (inherits the brackets' lighter 300) since a single `content` value can't mix font-weights
   — an acceptable trade for "?" that can never end up orphaned on its own line. */
@media (max-width: 37.5em) {
	.nn-rot-group {
		white-space: normal;
	}
	.nn-rot-group > .nn-bracket,
	.nn-rot-group > .nn-q {
		display: none;
	}
	.nn-rot {
		width: auto !important;
		max-width: 100%;
	}
	.nn-rot > span {
		white-space: normal;
		width: auto;
		max-width: 100%;
		/* overrides the desktop justify-self:start — there the grid cell always matches the
		   active phrase's own JS-measured width exactly, so alignment is moot. Here the cell
		   can end up wider than a short phrase, since all phrases share one grid-area (1/1)
		   and the implicit column sizes to fit the widest one among them — grid track sizing
		   considers every stacked item, not just the currently visible/active one. The h2's
		   own text-align:center only centers the outer .nn-rot box on its line, not the text
		   within it — without this, short phrases like "mehr Umsatz" hugged the cell's left
		   edge instead of sitting centered like the rest of the heading. */
		justify-self: center;
	}
	.nn-rot > span::before {
		content: "[";
		color: var(--bracket-ink);
		font-weight: 300;
	}
	.nn-rot > span::after {
		content: "]?";
		color: var(--bracket-ink);
		font-weight: 300;
	}
}
