/*
Theme Name: Druckio Child
Theme URI: https://druckio.de
Description: Child-Theme für Druckio – projektspezifische Anpassungen und Styles.
Author: Druckio
Template: druckio
Version: 1.0.0
Requires at least: 6.4
Tested up to: 6.8
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: druckio-child
*/

/* Projekt-spezifische Overrides hier einfügen. */

/* ------------------------------------------------------------------
   Lesbarer Satzspiegel auf reinen Textseiten
   Das Parent-Theme begrenzt .entry-content nicht; ohne Elementor lief
   der Text deshalb randlos über die volle Fensterbreite.
   ------------------------------------------------------------------ */

body:not(.elementor-page) .site-main .entry-header,
body:not(.elementor-page) .site-main .entry-content {
	box-sizing: border-box;
	width: 100%;
	max-width: calc(39rem + 2 * var(--druckio-gutter, 1.25rem));
	margin-inline: auto;
}

body:not(.elementor-page) .site-main .entry-content {
	padding: 0 var(--druckio-gutter, 1.25rem) 5rem;
}

/* ------------------------------------------------------------------
   Rechtstexte in Elementor-Containern auf dieselbe Lesebreite

   Die fuenf Rechtsseiten sind unterschiedlich gebaut: AGB und
   Widerrufsbelehrung sind klassische WordPress-Seiten, Impressum,
   Datenschutz und Cookie-Richtlinie liegen in Elementor-Containern.
   Sie fielen dadurch optisch in zwei Gruppen auseinander.

   Beide Gruppen trugen zwar 44rem, aber an verschiedenen Kaesten: Bei
   den klassischen Seiten sitzt die Angabe auf einem border-box, von dem
   die Rinne noch abgeht. Die Rinne ist nicht fest, sondern
   clamp(1.25rem, 4vw, 2.5rem) - die Textbreite schwankte deshalb mit der
   Fensterbreite: 320px bei 375, 642,6px bei 768, 632px bei 900, und erst
   ab 1024px die 624px, mit denen unten gerechnet wird. Beim
   Elementor-Container wirkt --content-width dagegen auf die
   Inhaltsbreite selbst, dort waren es durchgehend volle 704px.

   Die Zeichen pro Zeile sind bei 1280px gemessen, also im Endzustand
   beider Gruppen.

   Gemessen wurden die Zeichen pro Zeile, nicht geschaetzt (Median ueber
   alle vollen Zeilen der sechs laengsten Absaetze je Seite):

     624px bei 17px  ->  AGB 73, Widerruf 74 Zeichen
     704px bei 16px  ->  Impressum 90, Datenschutz 87, Cookie 87

   Der brauchbare Bereich liegt zwischen 45 und 90 Zeichen. Die zweite
   Gruppe stand am oberen Rand und darueber: einzelne Zeilen erreichten
   93 Zeichen. Die erste Gruppe liegt mit 73 mitten im Bereich. Deshalb
   gewinnen 624px und 17px, obwohl die 704px die aeltere Festlegung
   sind - die Festlegung wurde fuer 17px getroffen und traegt bei 16px
   nicht mehr.

   39rem = 624px, also genau die Textbreite der klassischen Seiten.
   ------------------------------------------------------------------ */

.is-legal-page .entry-content .e-con {
	--content-width: min(100%, 39rem);
}

/* Die Rinne zum Fensterrand fehlte den Elementor-Containern ganz.
   Gemessen bei 375px: Der Rechtstext begann bei 0 und endete bei 360 -
   er klebte an beiden Bildschirmkanten, waehrend AGB und
   Widerrufsbelehrung dort 20px Luft haben. Dieselbe Variable wie bei
   den klassischen Seiten, damit beide Gruppen denselben Rand mitgehen:
   clamp(1.25rem, 4vw, 2.5rem), also 20px schmal und 40px breit.

   .e-parent trifft nur die aeussersten Container. Ein Kindselektor
   waere hier falsch: Der Container haengt nicht unmittelbar unter
   .entry-content, sondern unter dem Zwischenkasten div.elementor. */
.is-legal-page.elementor-page .entry-content .e-con.e-parent {
	padding-inline: var(--druckio-gutter, 1.25rem);
}

/* Übersichtsseite Leistungen braucht mehr Platz für Bild und Text.

   Achtung beim Umsortieren: Diese Regel wiegt genau so schwer wie die
   Regel oben (beide 0-3-1 — das :not() selbst zählt nichts, sein
   Argument .elementor-page zählt als Klasse). Sie gewinnt allein, weil
   sie später in der Datei steht. Wird die Datei umgestellt oder mit
   einer anderen zusammengeführt, fällt die Leistungsübersicht still von
   68rem auf die schmale Textbreite zurück. */
body.is-service-index .site-main .entry-header,
body.is-service-index .site-main .entry-content {
	max-width: 68rem;
}

/* Fließtext zwischen den Karten bleibt auf Lesebreite */
body.is-service-index .entry-content > p,
body.is-service-index .entry-content > h2,
body.is-service-index .entry-content > h3 {
	max-width: 44rem;
}

/* ------------------------------------------------------------------
   Typografie für Fließtext ohne Elementor
   ------------------------------------------------------------------ */

body:not(.elementor-page) .entry-content,
.is-legal-page .entry-content {
	font-size: 1.0625rem;
	line-height: 1.75;
}

/* Auf den Elementor-Rechtsseiten erbte der Fliesstext 16px, Halbfett
   (600) und #0A0A0A vom body - nachgesehen: keine einzige Regel
   spricht diese Absaetze direkt an, alles kommt ueber Vererbung. Eine
   Angabe auf .entry-content genuegt deshalb, um sie zu erreichen.
   Halbfett ueber einen mehrseitigen Rechtstext ist der auffaelligste
   Unterschied der beiden Gruppen gewesen.

   Der Grauton bleibt bewusst unangetastet: #0A0A0A gegen #1A1F2E sind
   19,6:1 gegen 16,2:1 auf Weiss, beides tiefes Schwarzgrau und im Bild
   nicht zu unterscheiden. #0A0A0A ist ausserdem der Ton, den die
   uebrige Website in Elementor durchgaengig traegt - ihn nur auf drei
   Seiten zu aendern schuefe eine neue Abweichung statt eine zu
   beheben. */
.is-legal-page.elementor-page .entry-content {
	font-weight: 400;
}

/* Die Ueberschrift stand auf den Elementor-Seiten in einem
   Textfeld-Widget ganz ohne eigene Angabe und fiel damit auf die
   Vorgabe des Browsers zurueck: h1 = 2em = 32px. Die klassischen
   Seiten holen ihre Groesse aus .entry-title des Elterntemas. Dort
   steht clamp(1.75rem, 4vw, 2.5rem) - also 28px auf schmalen Schirmen
   und 40px ab 1000px Fensterbreite. Der Wert wird woertlich
   uebernommen, nicht auf die 40px des Endzustands festgenagelt: Sonst
   staende die Ueberschrift bei 375px mit 40px gegen 28px der beiden
   klassischen Seiten - genau die Zweiteilung, die hier weggeht. */
.is-legal-page.elementor-page .entry-content h1 {
	margin-block: 0 1rem;
	font-size: clamp(1.75rem, 4vw, 2.5rem);
	line-height: 1.2;
	font-weight: 700;
}

body:not(.elementor-page) .entry-content h2,
.is-legal-page .entry-content h2 {
	margin-block: 3rem 0.85rem;
	font-size: clamp(1.4rem, 2.6vw, 1.75rem);
	line-height: 1.25;
	letter-spacing: -0.01em;
}

body:not(.elementor-page) .entry-content h3,
.is-legal-page .entry-content h3 {
	margin-block: 2rem 0.6rem;
	font-size: clamp(1.1rem, 2vw, 1.25rem);
	line-height: 1.35;
}

body:not(.elementor-page) .entry-content p,
body:not(.elementor-page) .entry-content ul,
body:not(.elementor-page) .entry-content ol,
.is-legal-page .entry-content p,
.is-legal-page .entry-content ul,
.is-legal-page .entry-content ol {
	margin-block: 0 1.1rem;
}

body:not(.elementor-page) .entry-content ul,
body:not(.elementor-page) .entry-content ol,
.is-legal-page .entry-content ul,
.is-legal-page .entry-content ol {
	padding-left: 1.4rem;
}

body:not(.elementor-page) .entry-content li,
.is-legal-page .entry-content li {
	margin-block: 0.4rem;
}

/* Die Linienfarben stammten aus dem dunklen Farbschema und standen auf
   den hellen Textseiten weiss auf weiss. Nachgemessen: Der Grund hinter
   Trennlinie und Tabelle ist #FFFFFF (--druckio-color-page-bg), die
   Linien trugen rgba(255,255,255,0.14) bzw. 0.12 und 0.28 - Kontrast
   1,00:1, also gar nicht vorhanden. Betroffen sind die zwei <hr> der
   Widerrufsbelehrung und die einzige Tabelle des Bestands
   („Speicherdauer im Ueberblick" auf der Datenschutzerklaerung).

   Die Ersatzwerte spiegeln dieselbe Entscheidung, die im Abschnitt
   „Kopfstreifen und Hero verschmolzen" schon getroffen wurde: fuer
   nicht-textliche Elemente die Schwelle von 3:1 halten und darueber
   nicht hinausschiessen.
     rgba(0,0,0,0.42) auf Weiss  = #949494  3,03:1  - Trennlinie, Zellen
     rgba(0,0,0,0.55) auf Weiss  = #737373  4,76:1  - Kopfzeile, staerker
   Das Verhaeltnis der beiden bleibt damit wie vorher: die Kopfzeile
   traegt die kraeftigere Linie.

   Alle Seiten mit diesen Elementen sind hell - nachgezaehlt ueber alle
   13 Seiten. Landet eine Tabelle spaeter in einem dunklen
   Elementor-Abschnitt, gehoert die Farbe dort erneut geprueft. */
body:not(.elementor-page) .entry-content hr,
.is-legal-page .entry-content hr {
	margin-block: 3rem;
	border: 0;
	border-top: 1px solid rgba(0, 0, 0, 0.42);
}

body:not(.elementor-page) .entry-content a,
.is-legal-page .entry-content a {
	color: var(--druckio-color-accent, #2b6cee);
	text-underline-offset: 0.2em;
}

/* ------------------------------------------------------------------
   Leistungsübersicht: Bild und Text nebeneinander
   ------------------------------------------------------------------ */

.leistung {
	display: grid;
	grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
	gap: clamp(1.5rem, 4vw, 3rem);
	align-items: center;
	margin-block: 3.5rem;
}

.leistung--gespiegelt {
	grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
}

.leistung--gespiegelt .leistung__bild {
	order: 2;
}

.leistung__bild img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 3 / 2;
	object-fit: cover;
	border-radius: 0.75rem;
}

.leistung__text h2 {
	margin-top: 0;
}

.leistung__eignung {
	color: var(--druckio-color-muted, #8d97ad);
	font-size: 0.95rem;
}

.leistung__link {
	display: inline-block;
	margin-top: 0.5rem;
	font-weight: 600;
}

@media (max-width: 782px) {
	.leistung {
		grid-template-columns: 1fr;
		gap: 1.25rem;
	}

	.leistung--gespiegelt {
		grid-template-columns: 1fr;
	}

	.leistung--gespiegelt .leistung__bild {
		order: 0;
	}
}


/* Datenschutzhinweis über der Absendeschaltfläche */
.formular-datenschutz {
	margin-block: 1.5rem 1rem;
	max-width: 44rem;
	/* Nicht mehr --druckio-color-muted (#8D97AD): 2,93:1 auf Weiß war der
	   schlechteste Kontrastwert der Website. Begründung und Rechenweg
	   stehen im Abschnitt „Vier belegte Darstellungsfehler" am Dateiende. */
	color: #5E6A86;
	font-size: 0.875rem;
	line-height: 1.6;
}

.formular-datenschutz a {
	color: inherit;
	text-underline-offset: 0.2em;
}

.formular-datenschutz a:hover,
.formular-datenschutz a:focus-visible {
	color: var(--druckio-color-accent, #2b6cee);
}

/* ------------------------------------------------------------------
   Rechtstexte: Tabellen und hervorgehobene Hinweise
   Gilt auch innerhalb von Elementor-Textfeldern, deshalb ohne
   :not(.elementor-page)-Einschränkung.
   ------------------------------------------------------------------ */

.entry-content table {
	width: 100%;
	margin-block: 1.5rem 2rem;
	border-collapse: collapse;
	font-size: 0.95rem;
}

.entry-content th,
.entry-content td {
	padding: 0.7rem 0.9rem;
	border-bottom: 1px solid rgba(0, 0, 0, 0.42);
	text-align: left;
	vertical-align: top;
}

.entry-content th {
	font-weight: 600;
	border-bottom-color: rgba(0, 0, 0, 0.55);
}

.entry-content tr:last-child td {
	border-bottom: 0;
}

/* Der Hinweis auf das Widerspruchsrecht muss nach Artikel 21 Absatz 4 DSGVO
   von den übrigen Angaben getrennt und hervorgehoben dargestellt werden. */
.entry-content blockquote {
	margin-block: 2.5rem;
	margin-inline: 0;
	padding: 1.5rem 1.75rem;
	border: 1px solid rgba(43, 108, 238, 0.45);
	border-left: 4px solid var(--druckio-color-accent, #2b6cee);
	border-radius: 0.5rem;
	background: rgba(43, 108, 238, 0.07);
}

.entry-content blockquote > *:first-child {
	margin-top: 0;
}

.entry-content blockquote > *:last-child {
	margin-bottom: 0;
}

/* Breite Tabellen dürfen die Seite nicht seitlich schieben */
@media (max-width: 560px) {
	.entry-content table {
		display: block;
		overflow-x: auto;
	}
}

/* ------------------------------------------------------------------
   Karten „Einsatzbereiche" auf den Leistungsseiten und die
   Praxiskarten der Startseite (beide tragen die Klasse g-901e541)
   Eckenradius, Beschnitt, Spaltenrichtung und Bildseitenverhältnis
   der Karten stehen bei Elementor ausschließlich in der erzeugten
   Datei uploads/elementor/css/local-<Seiten-ID>-frontend-*.css.
   Diese Datei wird beim Leeren des Elementor-Caches gelöscht und erst
   beim nächsten Seitenaufruf neu geschrieben. Bis dahin verlieren die
   Karten Rundung, Beschnitt und Seitenverhältnis: Die Ecken sind eckig,
   Bild und Text rutschen nebeneinander, und die Karten stehen
   unterschiedlich hoch. Die Regeln stehen deshalb hier fest.
   ------------------------------------------------------------------ */

.elementor .e-con.g-901e541 {
	flex-direction: column;
	align-self: stretch;
	overflow: hidden;
	border-radius: 20px;
}

/* Der Textteil füllt die Restfläche, damit alle Karten gleich hoch enden */
.elementor .e-con.g-901e541 > .e-con:last-child {
	flex: 1 1 auto;
}

/* Nur das Kartenbild: Es sitzt allein im ersten Kind der Karte, der
   Text steht im zweiten. Ein etwaiges Bild im Textteil bleibt außen vor. */
.elementor .e-con.g-901e541 > .e-con:first-child img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 9;
	object-fit: cover;
}

/* ------------------------------------------------------------------
   Footer-Logo in nativer Größe
   Der Schriftzug „Druck- & Produktionslösungen" ist Teil der Logodatei
   und war bei 56 px Höhe nicht mehr lesbar. Die Datei misst nativ
   332 × 95 px – mehr gibt sie nicht her, größer würde unscharf.
   ------------------------------------------------------------------ */

.site-footer .site-footer__brand .site-branding img,
.site-footer .site-footer__brand .site-branding .custom-logo {
	max-height: 95px;
	max-width: 100%;
}

/* Die Markenspalte war mit 309 px schmaler als das Logo. Sie wächst von
   1,35 auf 1,55 Anteile, damit die vollen 332 px hineinpassen. Die
   vierspaltige Aufteilung bleibt dabei erhalten, die drei Linkspalten
   geben je rund 8 px ab. */
@media (min-width: 48rem) {
	.site-footer .site-footer__grid {
		grid-template-columns: minmax(0, 1.55fr) repeat(3, minmax(0, 1fr));
	}
}

/* Etwas mehr Luft unter dem nun höheren Logo */
.site-footer .site-footer__brand .site-footer__tagline {
	margin-top: 1.75rem;
}

/* ------------------------------------------------------------------
   Anwendungsbereich der Leistungsseiten absetzen

   Der Bereich „Anwendungen/Einsatzbereiche" und der Abschlussbereich
   tragen beide #06173F und gingen ohne sichtbare Kante ineinander über.

   Zwei Wege wurden verworfen: Eine Trennlinie wirkte auf der großen
   Fläche wie ein Versehen. Und den Abschlussbereich abzudunkeln ging
   nicht — sein Hintergrundbild (CTA.jpg) hat den Verlauf bereits
   eingebrannt: Die linke Bildhälfte ist einfarbig #06173F und geht dort
   in das Foto über. Eine abweichende Flächenfarbe erzeugt genau an der
   Bildkante einen harten senkrechten Bruch.

   Deshalb wird stattdessen der Bereich davor abgedunkelt — er trägt
   kein Hintergrundbild, seine Farbe ist frei wählbar. #020D1E ist der
   Ton, den der Kopfbereich der Seite bereits verwendet; die Seite
   bekommt dadurch einen Rhythmus aus vorhandenen Farben statt eines
   neu erfundenen Zwischentons.

   Kontrast der weißen Schrift steigt von 17,5:1 auf über 19:1.
   ------------------------------------------------------------------ */

.elementor .e-f378fb2-41dd1fd.bg-dark {
	background-color: #020D1E;
}

/* ------------------------------------------------------------------
   Druckverfahren als Mehrfachauswahl

   Aus dem einzelnen Auswahlfeld sind sechs Kontrollkästchen geworden
   (Filter druckio_child_formular_druckverfahren in der functions.php).
   Ohne eigene Angaben hingen sie als nackte Liste untereinander:
   assets/css/contact-form.css kennt nur Text-, Auswahl- und Textfelder
   und nimmt Kästchen ausdrücklich aus.

   Warum die Selektoren hier so lang sind: Die Feldregel in
   contact-form.css trägt vier :not([type=…]) und wiegt dadurch schwerer
   als ein üblicher Selektor. Sie greift sogar auf die <span>-Hülle der
   Kästchengruppe — ein <span> hat gar kein type-Attribut, also treffen
   alle vier Ausschlüsse zu, und die Gruppe bekäme Rahmen, Polster und
   weißen Grund eines Eingabefelds. Da contact-form.css nach dieser
   Datei geladen wird, muss der Selektor hier schwerer wiegen; er
   wiederholt deshalb dieselben Ausschlüsse.
   ------------------------------------------------------------------ */

.form-wrapper .wpcf7-form .feld-druckverfahren {
	margin: 0;
	padding: 0;
	border: 0;
	/* Ohne das behält ein fieldset seine Mindestbreite aus dem Inhalt und
	   sprengt auf schmalen Schirmen die Spalte. */
	min-inline-size: 0;
}

.form-wrapper .wpcf7-form .feld-druckverfahren legend {
	display: block;
	width: 100%;
	margin-bottom: 0.5rem;
	padding: 0;
	font-size: 0.875rem;
	font-weight: 500;
	line-height: 1.4;
	color: var(--druckio-field-text);
}

/* CF7 legt die Kästchengruppe in einen Absatz, weil sie in einem
   fieldset steht — dessen Außenabstand würde den Zeilenabstand des
   Formulars verdoppeln. */
.form-wrapper .wpcf7-form .feld-druckverfahren p {
	margin: 0;
}

.form-wrapper .wpcf7-form .feld-druckverfahren .wpcf7-checkbox.wpcf7-form-control:not([type="submit"]):not([type="checkbox"]):not([type="radio"]):not([type="file"]) {
	display: grid;
	/* Zwei Spalten, sobald rund 28 rem Platz sind; darunter eine. Das
	   min() verhindert, dass eine Spalte breiter wird als der Platz —
	   sonst liefe die Seite bei 375 px waagerecht über. */
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr));
	gap: 0.625rem;
	padding: 0;
	background: none;
	border: 0;
	border-radius: 0;
}

.form-wrapper .wpcf7-form .feld-druckverfahren .wpcf7-list-item {
	display: flex;
	margin: 0;
}

/* Jede Option ist ein eigenes Kästchen im Zuschnitt der übrigen Felder:
   gleiche Höhe, gleicher Rahmen, gleiche Ecken. Die Beschriftung gehört
   zur Trefferfläche, damit sie auch mit dem Finger sicher zu treffen
   ist. */
.form-wrapper .wpcf7-form .feld-druckverfahren .wpcf7-list-item label {
	display: flex;
	flex: 1;
	align-items: center;
	gap: 0.625rem;
	box-sizing: border-box;
	min-height: var(--druckio-field-height);
	margin: 0;
	padding: 0.625rem 0.875rem;
	font-size: 1rem;
	font-weight: 400;
	line-height: 1.35;
	color: var(--druckio-field-text);
	background-color: var(--druckio-field-bg);
	border: 1px solid var(--druckio-field-border);
	border-radius: var(--druckio-field-radius);
	cursor: pointer;
	transition:
		border-color 220ms cubic-bezier(0.4, 0, 0.2, 1),
		box-shadow 220ms cubic-bezier(0.4, 0, 0.2, 1),
		background-color 220ms cubic-bezier(0.4, 0, 0.2, 1);
}

.form-wrapper .wpcf7-form .feld-druckverfahren .wpcf7-list-item label:hover {
	border-color: #b8bec8;
}

/* Der Rahmen zeigt die Tastaturmarke an — das Kästchen selbst ist zu
   klein, als dass sein eigener Fokusring auffiele. */
.form-wrapper .wpcf7-form .feld-druckverfahren .wpcf7-list-item label:focus-within {
	border-color: var(--druckio-field-focus);
	box-shadow: 0 0 0 3px rgba(46, 107, 255, 0.15);
}

/* :has beherrschen alle aktuellen Browser; ältere zeigen den
   Normalzustand — der Haken im Kästchen bleibt so oder so sichtbar. */
.form-wrapper .wpcf7-form .feld-druckverfahren .wpcf7-list-item label:has(input:checked) {
	background-color: rgba(46, 107, 255, 0.06);
	border-color: var(--druckio-field-focus);
}

.form-wrapper .wpcf7-form .feld-druckverfahren input[type="checkbox"] {
	flex: none;
	width: 1.125rem;
	height: 1.125rem;
	margin: 0;
	accent-color: var(--druckio-field-focus);
}

/* Fehlt die Pflichtangabe, markiert CF7 nur die Gruppe. Ohne diese
   Zeile bliebe die Meldung ohne sichtbaren Bezug zu den Kästchen. */
.form-wrapper .wpcf7-form .feld-druckverfahren .wpcf7-not-valid .wpcf7-list-item label {
	border-color: #dc2626;
}

.form-wrapper .wpcf7-form .feld-druckverfahren .wpcf7-not-valid-tip {
	display: block;
	margin-top: 0.5rem;
}

/* ------------------------------------------------------------------
   Kopfstreifen auf den Grundton des Logos

   Das Logo ist eine PNG-Datei ohne Alphakanal — sein Hintergrund ist
   mitfotografiert und liegt als Fläche in der Datei. Solange der
   Kopfstreifen einen anderen Ton trug, stand das Logo als abgesetzter
   Kasten darin.

   Gemessen aus cropped-logo.png (332 × 95 px, Palettenbild, 75 Farben,
   keine Transparenz): Alle 6576 Pixel des acht Pixel breiten Rands
   ringsum tragen denselben Wert #020D1E — eine Volltonfläche, kein
   Verlauf. Zweifach geprüft: einmal über Canvas im Browser, einmal
   durch Entpacken der PNG-Datei selbst.

   Der Kopfstreifen bekommt seine Farbe im Elterntheme über
   --druckio-color-bg (#060A12). Diese Variable färbt auch den
   Fußbereich und die Klappnavigation; deshalb wird hier nicht die
   Variable geändert, sondern nur die Fläche des Kopfstreifens.
   ------------------------------------------------------------------ */

.site-header {
	background-color: #020D1E;
}

/* ------------------------------------------------------------------
   Fußbereich auf denselben Ton wie der Kopfstreifen

   Im Fuß steht dasselbe Logo wie oben. Solange die Fläche dort
   #060A12 trägt und der Logohintergrund #020D1E ist, zeichnet sich
   das Logo als heller Kasten ab – derselbe Fehler wie zuvor im
   Kopfbereich, nur eine Etage tiefer.

   Wieder wird nicht die Variable --druckio-color-bg geändert, sondern
   nur die Fläche des Fußbereichs. Die Klappnavigation behält damit
   ihren bisherigen Ton.
   ------------------------------------------------------------------ */

.site-footer {
	background-color: #020D1E;
}

/* ==================================================================
   Vier belegte Darstellungsfehler, behoben am 06.08.2026

   Alle Werte sind im Browser gemessen, nicht geschätzt: Überläufe über
   scrollWidth gegen clientWidth, Kontraste nach WCAG 2.1 aus der
   relativen Luminanz der tatsächlich gerenderten Farben.
   ================================================================== */

/* ------------------------------------------------------------------
   1 · Der Kopfstreifen lief auf schmalen Schirmen waagerecht über

   Gemessen bei 375 px: scrollWidth 414 gegen clientWidth 375, also
   39 px Überlauf – und zwar auf jeder Seite, weil die Ursache im
   Kopfstreifen sitzt (auf /agb/ waren es 35 px, dort ist der Menüknopf
   minimal schmaler).

   Die Markenspalte ist ein Flex-Element mit flex: 0 0 auto. Sie
   schrumpft deshalb nie, obwohl das Logo längst max-width: 100% trägt –
   das allein reicht nicht, solange der Kasten darum starr bleibt.
   Rechnung für eine Zeile ohne Überlauf: 10 px Polster + 332 px Logo +
   24 px Spaltenabstand + 48 px Menüknopf + 10 px Polster = 424 px.

   Der Umschaltpunkt liegt deshalb genau dort. Ab 424 px behält das Logo
   seine nativen 332 × 95 px; darunter schrumpft es mit. Bei 375 px misst
   es dann 283 × 81 px, der Schriftzug „Druck- & Produktionslösungen"
   bleibt lesbar – nachgesehen, nicht nur gerechnet.
   ------------------------------------------------------------------ */

@media (max-width: 423px) {
	.site-header .site-branding {
		flex-shrink: 1;
		/* Ohne min-width: 0 behielte das Flex-Element die Mindestbreite
		   seines Inhalts und schrumpfte trotz flex-shrink nicht. */
		min-width: 0;
	}

	.site-header .site-branding .custom-logo-link {
		display: block;
		min-width: 0;
	}

	.site-header .site-branding img {
		max-width: 100%;
		height: auto;
	}
}

/* ------------------------------------------------------------------
   2 · Das Deko-Raster im Fußbereich schob die Seite zur Seite

   .site-footer__main::before (footer-grid.png, 352 × 288) sitzt mit
   right: -1rem absichtlich etwas über der Kante des 1140er-Containers.
   Sobald der Container die Fensterkante berührt, ragen diese 16 px aus
   dem Fenster hinaus: gemessen 6 px Überlauf bei 768 px – das Polster
   von 10 px fängt nur einen Teil ab.

   Die Grenze liegt bei 1172 px Inhaltsbreite = 1140 px Container
   + 2 × 16 px. Achtung, das ist die Breite ohne Scrollleiste: Ein
   Media-Query misst die Fensterbreite einschließlich der 15 px breiten
   Leiste. Die Regel muss deshalb bis 1186 px greifen, nicht bis 1171.

   Nachgemessen im Rahmen fester Breite, mit dem alten Wert 1171:
   bei 1172 px 6 px Überlauf, bei 1180 px 4 px, bei 1186 px 1 px, ab
   1187 px keiner mehr. Genau diese Lücke schließt der neue Wert.
   Darüber bleibt der Überstand in der freien Randfläche und stört
   nicht, deshalb greift die Regel nur darunter.

   overflow: hidden auf .site-footer__main wurde geprüft und verworfen:
   die Grafik ragt mit top: -2.5rem auch 40 px nach oben in das Polster
   des Fußbereichs. overflow: hidden hätte diese 40 px mit abgeschnitten
   und die Grafik oben angeschnitten. Zurückgenommen wird deshalb nur der
   seitliche Überstand, und nur dort, wo er aus dem Fenster ragt.
   ------------------------------------------------------------------ */

@media (max-width: 1186.98px) {
	.site-footer__main::before {
		right: 0;
	}
}

/* ------------------------------------------------------------------
   3 · Vier Farbpaare unter der Schwelle von 4,5:1

   Die Ersatzfarben sind aus der vorhandenen Palette gemischt, nicht frei
   gewählt: Akzent #2E6BFF, dunkle Flächen #020D1E und #06173F, helle
   Fläche #F5F8FF.

   a) Rubrikzeile .preline (12 px, 600) auf hellem Grund
      bisher #2E6BFF auf #F5F8FF   4,24:1
      neu    #265AD9 auf #F5F8FF   5,57:1   (auf Weiß 5,92:1)
      #265AD9 = Akzent 80 % + #06173F 20 %.

   b) Dieselbe Zeile auf dunklem Grund
      bisher #2E6BFF auf #06173F   3,88:1
      neu    #779FFF auf #06173F   6,81:1   (auf #020D1E 7,59:1)
      #779FFF = Akzent 65 % + Weiß 35 %.

      Die Unterscheidung hängt an der Klasse .bg-dark. Auf allen elf
      Seiten wurde nachgezählt: kein dunkler Abschnitt ohne diese Klasse
      und keine .bg-dark auf hellem Grund. Käme später ein dunkler
      Abschnitt ohne .bg-dark hinzu, stünde dort die dunkle Variante der
      Rubrikzeile auf dunklem Grund – dann gehört .bg-dark ergänzt.

   c) Formularhinweis .formular-datenschutz (14 px, 600) auf Weiß
      bisher #8D97AD   2,93:1   – schlechtester Wert der Website
      neu    #5E6A86   5,41:1
      #5E6A86 = bisheriges #8D97AD 65 % + #06173F 35 %. Die Farbe steht
      oben in der Regel selbst, der Link darin erbt sie.

   d) Kartentext .card-text-grey-14 auf #F5F8FF
      bisher #737373   4,46:1
      neu    #6E6E6E   4,80:1   (auf Weiß 5,10:1)

      .card-text-grey-16 trägt dieselbe Farbe aus --text-mid, und auf
      /kontakt/ trägt derselbe Absatz beide Klassen – deshalb stehen hier
      beide. Das :not() nimmt die hellen Zeilen auf dunklem Grund aus:
      Sie holen ihre Farbe aus .inverted-text-light-16 (#A8B9E2), und
      diese Datei wird nach der Elementor-Datei geladen, würde sie also
      sonst überschreiben und dunkelgrauen Text auf dunklen Grund setzen.
   ------------------------------------------------------------------ */

.elementor .preline {
	color: #265AD9;
}

.elementor .bg-dark .preline {
	color: #779FFF;
}

.elementor .card-text-grey-14:not(.inverted-text-light-16),
.elementor .card-text-grey-16:not(.inverted-text-light-16) {
	color: #6E6E6E;
}

/* ------------------------------------------------------------------
   4 · Kopfstreifen und Hero verschmolzen auf der Startseite

   Beide Flächen tragen #020D1E. Getrennt wurden sie nur durch eine
   1-px-Linie in rgba(255, 255, 255, 0.06) – über der Fläche ergibt das
   den Ton #111C2C und 1,13:1, praktisch unsichtbar.

   Ein Schatten unter dem Kopfstreifen wurde ausprobiert und wieder
   entfernt: Schwarz über #020D1E bringt selbst bei 85 % Deckung nur
   1,05:1. Auf einer fast schwarzen Fläche kann ein dunkler Schatten
   nichts sichtbar machen – die Kante muss die Linie selbst leisten.

   rgba(255, 255, 255, 0.34) ergibt über #020D1E den Ton #585F6A und
   3,03:1. Das liegt über der Schwelle von 3:1 für nicht-textliche
   Elemente und bleibt im Bild eine feine Haarlinie. Die Flächenfarben
   bleiben unangetastet: #020D1E stammt aus dem Logohintergrund.
   ------------------------------------------------------------------ */

.site-header {
	border-bottom-color: rgba(255, 255, 255, 0.34);
}

/* ------------------------------------------------------------------
   Hinweis auf KI-erzeugte Bilder

   Steht als Fußnote am Ende jeder Karte, unter dem beschreibenden
   Text. Im Elementor-Baum sitzt das Widget aus technischen Gründen
   an erster Stelle; weil die Karte ein Flex-Container in Spalten-
   richtung ist, schiebt „order" es ohne Umbau der Seitendaten ans
   Ende. Auf der klassisch gebauten Leistungsseite steht es ohnehin
   schon hinten – dort ist „order" wirkungslos und stört nicht.

   Auf Ronnys Wunsch am 07.08.2026 kleiner und heller gesetzt:
   11 px / #6E6E6E  ->  10 px / #767676.

   #767676 ist der hellste Grauton, der auf Weiß noch 4,54:1 erreicht
   und damit knapp über der Schwelle von 4,5:1 bleibt. Heller geht
   nicht ohne Verlust der Barrierefreiheit: #808080 fällt auf 3,95:1
   und wäre nur noch für großen Text zulässig – der Hinweis ist aber
   der kleinste Text der Seite. Wer hier weiter aufhellt, macht die
   KI-Kennzeichnung praktisch unlesbar, und genau dafür steht sie da.
   ------------------------------------------------------------------ */

.ki-hinweis {
	order: 99;
	margin-block: 0.6rem 0;
}

/* Elementor erzeugt je Widget eine eigene Regel mit einer Klasse auf
   .elementor-Ebene. Größe und Farbe brauchen deshalb dieselbe
   Spezifität, sonst gewinnt die Widget-Regel. */
.elementor .ki-hinweis,
.leistung .ki-hinweis {
	color: #767676;
	font-size: 0.625rem;
	line-height: 1.5;
}

.leistung__bild .ki-hinweis,
.leistung .ki-hinweis {
	margin-block: 0.5rem 0;
}

/* ------------------------------------------------------------------
   Schlusszeile des Fußbereichs mittig setzen

   Der Sockel war als „space-between" für zwei Elemente angelegt –
   Copyright links, Rechtsmenü rechts. Seit die Rechtslinks in die
   Spalte „Service" gewandert sind, steht dort nur noch ein Element
   und klebte am linken Rand.
   ------------------------------------------------------------------ */

.site-footer .site-footer__socket {
	justify-content: center;
}

.site-footer .site-footer__copy {
	text-align: center;
}

/* ==================================================================
   Vier weitere belegte Darstellungsmängel, behoben am 06.08.2026

   Wieder gilt: gemessen, nicht geschätzt. Überläufe über scrollWidth
   gegen clientWidth in einem Rahmen fester Breite, Kontraste nach
   WCAG 2.1 aus der relativen Luminanz der gerenderten Farben.
   ================================================================== */

/* ------------------------------------------------------------------
   5 · Der Fußbereich druckte weiß auf weiß

   Keines der acht eingebundenen Stylesheets enthielt eine einzige
   Regel für das Medium „print" – nachgezählt über document.styleSheets:
   0 Treffer für @media print, @page und print-color-adjust.

   Die Folge auf Impressum und AGB, den Seiten, die am ehesten
   ausgedruckt werden: 28 Textknoten standen in reinem Weiß, Kontrast
   1,00:1 gegen Papier. 6 davon in der Kopfnavigation, 22 im Fußbereich –
   darunter sämtliche Rechtslinks, die Anschrift, Rufnummer und
   E-Mail-Adresse. Browser lassen Flächenfarben beim Drucken weg, die
   weiße Schrift darauf aber nicht; genau daraus entsteht das Weiß auf
   Weiß.

   Kopfstreifen und Fuß-Logo werden ausgeblendet statt umgefärbt. Grund:
   druckio-logo-randlos.png ist ein RGB-Bild ohne Alphakanal – von seinen
   25 460 Pixeln tragen 20 719 (81,4 %) den Ton #020D1E. Als Bild bliebe
   es beim Drucken erhalten und legte einen fast vollflächig dunklen
   Block aufs Blatt. Die Kennung der Seite übernimmt der Textblock im
   Fuß („Druckio", Anschrift, Rufnummer, E-Mail), der ausdrücklich
   erhalten bleibt.
   ------------------------------------------------------------------ */

@media print {

	@page {
		margin: 18mm 16mm;
	}

	/* Der Browser soll die hier gesetzten Werte übernehmen und nicht
	   selbst entscheiden, welche davon er weglässt. Damit sieht der
	   Ausdruck gleich aus, ob „Hintergrundgrafiken" im Druckdialog
	   angehakt sind oder nicht. */
	html {
		-webkit-print-color-adjust: exact;
		print-color-adjust: exact;
	}

	/* Flächen weg, Schrift dunkel – ausnahmslos. Das erfasst auch die
	   dunklen Elementor-Abschnitte mit weißer Schrift, die sonst
	   ebenfalls unsichtbar aufs Papier gingen. #111111 statt reinem
	   Schwarz: 18,9:1 auf Weiß, spart Toner und wirkt gedruckt ruhiger. */
	*,
	*::before,
	*::after {
		background: transparent !important;
		color: #111111 !important;
		box-shadow: none !important;
		text-shadow: none !important;
		filter: none !important;
		/* Eine laufende Überblendung steht in der Kaskade noch über
		   !important. Wird gedruckt, während eine solche läuft – etwa weil
		   der Mauszeiger beim Auslösen des Druckbefehls auf einem Link
		   stand –, gewönne sie gegen jede Regel hier. Deshalb aus. */
		transition: none !important;
		animation: none !important;
	}

	html,
	body {
		width: auto !important;
		margin: 0 !important;
		padding: 0 !important;
		background: #ffffff !important;
		font-size: 11pt !important;
		line-height: 1.5 !important;
	}

	/* Die Zeile darueber trifft body. .entry-content ist ein Kind davon und
	   traegt aus der Bildschirmfassung eine eigene Angabe von
	   1.0625rem/1.75 ohne !important - die bleibt sonst stehen. Weil html
	   im Druck auf 11pt steht, sind 1.0625rem dann 11,7pt, und mit
	   Zeilenabstand 1,75 statt 1,5 braucht der Text rund ein Sechstel mehr
	   Blatthoehe. Betraf bisher AGB und Widerruf; seit die Angabe auch fuer
	   die Elementor-Rechtsseiten gilt, waeren es alle fuenf. */
	body:not(.elementor-page) .entry-content,
	.is-legal-page .entry-content {
		font-size: 11pt !important;
		line-height: 1.5 !important;
	}

	/* Satzbreite: Auf Papier begrenzt bereits der Seitenrand aus @page
	   die Zeile. Die 44rem der Bildschirmfassung würden zusätzlich
	   einwirken und ein Drittel des Blattes leer lassen. */
	body:not(.elementor-page) .site-main .entry-header,
	body:not(.elementor-page) .site-main .entry-content,
	.is-legal-page .entry-content .e-con,
	.entry-content .e-con,
	.e-con-inner,
	.site-footer .e-con-inner {
		max-width: none !important;
		width: auto !important;
		margin-inline: 0 !important;
		padding-inline: 0 !important;
	}

	body:not(.elementor-page) .site-main .entry-content {
		padding-bottom: 0 !important;
	}

	/* Was auf Papier nicht hilft: Kopfnavigation samt Klappmenü, der
	   Cookie-Hinweis (Real Cookie Banner, Klassen und Kennungen mit
	   „rcb"), die Deko-Grafik im Fuß, die Zierlinien, die Symbole der
	   sozialen Netze – deren Ziele sind ohnehin nur „#" – sowie
	   eingebettete Rahmen und Videos. */
	.site-header,
	.mobile-menu,
	.mobile-menu__backdrop,
	.menu-toggle,
	.site-footer .site-branding,
	.site-footer__main::before,
	.site-footer__social,
	.site-footer__tagline-line,
	.elementor-background-overlay,
	#wpadminbar,
	[id^="rcb-"],
	[class*="rcb-"],
	iframe,
	video {
		display: none !important;
	}

	/* Der Fußbereich bleibt – er trägt Anschrift und Rechtslinks. Statt
	   der Fläche trennt ihn nun ein Strich vom Text darüber. */
	.site-footer {
		margin-top: 8mm !important;
		padding: 5mm 0 0 !important;
		border-top: 1pt solid #767676 !important;
		font-size: 9pt !important;
		break-inside: avoid;
		page-break-inside: avoid;
	}

	/* Vier Spalten passen auf ein Blatt nicht nebeneinander, eine
	   einzelne verbrauchte eine halbe Seite. Zwei sind der Mittelweg. */
	.site-footer .site-footer__grid {
		display: grid !important;
		grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
		gap: 4mm 8mm !important;
	}

	.site-footer .footer-col__title {
		margin: 0 0 1.5mm !important;
		font-size: 10pt !important;
		font-weight: 700 !important;
	}

	.site-footer .site-footer__socket {
		margin-top: 4mm !important;
		padding-top: 2mm !important;
		border-top: 0.5pt solid #999999 !important;
	}

	/* Überschriften dürfen nicht als letzte Zeile einer Seite stehen. */
	h1, h2, h3, h4, h5, h6 {
		break-after: avoid;
		page-break-after: avoid;
		break-inside: avoid;
		page-break-inside: avoid;
	}

	/* Einzelne Zeilen sollen nicht allein auf einer Seite zurückbleiben.
	   Absätze selbst bleiben umbrechbar: Ein „break-inside: avoid" auf
	   <p> schöbe die langen Absätze der AGB komplett auf das nächste
	   Blatt und ließe das vorige halb leer. */
	p, li {
		orphans: 3;
		widows: 3;
	}

	li, tr, figure, blockquote {
		break-inside: avoid;
		page-break-inside: avoid;
	}

	.entry-title,
	.site-main h1 {
		font-size: 19pt !important;
		line-height: 1.2 !important;
	}

	body:not(.elementor-page) .entry-content h2,
	.is-legal-page .entry-content h2 {
		margin-block: 6mm 2mm !important;
		font-size: 14pt !important;
	}

	body:not(.elementor-page) .entry-content h3,
	.is-legal-page .entry-content h3 {
		margin-block: 4mm 1.5mm !important;
		font-size: 12pt !important;
	}

	/* Die Bildschirmregel schaltet Tabellen unter 560 px auf
	   seitliches Rollen um. Auf Papier kann man nicht rollen. */
	.entry-content table {
		display: table !important;
		overflow: visible !important;
		font-size: 10pt !important;
	}

	.entry-content th,
	.entry-content td {
		border-bottom: 0.5pt solid #999999 !important;
	}

	.entry-content blockquote {
		padding: 3mm 4mm !important;
		border: 0.5pt solid #999999 !important;
		border-left: 2pt solid #111111 !important;
	}

	/* Links bleiben als Links erkennbar, im Fließtext zusätzlich mit
	   ihrer Zieladresse – auf Papier führt kein Klick weiter. */
	.entry-content a {
		text-decoration: underline !important;
	}

	.entry-content a[href^="http"]::after {
		content: " (" attr(href) ")" !important;
		font-size: 0.85em !important;
		font-weight: 400 !important;
		word-break: break-all !important;
	}

	/* Nicht in Navigation und Fußbereich: Dort stünde hinter jedem der
	   zwölf Links eine vollständige Adresse und machte die Spalten
	   unlesbar. */
	.site-header a::after,
	.site-footer a::after,
	.mobile-menu a::after {
		content: none !important;
	}
}

/* ------------------------------------------------------------------
   6 · Lange Wörter schoben vier Seiten bei 320 px zur Seite

   Gemessen bei 320 px Fensterbreite: Startseite +39 px, AGB +21 px,
   Sublimationsdruck +7 px, Widerrufsbelehrung +64 px. Bei 375 px blieb
   nur die Widerrufsbelehrung mit +9 px übrig.

   Die Ursache ist überall dieselbe. Beispiel Startseite: Die
   Überschrift „Maßgeschneiderte Lösungen für Unternehmen und Marken."
   steht in Inter 600 auf 36 px. Allein das Wort „Maßgeschneiderte" misst
   dort 329 px – die Spalte ist 245 px breit. Ohne Umbruchmöglichkeit
   ragt es 84 px über sein eigenes Kästchen und 39 px aus dem Fenster.
   Gemessen wurden ausdrücklich die Wortbreiten, nicht die Elemente:
   Lösungen 172, Unternehmen 238, Marken. 143 px – nur das erste Wort
   ist zu lang.

   Bisher stand dort hyphens: manual und overflow-wrap: normal. Da
   <html lang="de"> gesetzt ist – auf allen geprüften Seiten nachgesehen –
   greift hyphens: auto und trennt nach deutschen Regeln.
   overflow-wrap: break-word bleibt als Auffangnetz für Zeichenfolgen,
   für die es keine Trennstelle gibt.
   ------------------------------------------------------------------ */

.entry-content,
.entry-title,
.site-main h1,
.site-main h2,
.site-main h3,
.site-main h4,
.elementor h1,
.elementor h2,
.elementor h3,
.elementor h4,
.elementor .elementor-heading-title,
.leistung__text h2 {
	overflow-wrap: break-word;
	hyphens: auto;
}

/* Die Unterstrichzeilen des Muster-Widerrufsformulars gehen einen
   eigenen Weg. Sie brauchen ihn: 47 Unterstriche am Stück ergeben
   364 px in einer 280 px breiten Spalte, und für eine Zeichenfolge ohne
   Buchstaben findet die Silbentrennung keine Trennstelle.

   Im Markup tragen diese Absätze weder Klasse noch Attribut – nachgesehen
   in der ausgelieferten Seite, es sind schlichte <p> zwischen anderen
   <p>. Einzeln ansprechbar sind sie deshalb nicht, ohne den Seiteninhalt
   anzufassen. Die Regel greift stattdessen auf den Rechtsseiten und
   nutzt „anywhere" statt „break-word": Nur „anywhere" senkt auch die
   Mindestbreite des Absatzes, sodass er sich der Spalte fügt statt sie
   aufzuweiten. Die Zeile bricht dann ohne Trennstrich um und bleibt als
   Linie zum Ausfüllen erkennbar. */
.is-legal-page .entry-content p,
body:not(.elementor-page) .site-main .entry-content p {
	overflow-wrap: anywhere;
}

/* ------------------------------------------------------------------
   7 · Der Datenschutz-Link im Formularhinweis war nicht zu erkennen

   Gemessen auf /kontakt/: .formular-datenschutz a erbte mit
   color: inherit die Textfarbe #5E6A86 des Absatzes und trug
   text-decoration: none. Kontrast des Links gegen den Text ringsum:
   1,00:1 – der Link war von gewöhnlichem Text nicht zu unterscheiden.

   Farbe allein genügt hier ohnehin nicht: Zwischen #265AD9 und dem
   Absatzton #5E6A86 liegen nur 1,09:1, die Schwelle für allein durch
   Farbe unterschiedene Links wäre 3:1. Deshalb die Unterstreichung –
   sie trägt die Unterscheidung, die Farbe kommt hinzu.

   #265AD9 ergibt 5,92:1 auf Weiß und ist dieselbe Farbe, die oben schon
   die Rubrikzeilen auf hellem Grund tragen. Für Mauszeiger und
   Tastaturmarke #1E49B2 (Akzent 60 % + #06173F 40 %, 7,92:1).
   ------------------------------------------------------------------ */

.formular-datenschutz a {
	color: #265AD9;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.2em;
}

.formular-datenschutz a:hover,
.formular-datenschutz a:focus-visible {
	color: #1E49B2;
	text-decoration-thickness: 2px;
}

/* ------------------------------------------------------------------
   8 · Die Kopfnavigation schrumpfte nicht und sprengte die Seite

   Live geprüft bei 1280 px: Wird die letzte Menübeschriftung testweise
   auf „Individuelle Großformat-Werbetechnik für Firmenkunden" verlängert,
   wächst die Liste von 732 auf 1079 px, der Kopfstreifen von 1265 auf
   1433 px scrollWidth – 168 px Überlauf der ganzen Seite, nicht nur der
   Kopfzeile.

   Der Grund steht in header.css: .site-header__end trägt
   flex-shrink: 0 und .primary-nav__list bricht nicht um. Damit kann die
   Zeile nur wachsen. Die sechs heutigen Punkte passen – jeder siebte
   oder jede längere Beschriftung sprengt die Seite.

   Der Abstand zwischen den Punkten bleibt bewusst unangetastet:
   clamp(1.5rem, 3vw, 2.75rem) ergibt bei 1280 px 38,4 px, und die
   gewohnte Ansicht soll sich nicht ändern. Stattdessen darf die Liste
   umbrechen. Solange alles in eine Zeile passt, ist davon nichts zu
   sehen; erst wenn es eng wird, rutscht der letzte Punkt eine Zeile
   tiefer, statt die Seite zu verbreitern.

   min-width: 0 ist an jeder Stufe nötig: Ein Flex-Element behält sonst
   die Mindestbreite seines Inhalts und schrumpft trotz flex-shrink nicht.
   ------------------------------------------------------------------ */

.site-header .site-header__end {
	flex-shrink: 1;
	min-width: 0;
}

.site-header .primary-navigation {
	min-width: 0;
}

.site-header .primary-navigation .primary-nav__list {
	flex-wrap: wrap;
	justify-content: flex-end;
	row-gap: 0.25rem;
	min-width: 0;
}

.site-header .primary-navigation .primary-nav__list > li {
	min-width: 0;
}

/* Auch eine einzelne überlange Beschriftung darf die Zeile nicht mehr
   aufweiten – sie bricht dann innerhalb ihres eigenen Punktes um. */
.site-header .primary-navigation .primary-nav__list > li > a {
	overflow-wrap: anywhere;
}

/* ------------------------------------------------------------------
   Vier Vorteilskacheln der Startseite: zweispaltig statt gequetscht

   Die vier Kacheln „Alles aus einer Hand", „Modernste Technik",
   „Schnell & zuverlässig" und „Persönlicher Partner" (Klasse
   .card-white-16px) stehen in einer Flexzeile, die Elementor erst bei
   767 px umbrechen lässt. Ein Pixel darüber stehen sie wieder zu viert
   nebeneinander: bei 768 px mit 154 px Breite, von denen nach Polster,
   Symbol und Abstand 54 px für den Text übrig bleiben. Die Überschrift
   „Modernste Technik" lief dort über fünf Zeilen, der Absatz darunter
   über elf. Betroffen ist jedes Tablet im Hochformat.

   Bedingung für den Umschaltpunkt: alle vier Überschriften in höchstens
   zwei Zeilen, alle vier Absätze in höchstens vier. Erfüllt ist das ab
   240 px Kartenbreite, also ab 4 × 240 + 3 × 24 px Abstand = 1032 px
   Containerbreite.

   KORREKTUR 06.08.2026 — hier stand vorher, bei 1060 px blieben 4,4 px
   frei. Das war falsch gerechnet: 1060 wurde als Containerbreite
   ermittelt, aber als Fensterbreite in den Media-Query geschrieben.
   Ein Media-Query misst die Fensterbreite einschließlich der 15 px
   breiten Scrollleiste; der Container ist dort also nur 1045 px breit.
   Nachgemessen bleiben bei 1060 px Fensterbreite **0,4 px** frei, nicht
   4,4. Für den breitesten Zustand stimmte der alte Kommentar: 5,9 px
   gemessen gegen 6,1 px genannt.

   Der Container ist auf 1140 px begrenzt. Diese volle Breite erreicht er
   erst ab 1155 px Fensterbreite (1140 + 15 px Scrollleiste). Gemessener
   freier Platz auf der engsten Zeile, Fensterbreite gegen Rest:

     1060 px → 0,4   1090 px → 1,4   1120 px → 0,0
     1065 px → 2,4   1100 px → 0,8   1130 px → 1,1
     1075 px → 1,4   1110 px → 3,8   1140 px → 1,9
     1080 px → 2,4                   1155 px → 5,9  ← Container voll

   Zwischen 1060 und 1154 px erreicht die Reserve an keiner Stelle die
   5,9 px des breitesten Zustands. Erst bei 1155 px ist sie erreicht —
   und zwar naturgemäß, weil der Container dort seine Endbreite hat und
   sich darüber nichts mehr ändert. Der Umschaltpunkt wandert deshalb
   von 1060 auf 1155 px: Die vierspaltige Reihe steht damit nur noch in
   genau dem Zustand, für den sie entworfen wurde, und die schmale Zone
   mit unter einem Pixel Reserve verschwindet ganz.

   Zur Scrollleiste: Gemessen wurde in Chromium auf macOS mit klassischer,
   15 px breiter Leiste — dort ist die Rechnung genau. Wo das System
   überlagernde Leisten verwendet (macOS in der Voreinstellung, iPadOS,
   Android), ist die Leiste 0 px breit und der Container schon bei 1140 px
   Fensterbreite voll. Dort stehen die Karten zwischen 1140 und 1154 px
   zweispaltig, obwohl sie vierspaltig passen würden. Das ist die
   vorsichtige Richtung des Fehlers und bewusst in Kauf genommen: Ein
   niedrigerer Wert wäre auf Systemen mit klassischer Leiste zu knapp.

   Zwischen 768 und 1154 px stehen die Karten dadurch zu zweit
   nebeneinander, ab 1155 px unverändert zu viert, bis 767 px unverändert
   einspaltig. Bei 1280 und 1440 px ändert sich nichts. Die Regel hängt
   an der Kachelklasse statt an der Elementor-Kennung: :has() greift
   genau den Flexcontainer, in dem diese Karten liegen, und übersteht
   damit ein erneutes Speichern der Seite.

   Zur Klasse .g-901e541: Auf den Leistungsseiten stehen diese Karten ab
   1024 px abwärts einspaltig und sind nicht betroffen — nachgemessen auf
   /leistungen/3d-druck/ und /leistungen/uv-druck/: 689 px Kartenbreite
   bei 768 px, eine Karte je Zeile. Auf der STARTSEITE gilt das nicht:
   Dort trägt derselbe Klassenname im Container 995cb4e fünf
   Referenzkarten, die bis 767 px dreispaltig bleiben. Siehe den
   Abschnitt „Zwei weitere Reihen" am Dateiende.
   ------------------------------------------------------------------ */

@media (min-width: 768px) and (max-width: 1154.98px) {
	.elementor .e-con.e-flex > .e-con-inner:has(> .card-white-16px) {
		flex-wrap: wrap;
		/* Die Reihe bringt nur einen waagerechten Abstand mit
		   (--gap: 0px 24px). Ohne Zeilenabstand klebten die beiden
		   Kartenreihen nach dem Umbruch aufeinander. */
		row-gap: 24px;
	}

	/* Ohne Breitenangabe blieben die Karten inhaltsbreit, denn Elementor
	   gibt ihnen flex: 0 1 auto. calc(50% - 12px) ist die halbe Zeile
	   abzüglich der Hälfte des 24-px-Abstands. */
	.elementor .e-con.e-flex > .e-con-inner > .card-white-16px {
		flex: 1 1 calc(50% - 12px);
		max-width: calc(50% - 12px);
	}
}

/* ------------------------------------------------------------------
   „In vier Schritten zum fertigen Produkt": zweispaltig statt gequetscht

   Derselbe Fehler wie bei den Vorteilskacheln darüber, eine Reihe
   tiefer — und etwas schlimmer. Die vier Kacheln .how-it-works-step
   („Anfrage senden", „Beratung & Planung", „Produktion", „Lieferung")
   stehen bis 767 px einspaltig und ab 768 px sofort wieder zu viert
   nebeneinander. Gemessen bei 768 px: 152,25 px Kachelbreite, davon nach
   10 px Polster je Seite 132 px für den Text. Die Überschrift
   „Beratung & Planung" lief dort über zwei Zeilen, die Absätze über
   fünf. 152 px ist enger als die 154 px, wegen derer die Reihe darüber
   korrigiert wurde.

   Der Bau unterscheidet sich: Diese Reihe ist ein Raster, keine
   Flexzeile. Elementor setzt --e-con-grid-template-columns auf dem
   äußeren .e-con, das .e-con-inner erbt die Angabe und löst sie in
   grid-template-columns auf. Ein flex-wrap wie bei den Vorteilskacheln
   greift hier deshalb nicht; geändert wird die Variable selbst, und zwar
   auf dem .e-con-inner — dort gewinnt der eigene Wert gegen den
   ererbten, unabhängig von der Spezifität der Elementor-Regel.
   minmax(0, 1fr) statt 1fr, damit ein langes Wort die Spalte nicht
   aufweiten kann. Ein row-gap ist nicht nötig: Das Raster bringt
   gap: 20px für beide Richtungen mit.

   Umschaltpunkt: Die Zeilenbedingung allein (Überschriften höchstens
   zwei Zeilen, Absätze höchstens vier) ist schon ab 780 px erfüllt —
   dort bleiben auf der engsten Zeile aber nur 0,05 px frei. Gemessener
   freier Platz über den ganzen Bereich, Fensterbreite gegen Rest:

     768 → 1,4 (fünf Zeilen, Bedingung verletzt)
     780 → 0,05   820 → 0,6   880 →  6,9   960 → 1,4
     790 → 0,6    840 → 1,9   900 → 11,9   1000 → 11,4
     800 → 1,9    860 → 1,9   940 → 27,8   1060 →  5,8

   Die Kurve ist ein Sägezahn: Sobald ein Absatz eine Zeile verliert,
   rückt die nächste enge Zeile nach und die Reserve fällt zurück. Einen
   Wert zu wählen, der knapp über der Bedingung liegt, hieße also, auf
   einen zufälligen Zacken zu setzen.

   Gewählt sind deshalb dieselben 1155 px wie bei den Vorteilskacheln.
   Nachgemessen bei 1155 px: 265 px Kachelbreite, alle vier
   Überschriften einzeilig, der längste Absatz dreizeilig. Damit steht
   kein einziges Textstück an seiner Zeilengrenze — die Bedingung kann
   durch eine geringfügig andere Schriftauslieferung gar nicht mehr
   kippen. Bei 1060 px wäre ein Absatz vierzeilig mit 5,8 px Reserve.

   Der zweite Grund ist die Seite selbst: Beide Reihen stehen auf der
   Startseite untereinander. Ein unterschiedlicher Umschaltpunkt hätte
   zwischen den beiden Werten eine Ansicht erzeugt, in der die obere
   Reihe zweispaltig und die untere vierspaltig steht.
   ------------------------------------------------------------------ */

@media (min-width: 768px) and (max-width: 1154.98px) {
	.elementor .e-con.e-grid > .e-con-inner:has(> .how-it-works-step) {
		--e-con-grid-template-columns: repeat(2, minmax(0, 1fr));
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* ------------------------------------------------------------------
   Zwei weitere Reihen mit demselben Muster — gemessen, nicht behoben

   Beim Nachzählen aller mehrspaltigen Kachelreihen auf allen 13 Seiten
   bei 768, 900 und 1024 px sind zwei weitere Reihen aufgefallen. Beide
   stehen auf der Startseite, beide brechen erst bei 767 px um. Sie sind
   hier bewusst nur festgehalten und nicht geändert, weil bei ihnen
   nicht der Umschaltpunkt allein die Frage ist.

   Alle Zahlen sind ein Stand vom 06.08.2026. Die Kartentexte wurden an
   diesem Tag mehrfach überarbeitet; wer die Werte nachprüft und
   abweichende findet, sollte zuerst den Text vergleichen, nicht das CSS.

   a) .g-901e541 im Container 995cb4e — fünf Referenzkarten, dreispaltig.
      Gemessene Kachelbreite und Zeilen (Überschrift/Absatz):
        768 px → 203 px, 4/17   900 px → 247 px, 3/13
       1024 px → 288 px, 3/11   1280 px → 367 px, 2/8
      Die Reihe verletzt die Zeilenbedingung auch im Endzustand bei
      1280 px (acht statt vier Zeilen). Sie trägt schlicht längere
      Texte. Eine Umschaltgrenze allein löst das nicht; hier wäre zuerst
      zu klären, ob vier Zeilen für diese Karten überhaupt der richtige
      Maßstab sind. Siebzehn Zeilen bei 768 px gegen acht bei 1280 px
      zeigen aber dieselbe Verdopplung wie bei den beiden behobenen
      Reihen.

   b) .service-card im Container f29196d — drei Karten in einer
      Flexzeile ohne Umbruch.
        768 px → 207 px, 3/6    900 px → 251 px, 2/5
       1024 px → 292 px, 2/4    1280 px → 364 px, 1/3
      Hier reicht ein Umschaltpunkt aus: Ab 1024 px ist die Bedingung
      erfüllt, darunter nicht.

   Nicht betroffen und nachgemessen: .target-group-card auf der
   Startseite (768 px → 210 px, 2/3 — Bedingung erfüllt), .service-card
   im Container 71cf12f (zwei Karten, 322 px und 2/4 bei 768 px, damit
   gerade noch innerhalb der Bedingung) sowie sämtliche
   Reihen der fünf Leistungsseiten, die ab 1024 px abwärts ein- oder
   zweispaltig stehen. Die Rechtsseiten tragen keine Kachelreihen.
   ------------------------------------------------------------------ */


/* ==================================================================
   Vier Darstellungsfehler der verlängerten Texte — 06.08.2026
   ================================================================== */

/* ------------------------------------------------------------------
   1 · Hero-Text auf hellem Bildbereich lesbar machen

   Auf den fünf Verfahrensseiten läuft die verlängerte .hero-subline
   (rgb(238,241,248), 20px) quer über die helle Bildmitte. Ein Overlay
   gab es nicht: ::before und ::after standen auf content: none, kein
   Verlauf, kein Blend-Mode.

   Gemessen wurde der Anteil der Textfläche unter 4,5:1 — je Textzeile
   über Range.getClientRects(), Hintergrundfarbe aus dem Hero-Bild über
   Canvas mit derselben cover-Rechnung wie im Browser. Ausgangslage:

     3D-Druck   375px 13,7 %  768px 33,4 %  1024px 34,5 %  1440px 0 %
     UV-Druck   375px 16,3 %  768px 20,8 %  1024px 22,0 %  1440px 7,3 %

   Warum genau rgb(2,14,30): Alle vier Hero-Bilder tragen links eine
   eingebrannte Abdunklung. Sie ist kein Verlauf, sondern eine
   Volltonfläche — über die linken 30 % der Bildbreite und die ganze
   Höhe wurde in allen vier Dateien exakt ein einziger Farbwert
   gefunden, rgb(2,14,30) (435 Stichproben je Bild, einmal mit Pillow,
   einmal über Canvas im Browser gegengeprüft). Deckt man diese Fläche
   mit demselben Farbwert ab, ändert sich dort nichts — egal bei
   welcher Deckkraft, denn rgb(2,14,30) über rgb(2,14,30) bleibt
   rgb(2,14,30). Genau daran ist ein früherer Versuch gescheitert: Ein
   abweichender Ton reißt an der Grenze zur eingebrannten Fläche eine
   sichtbare Kante. Der Wert liegt um 1 im Grünkanal neben dem
   Kopfstreifen-Ton #020D1E — nicht wahrnehmbar, aber hier zählt der
   Bildwert, nicht der Palettenwert.

   Warum die Deckkraft nirgends unter 0,65 fällt: Unter dem Text liegt
   stellenweise reines Weiß (schlechtester Einzelwert der Ausgangslage
   1,00:1 — Weiß auf Weiß). Reinweiß ist der ungünstigste überhaupt
   mögliche Hintergrund; wer ihn schafft, schafft jeden. Gerechnet mit
   der Textfarbe rgb(238,241,248), die höchstens eine
   Hintergrundluminanz von 0,1564 verträgt:

     alpha 0,55 → 3,81:1   alpha 0,60 → 4,53:1   alpha 0,65 → 5,43:1
     alpha 0,58 → 4,22:1   alpha 0,62 → 4,87:1

   Ab 0,60 ist die Grenze gehalten, 0,65 gibt Rücklage. Damit gilt die
   Korrektur für alle fünf Seiten, ohne dass jedes Bild einzeln
   nachgerechnet werden muss — auch wenn die Texte weiter wachsen.

   Ein erster Versuch mit 0,52 am rechten Rand reichte auf 3D-Druck,
   fiel auf UV-Druck aber durch (768px 3,2 %, 1024px 3,8 % blieben
   übrig): Das UV-Bild trägt unter dem Text ausgedehnte weiße Flächen,
   die 0,60 verlangen. Deshalb der Rechenweg oben statt einer je Bild
   angepassten Kurve.

   Zwei Bereiche, weil der Text unterschiedlich weit reicht:

   Bis 1024px füllt der Text fast die ganze Breite (Textkante bei
   96,8 % der Containerbreite) — der Schleier muss bis zum rechten Rand
   tragen und endet deshalb bei 0,65 statt bei 0.

   Ab 1025px greift Elementors Tablet-Grenze, der .hero-content-wrapper
   fällt von voller Breite auf 606px, und der Text endet bei 57–58 %
   der Containerbreite (gemessen auf allen fünf Seiten bei 1440px:
   56,8 / 57,0 / 57,7 / 57,8 / 59,6 %). Dort deckt der Verlauf nur die
   linken zwei Drittel und läuft bis 82 % auf null aus — das rechte
   Fünftel des Bildes bleibt unangetastet.

   Dass auch oberhalb von 1024px etwas nötig ist, zeigt die Messung:
   nicht nur UV-Druck (7,3 %), auch Lasergravur und Sublimation
   verlangen dort bis zu 0,40 Deckkraft in den Spalten 50–60 %.
   Gemessener Bedarf bei 1440px, Spalte 50–60 %:

     Lasergravur 0,40 · UV-Druck 0,36 · Sublimation 0,35 · DTF 0,05

   z-index: -1 statt 0: Die Hero-Sektion trägt position: relative und
   z-index: 1, bildet also einen Stapelkontext. Ihr Inhalt
   (.e-con-inner) steht im Fluss und ist nicht positioniert. Ein
   positioniertes ::before mit z-index: 0 läge damit ÜBER dem Text —
   positionierte Nachfahren werden nach den nicht positionierten
   gezeichnet. Erst z-index: -1 legt die Fläche zwischen
   Hintergrundbild und Text.
   ------------------------------------------------------------------ */

.elementor .e-con.e-parent:has(.hero-content-wrapper) {
	position: relative;
}

.elementor .e-con.e-parent:has(.hero-content-wrapper)::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	pointer-events: none;
}

/* Bis 1024px: Text reicht fast an den rechten Rand, der Schleier auch. */
@media (max-width: 1024px) {
	.elementor .e-con.e-parent:has(.hero-content-wrapper)::before {
		background-image: linear-gradient(
			to right,
			rgba(2, 14, 30, 0.82) 0%,
			rgba(2, 14, 30, 0.68) 45%,
			rgba(2, 14, 30, 0.65) 100%
		);
	}
}

/* Ab 1025px: Text endet bei 57-58 %, rechts bleibt das Bild frei. */
@media (min-width: 1025px) {
	.elementor .e-con.e-parent:has(.hero-content-wrapper)::before {
		background-image: linear-gradient(
			to right,
			rgba(2, 14, 30, 0.78) 0%,
			rgba(2, 14, 30, 0.68) 50%,
			rgba(2, 14, 30, 0.65) 62%,
			rgba(2, 14, 30, 0) 82%
		);
	}
}


/* ------------------------------------------------------------------
   2 · „Geeignet für:" auf /leistungen/ dunkler

   .leistung__eignung stand auf --druckio-color-muted (#8D97AD): 2,93:1
   auf Weiß bei 15,2px, an fünf Stellen. Fließtext braucht 4,5:1.

   #5E6A86 ergibt 5,41:1 und ist derselbe Wert, der weiter oben schon
   bei .formular-datenschutz aus demselben Grund an die Stelle von
   --druckio-color-muted getreten ist — deshalb hier kein neuer Ton.

   Es bleibt ein Etikett und wird nicht zu Fließtext: Der Fließtext
   daneben steht auf rgb(26,31,46) bei 17px, die Zeile bleibt mit
   #5E6A86 bei 15,2px deutlich heller und kleiner.

   Das <strong> darin braucht keine eigene Regel — geprüft: es erbt
   die Farbe (Probe: Elternfarbe gesetzt, strong ist mitgegangen).
   ------------------------------------------------------------------ */

.leistung__eignung {
	color: #5E6A86;
}


/* ------------------------------------------------------------------
   3 · CTA-Bild: cover statt contain, links wieder abdunkeln

   Die CTA-Sektion trägt CTA-1024x324.jpg auf rgb(6,23,63) mit
   background-size: contain und background-position: right center. Weil
   der Kasten höher ist als das Bild breit zulässt, blieb oben und
   unten eine Fläche in Sektionsfarbe stehen; das Bild schwebte als
   Streifen mit zwei waagerechten Kanten. Gemessene Balkenhöhe je
   Seite: 375px 289px · 768px 163px · 1024px 123px · 1440px 9px.

   cover schließt die Balken. Beschnitten wird dabei nur Fülle: Die
   linken 480 der 1024 Bildpunkte sind eine Volltonfläche rgb(5,23,63)
   (Streuung 0,00 über die ganze Höhe) — die Datei bringt ihre eigene
   Abdunklung nach links mit, damit sie in die Sektion übergeht.

   Zweite Hälfte der Korrektur: Genau diese Fläche schneidet cover bei
   schmalen Fenstern weg (sichtbar erst ab Bildpunkt 592 bei 768px,
   ab 850 bei 375px). Die Kleinschrift „Jetzt starten" (rgb(119,159,255),
   12px) stand dann auf Bildinhalt statt auf Navy:

     768px: contain 0 % unter 4,5:1 (min 6,82) → cover allein 21,9 % (min 4,02)
     375px: contain 0 % unter 4,5:1 (min 6,81) → cover allein  1,9 % (min 3,23)

   Der Verlauf stellt unterhalb von 1024px wieder her, was das Bild bei
   breiten Fenstern selbst mitbringt. Danach wieder 0 % unter 4,5:1
   (768px min 6,75 · 375px min 5,02). Oberhalb von 1024px bleibt genug
   von der eingebauten Fläche stehen, dort ist der Verlauf unnötig.

   Farbe rgb(6,23,63) ist die Sektionsfarbe; das Bild trägt an seiner
   Volltonfläche rgb(5,23,63) — ein Punkt daneben und nicht sichtbar.
   ------------------------------------------------------------------ */

.elementor .e-con.elementor-element-0da03d7 {
	background-size: cover;
}

@media (max-width: 1024px) {
	.elementor .e-con.elementor-element-0da03d7::before {
		content: "";
		position: absolute;
		inset: 0;
		z-index: -1;
		pointer-events: none;
		background-image: linear-gradient(
			to right,
			rgb(6, 23, 63) 0%,
			rgba(6, 23, 63, 0.95) 30%,
			rgba(6, 23, 63, 0) 72%
		);
	}
}


/* ------------------------------------------------------------------
   4 · Löcher in den Kacheln bei einspaltiger Darstellung

   Elementor lässt --e-con-grid-template-rows auf repeat(3, 1fr)
   stehen, auch wenn die Spalten auf repeat(1, 1fr) gefallen sind. Bei
   einer Spalte teilen sich die ersten drei Kacheln dann die Höhe der
   höchsten, ab Kachel vier greift die Vorgabe nicht mehr — die Reihe
   zerfällt sichtbar in zwei Gruppen.

   Gemessen auf /leistungen/3d-druck/ bei 375px, Container be3aca6 mit
   fünf Kacheln — Zeilenhöhen vorher/nachher:

     vorher   224 224 224 204 204   größtes Loch 75px
     nachher  185 165 224 204 204   größtes Loch 16px (nur noch Abstand)

   Umschaltpunkt 767px: Dort stehen alle Kachelreihen der fünf
   Verfahrensseiten einspaltig (nachgemessen bei 767px: alle drei
   Rasterreihen auf repeat(1, 1fr)); bei 768px ist die erste noch
   zweispaltig, und dort ist die gemeinsame Zeilenhöhe erwünscht —
   nebeneinanderstehende Kacheln sollen gleich hoch sein.

   Gesetzt werden Variable und Eigenschaft zusammen, wie schon bei
   --e-con-grid-template-columns weiter oben: Elementor löst die
   Variable auf dem äußeren .e-con auf, der eigene Wert auf dem
   .e-con-inner gewinnt gegen den ererbten.

   auto wirkt auch auf die Kacheln ab der vierten: Die vierte und
   fünfte Zeile entstehen implizit über grid-auto-rows (auto) und
   waren schon vorher eigenständig hoch — deshalb sah man den Bruch
   überhaupt.
   ------------------------------------------------------------------ */

@media (max-width: 767px) {
	.elementor .e-con.e-grid > .e-con-inner {
		--e-con-grid-template-rows: auto;
		grid-template-rows: auto;
	}
}


/* ==================================================================
   Hero der Startseite in der Handyansicht — 06.08.2026
   ================================================================== */

/* ------------------------------------------------------------------
   Der Startseiten-Hero blieb auf jeder Breite zweispaltig

   Gemessen auf / bei drei Handybreiten, jeweils vorher:

     Breite   Textspalte   Schrift   Höhe der h1   Trennungen   Rand
      320px      192px       54px       702px          6         0px
      375px      225px       54px       594px          4         0px
      414px      248px       54px       540px          4         0px

   Die Überschrift füllte damit bei 375px fast den ganzen Bildschirm
   („Indivi-duelle Druck- und Produk-tionslö-sungen – alles aus ei-ner
   Hand"), Unterzeile und Knopf standen unterhalb von 812px und waren
   ohne Scrollen nicht zu sehen.

   Ursache: Der Hero-Container trägt --flex-direction: row ohne jede
   Ausnahme für schmale Fenster. Die Textspalte behält ihre 60 % aus
   local-2-frontend-desktop.css, die zweite Spalte (leer, sie gibt auf
   dem Desktop nur den Blick auf das Hintergrundbild frei) nimmt die
   restlichen 40 %. In die verbleibenden 225px presst sich eine 54px
   große Schrift — dann bleibt dem Browser nur die Silbentrennung,
   denn weiter oben in dieser Datei steht hyphens: auto für alle
   Überschriften.

   Einen waagerechten Überlauf gab es dabei nie: scrollWidth und
   clientWidth lagen auf allen Breiten gleichauf. Genau deshalb ist
   der Fehler jeder Prüfung entgangen, die auf Überlauf gemessen hat.

   Die fünf Verfahrensseiten haben das Problem nicht: Dort steht in
   post-288.css ein @media (max-width: 1024px) mit
   --flex-direction: column und --padding-left/right: 32px, dazu in
   local-288-frontend-tablet.css die Textspalte auf width: 100 %. Der
   Startseite (post-2.css) fehlen beide Blöcke ersatzlos.

   WARUM ALLES AUF .elementor-2 EINGEGRENZT IST — das ist der Kern:
   Die Elementor-Kennungen sind auf allen sechs Seiten dieselben.
   2e2357a, 008b5b5, 1b441e4 und 7ff3475 stehen wortgleich auch auf
   /leistungen/dtf-druck/ (nachgesehen im Seitenquelltext). Auch die
   Sammelklassen der Atomic-Elemente sind gleich: .e-008b5b5-9f8795b
   trägt sowohl die Startseite als auch jede Verfahrensseite. Eine
   Regel ohne .elementor-2 träfe deshalb sechs Heros statt einem — und
   die fünf Verfahrensseiten sind mobil in Ordnung und sollen so
   bleiben. .elementor-2 steht nur auf der Startseite; CSS vergleicht
   ganze Klassennamen, .elementor-288 wird davon nicht getroffen.

   WARUM 767px UND NICHT 1024px WIE AUF DEN VERFAHRENSSEITEN:
   Zwischen 768px und 1024px ist der Startseiten-Hero unauffällig
   (bei 1024px: Textspalte 605px, vier Zeilen). Dort soll sich nichts
   ändern, deshalb die engere Grenze. Chrome wertet Media Queries
   gegen window.innerWidth aus, also einschließlich der Bildlaufleiste
   — bei einem 768px breiten Fenster (Inhaltsbreite 753px) greift
   max-width: 767px nicht. Nachgeprüft mit matchMedia.
   ------------------------------------------------------------------ */

@media (max-width: 767px) {

	/* Der Hero stellt sich untereinander statt nebeneinander.
	   Variable und Eigenschaft werden zusammen gesetzt, wie schon
	   weiter oben bei den Rasterreihen: Elementor löst die Variable
	   auf dem äußeren .e-con auf, der eigene Wert auf dem
	   .e-con-inner gewinnt gegen den ererbten.

	   Seitenrand 20px: Der Hero war der einzige Bereich der
	   Startseite ohne Rand. Die übrigen neun Bereiche stehen bei
	   375px auf 20px (vier Bereiche) oder 30px (vier Bereiche);
	   20px ist der schmalste und damit der Wert, der der
	   Überschrift den meisten Platz lässt. --padding-top/bottom
	   bleiben unangetastet bei 80px. */
	.elementor-2 .e-con.elementor-element-2e2357a {
		--flex-direction: column;
		--padding-left: 20px;
		--padding-right: 20px;
	}

	.elementor-2 .e-con.elementor-element-2e2357a > .e-con-inner {
		flex-direction: column;
	}

	/* Textspalte über die volle Breite statt über 60 %. */
	.elementor-2 .elementor-element-2e2357a .elementor-element-008b5b5 {
		width: 100%;
	}

	/* Die zweite Spalte ist leer: kein Kindelement, kein Text, kein
	   eigener Hintergrund (nachgesehen: childElementCount 0,
	   background-image none). Sie hält auf dem Desktop nur die
	   rechten 40 % für das Hintergrundbild des Containers frei. Steht
	   der Hero untereinander, hat sie keine Aufgabe mehr. */
	.elementor-2 .elementor-element-2e2357a .elementor-element-1b441e4 {
		display: none;
	}

	/* Überschrift mitwachsen lassen.

	   Die Zahl 12 ist gemessen, nicht geschätzt. Abgetastet wurde in
	   1px-Schritten, welche Schriftgrößen ohne Silbentrennung
	   auskommen (Spaltenbreite = Fensterbreite minus 2 × 20px):

	     320px  Spalte 280px  sauber bis 24px   (280/24 = 11,67)
	     375px  Spalte 335px  sauber 27 – 29px  (335/29 = 11,55)
	     414px  Spalte 374px  sauber 30 – 32px  (374/32 = 11,69)

	   Die Grenze ist überall dieselbe: Die erste Zeile
	   „Individuelle Druck- und" misst rund 11,6 em. Passt sie, steht
	   die Überschrift in genau den drei Zeilen, die auch der Desktop
	   ab 1280px zeigt. Passt sie nicht, rutscht „und" in die zweite
	   Zeile, „Produktionslösungen" wird gebrochen, und ab da reißt
	   es die ganze Überschrift auseinander.

	   Teiler 12 statt 11,6 lässt rund 3 % Luft für
	   Schriftschnitt-Unterschiede. Damit gilt schlicht:
	   Schriftgröße = Spaltenbreite ÷ 12, also
	   (100vw − 40px) ÷ 12 = 8.33vw − 3.33px.

	   Ergebnis: 320px → 23,3px · 375px → 27,9px · 414px → 31,2px,
	   überall drei Zeilen und null Trennungen.

	   Die Obergrenze 54px ist der unveränderte Desktop-Wert. Sie ist
	   schon bei 688px Fensterbreite erreicht (8.33 × 6,88 − 3,33 =
	   54) — also deutlich vor der Grenze der Media Query. Zwischen
	   688px und 767px steht die Überschrift damit auf denselben 54px
	   wie ab 768px; an der Umschaltstelle springt die Schriftgröße
	   nicht.

	   Die Untergrenze 20px greift erst unterhalb von 280px
	   Fensterbreite und ist reine Rückversicherung; das schmalste
	   verbreitete Gerät misst 320px.

	   WARUM ZUSÄTZLICH hyphens: manual — das war ein echter Fund,
	   keine Vorsichtsmaßnahme: Mit der Formel allein blieben 39
	   Breiten übrig, die weiter trennten, nämlich 729px bis 767px.
	   Dort steht die Schrift auf der gekappten 54px, die Spalte ist
	   aber schon 689px bis 727px breit. Der Zeilenumbruch arbeitet
	   gierig: Nach „Produktions­lösungen –" bleibt genug Platz für
	   „al-", also zieht der Browser die Silbe hoch, und die Zeile
	   endet auf „all / es aus einer Hand." Breiter ist hier also
	   schlechter — bei 728px passt „alles" nicht mehr halb hinein
	   und die Zeile bleibt heil.

	   Abgetastet wurde jede einzelne Breite von 280px bis 767px
	   (488 Stück), indem Spaltenbreite und Schriftgröße direkt an die
	   h1 gelegt und die Zeilen über Range.getBoundingClientRect
	   ausgelesen wurden. Ergebnis mit hyphens: manual: 0 Trennungen,
	   0 Überläufe, überall genau drei Zeilen.

	   manual statt none: none würde auch die ausgeschriebene weiche
	   Trennstelle in „Produktions­lösungen" (U+00AD, steht so im
	   Text) verbieten. Gebraucht wird sie hier nie — die Formel hält
	   das Wort immer auf einer Zeile (10,45 em Wortbreite gegen
	   12 em Spaltenbreite) —, aber sie bleibt als Rückfalllinie
	   erhalten, falls der Text einmal wächst. Ein Überlauf kann
	   dadurch nicht entstehen: overflow-wrap: break-word aus der
	   allgemeinen Regel weiter oben bleibt in Kraft.

	   -webkit-hyphens für ältere iOS-Fassungen, die die Eigenschaft
	   nur mit Präfix kennen.

	   Zeilenhöhe 1.15 statt der geerbten 1: Bei einer einzeiligen
	   Desktop-Zeile fällt line-height: 1 nicht auf, bei drei Zeilen
	   auf dem Handy stoßen die Unterlängen von „Produktionslösungen"
	   an die Versalien der nächsten Zeile.

	   Der Selektor wiederholt Elementors eigenen Aufbau
	   (.elementor-element.elementor-element-7ff3475 …), weil dessen
	   Regel in post-2.css vier Klassen tief ist. Mit nur drei Klassen
	   gewinnt sie trotz späterer Ladereihenfolge — nachgemessen: Die
	   Schriftgröße blieb im ersten Versuch bei 54px stehen. */
	.elementor-2 .elementor-element.elementor-element-7ff3475 .elementor-heading-title {
		font-size: clamp(20px, 8.33vw - 3.33px, 54px);
		line-height: 1.15;
		-webkit-hyphens: manual;
		hyphens: manual;
	}
}


/* ==================================================================
   Mobile Nacharbeiten — 06.08.2026
   ================================================================== */

/* ------------------------------------------------------------------
   1 · Silbentrennung nur noch dort, wo sie gebraucht wird

   Regel 6 des oberen Abschnitts („Lange Wörter schoben vier Seiten
   bei 320 px zur Seite") hat hyphens: auto auf .entry-content gelegt, um
   bei 320px vier Seiten am Überlaufen zu hindern. Die Trennung erbt
   von dort auf jeden Absatz, jeden Listenpunkt und jede Tabellenzelle
   der Website. Gemessen bei 375px, Zahl der Wörter, die mitten
   entzweigehen:

     Startseite 26 · /leistungen/ 30 · DTF 6 · UV 15 · 3D 11 ·
     Lasergravur 11 · Sublimation 6 · Kontakt 9 · Impressum 18 ·
     AGB 310 · Datenschutz 130 · Widerruf 77 · Cookies 67
     — zusammen 716 auf 13 Seiten.

   Darunter „Ron-ny Broszinski" in den AGB. Ein getrennter Eigenname
   in einer Vertragsbedingung ist schlicht falsch, und im Fließtext
   sind 310 Trennstriche auf einer Seite auch typografisch zu viel.

   WARUM NICHT EINFACH ABSCHALTEN: Genau das war der Zustand vor
   Regel 6. Nachgemessen mit hyphens: manual auf allem, bei 320px:

     /leistungen/sublimationsdruck/   Überlauf 0 → 26px
     /datenschutzerklaerung/          Überlauf 0 →  6px

   Der Grund ist nicht der Zeilenumbruch, sondern die Mindestbreite:
   overflow-wrap: break-word bricht zwar lange Wörter um, senkt aber
   die min-content-Breite des Elements nicht. Die Überschrift „Wofür
   sich Sublimationsdruck eignet" verlangte deshalb 326px in einem
   320px breiten Fenster, die Zelle „Server-Protokolldateien" trieb
   die Datenschutz-Tabelle auf 356px. Die automatische Trennung senkt
   die Mindestbreite, break-word nicht — deshalb hielt Regel 6.

   Die Trennlinie verläuft also zwischen Fließtext und den Stellen,
   deren Breite von einem einzigen langen Wort bestimmt wird:

     Fließtext        → manual (keine automatische Trennung)
     Überschriften    → bleiben auf auto (Regel 6 fasst sie schon,
                        hier steht deshalb nichts; ihre eigenen
                        Selektoren gewinnen gegen den geerbten Wert)
     Tabellenzellen   → ausdrücklich zurück auf auto

   Nachgemessen mit dieser Aufteilung, alle 13 Seiten:

     bei 320px   871 → 105 Brüche, Überlauf überall 0
     bei 375px   716 →  ~90 Brüche, Überlauf überall 0

   Von den verbliebenen Brüchen sind die meisten gar keine Trennungen,
   sondern Umbrüche an echten Bindestrichen im Text („3D-Druck",
   „E-Mail", „Umsatzsteuer-Identifikationsnummer") — die Zählung kann
   beides nicht unterscheiden, weil zwischen den Zeilen in beiden
   Fällen kein Leerzeichen steht.

   overflow-wrap: break-word aus Regel 6 bleibt unangetastet als Netz.
   ------------------------------------------------------------------ */

.entry-content {
	-webkit-hyphens: manual;
	hyphens: manual;
}

/* Tabellenzellen behalten die Trennung: Ihre Spaltenbreite richtet
   sich nach dem längsten Wort, und ohne Trennung schiebt ein Wort wie
   „Server-Protokolldateien" die ganze Tabelle aus dem Fenster
   (nachgemessen: +6px auf /datenschutzerklaerung/ bei 320px). */
.entry-content td,
.entry-content th {
	-webkit-hyphens: auto;
	hyphens: auto;
}

/* Cookie-Namen und andere Codeschnipsel werden nie getrennt. Ein
   eingefügter Trennstrich macht den Namen falsch: Aus
   „real_cookie_banner-*" wurde in der Cookie-Richtlinie
   „real_-coo-kie_ban-ner-*" über fünf Zeilen — so ist der Cookie im
   Browser nicht wiederzufinden. Umbrechen darf der Name trotzdem, nur
   eben an seinen eigenen Bindestrichen; break-word bleibt als Netz
   für den Fall, dass auch das nicht reicht. */
.entry-content code {
	-webkit-hyphens: none;
	hyphens: none;
	word-break: normal;
	overflow-wrap: break-word;
}


/* ------------------------------------------------------------------
   2 · Cookie-Richtlinie: die Tabelle wird auf dem Handy zu Karten

   Die Tabelle hat vier Spalten. Bei 375px Fensterbreite blieben davon
   105 / 68 / 87 / 74px übrig. In eine 68px breite Spalte passt kein
   deutsches Wort mehr am Stück, also wurde jede Zelle zwölf Zeilen
   hoch: 316px für eine Zeile mit vier Wörtern. Die ganze Tabelle maß
   1419px Höhe für vier Datenzeilen (bei 320px sogar 1579px).

   Ab 768px bleibt alles, wie es ist — dort hat die Tabelle Platz.

   Umgebaut wird ohne Eingriff in den Seiteninhalt: table, tbody, tr
   und td werden zu Blöcken, die Kopfzeile wird ausgeblendet, und
   jedes Feld bekommt seine Beschriftung über ::before zurück.

   DAS IST DIE WARTUNGSSTELLE: Die vier Beschriftungen stehen hier im
   Stylesheet, weil CSS den Text der Kopfzeile nicht in die Zellen
   kopieren kann und der Seiteninhalt nicht angefasst werden soll.
   Ändert sich die Reihenfolge oder Zahl der Spalten in der Tabelle,
   müssen die vier content-Angaben hier mitgeändert werden. Die
   Tabelle ist handgeschrieben (Elementor-Textfeld 24806a3a), kommt
   also nicht aus einem Plugin und ändert sich nicht von allein.

   Eingegrenzt auf .page-id-541: Die Datenschutzerklärung hat eine
   eigene Tabelle mit zwei Spalten und anderen Beschriftungen. Sie ist
   bei 375px unauffällig (Spalten 168px) und bleibt unberührt.

   Die Zellen gehen hier zurück auf hyphens: manual — als Karte sind
   sie 280px breit statt 68px, die Trennung aus Regel 1 wird nicht
   mehr gebraucht.
   ------------------------------------------------------------------ */

@media (max-width: 767px) {
	.page-id-541 .entry-content table,
	.page-id-541 .entry-content tbody,
	.page-id-541 .entry-content tr,
	.page-id-541 .entry-content td {
		display: block;
		width: auto;
	}

	/* Die Kopfzeile wird zur Beschriftung in jeder Karte, siehe unten. */
	.page-id-541 .entry-content tbody tr:first-child {
		display: none;
	}

	.page-id-541 .entry-content tbody tr {
		padding: 0 0 16px;
		margin: 0 0 16px;
		border-bottom: 1px solid rgba(0, 0, 0, 0.42);
	}

	.page-id-541 .entry-content tbody tr:last-child {
		margin-bottom: 0;
		border-bottom: 0;
	}

	.page-id-541 .entry-content td {
		padding: 0;
		border: 0;
		-webkit-hyphens: manual;
		hyphens: manual;
	}

	.page-id-541 .entry-content td + td {
		margin-top: 12px;
	}

	/* Beschriftung: dieselbe Farbe wie „Geeignet für:" auf
	   /leistungen/ (#5E6A86, 5,41:1 auf Weiß). */
	.page-id-541 .entry-content td::before {
		display: block;
		margin-bottom: 2px;
		font-size: 13.6px;
		font-weight: 600;
		line-height: 1.4;
		color: #5E6A86;
	}

	.page-id-541 .entry-content td:nth-child(1)::before { content: "Name"; }
	.page-id-541 .entry-content td:nth-child(2)::before { content: "Art"; }
	.page-id-541 .entry-content td:nth-child(3)::before { content: "Zweck"; }
	.page-id-541 .entry-content td:nth-child(4)::before { content: "Laufzeit"; }
}


/* ------------------------------------------------------------------
   3 · Antippbare Flächen auf 44px bringen

   Gemessen bei 375px, Höhe der echten Trefferfläche:

     Mobilmenü-Links            30px, Abstand 4px
     „Mehr erfahren" (5×, /)    26px
     „Mehr über …" (/leistungen/) 30px
     Fußzeilenlinks             19–21px

   Bei „Mehr erfahren" ist die Fläche wirklich nur 26px hoch: Die
   Kachel darum ist kein Link, es gibt auch keinen aufgespannten
   Stretched-Link — nachgesehen im Markup, das <a> trägt die Klasse
   .textlink-blue und endet mit dem Pfeilbild.

   Vergrößert wird über min-height und padding, nie über height: Der
   Text soll an seiner Stelle bleiben und nur mehr Fläche um sich
   bekommen. align-items: center hält ihn dabei mittig.

   Nur bis 767px: Oberhalb davon wird mit der Maus gezielt, dort ist
   die Vergrößerung unnötig und würde die Abstände der Kacheln
   verschieben. Die Desktop-Ansicht bleibt damit unangetastet.

   HINWEIS ZUM MOBILMENÜ, nicht behoben: header.css bringt für das
   Mobilmenü bereits eine eigene Gestaltung mit —
   .primary-nav__list--mobile a mit padding: 1rem 0.5rem und
   font-size: clamp(1.5rem, 6vw, 2rem). Sie greift nie, weil
   .primary-nav__list > li > a (drei Stellen Spezifität gegen zwei)
   gewinnt. Deshalb stehen dort 15px Schrift und 6px Innenabstand
   statt der vorgesehenen großen Schrift. Hier wird nur die
   Trefferfläche auf 44px gebracht; die vorgesehene Gestaltung
   wiederherzustellen wäre eine sichtbare Änderung des Menüs und
   gehört Ronny vorgelegt, nicht nebenbei erledigt.
   ------------------------------------------------------------------ */

@media (max-width: 767px) {

	/* Mobilmenü: 30px → 44px, Abstand 4px → 8px.
	   .mobile-menu davor, um gegen .primary-nav__list > li > a aus
	   header.css zu gewinnen. */
	.mobile-menu .primary-nav__list--mobile {
		row-gap: 8px;
	}

	.mobile-menu .primary-nav__list--mobile > li > a {
		min-height: 44px;
		padding-top: 8px;
		padding-bottom: 8px;
	}

	/* „Mehr erfahren" auf der Startseite, fünfmal. Das <a> ist schon
	   ein Flexkasten, es fehlt nur die Höhe. */
	.elementor .textlink-blue {
		min-height: 44px;
		align-items: center;
	}

	/* „Mehr über …" auf /leistungen/. inline-block kennt kein
	   align-items, deshalb auf inline-flex; die Zeile bricht dort
	   genauso um wie vorher (zwei der fünf Links sind zweizeilig). */
	.leistung__link {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
	}

	/* Fußzeile. Der Abstand von 11,5px zwischen den Zeilen reicht und
	   bleibt, nur die Zeilen selbst werden höher. */
	.site-footer .footer-nav__list a {
		min-height: 44px;
		align-items: center;
	}
}


/* ------------------------------------------------------------------
   4 · Überschriften trennen auf dem Handy auch nicht mehr

   Regel 1 dieses Abschnitts hat die Überschriften bewusst auf auto stehen
   lassen, weil ihre Mindestbreite sonst nicht mehr schrumpft und vier
   Seiten bei 320px überlaufen. Der Preis war sichtbar: Auf
   /leistungen/dtf-druck/ stand „hochwertige Drucke für Klei-dung und
   Arbeitskleidung" — ein kurzes Wort mitten entzweigeschnitten,
   obwohl der Platz gereicht hätte.

   overflow-wrap: anywhere löst beides zugleich. Anders als
   break-word senkt „anywhere" auch die min-content-Breite (genau der
   Unterschied, der weiter oben schon bei den Unterstrichzeilen des
   Widerrufsformulars den Ausschlag gab). Damit passt sich die
   Überschrift der Spalte an, ohne dass die automatische Trennung
   dafür herhalten muss — und ein Wort wird nur dann überhaupt
   umgebrochen, wenn es allein nicht in die Zeile passt. „Kleidung"
   passt, „Maßgeschneiderte" bei 320px nicht.

   Der Unterschied zum vorherigen Stand, alle 13 Seiten:

     bei 320px   56 → 33 Brüche, Überlauf bleibt überall 0
     bei 375px   40 → 19 Brüche, Überlauf bleibt überall 0

   Die DTF-Unterüberschrift steht danach als „hochwertige Drucke für /
   Kleidung und Arbeitskleidung" — zwei Zeilen, keine Trennung.

   Was bei einem zu langen Wort bleibt, ist ein Umbruch ohne
   Trennstrich („Maßgeschneidert|e"). Das betrifft bei 375px genau
   eine Stelle auf der ganzen Website und bei 320px drei; ein
   fehlender Trennstrich ist dort das kleinere Übel gegenüber einer
   Seite, die sich zur Seite schieben lässt.

   NUR BIS 767px: overflow-wrap: anywhere verändert die
   min-content-Breite und damit die Breite, die eine Kachel in einem
   Raster mindestens beansprucht. Auf dem Handy stehen die Kacheln
   einspaltig, dort ist das folgenlos — nachgemessen bei 375px, die
   fünf Kacheln der Startseite bleiben auf 44px Linkhöhe und
   unveränderter Kachelhöhe. Oberhalb von 767px bleibt alles beim
   Alten: Überschriften behalten dort hyphens: auto und
   overflow-wrap: break-word aus Regel 6.
   ------------------------------------------------------------------ */

@media (max-width: 767px) {
	.entry-content h1,
	.entry-content h2,
	.entry-content h3,
	.entry-content h4,
	.entry-content .elementor-heading-title,
	.entry-title,
	.site-main h1,
	.site-main h2,
	.site-main h3,
	.site-main h4,
	.elementor h1,
	.elementor h2,
	.elementor h3,
	.elementor h4,
	.elementor .elementor-heading-title,
	.leistung__text h2 {
		-webkit-hyphens: manual;
		hyphens: manual;
		overflow-wrap: anywhere;
	}
}

/* ------------------------------------------------------------------
   Fußbereich: Logo linksbündig zum Text darunter
   Die Logodatei druckio-logo-randlos.png (268 × 95 px) trägt links
   einen eingebrannten Rand: Der Schriftzug „DRUCKIO“ beginnt erst in
   Bildspalte 22, davor liegt nur das blasse Ende des blauen Schwungs.
   Dadurch stand das Logo optisch 22 px weiter rechts als die Zeile
   „Your Brand. Our Mission.“ und der Beschreibungstext darunter,
   obwohl beide Kästen exakt dieselbe linke Kante haben (gemessen:
   142,5 px bei 1440 px Fensterbreite).

   22 von 268 Bildpunkten sind 8,209 % der Bildbreite. Prozentwerte in
   translateX beziehen sich auf die eigene Breite des Elements, deshalb
   wandert die Verschiebung mit, sobald das Bild schrumpft: Bei 768 px
   Fensterbreite ist das Logo nur noch 217 px breit und braucht 17,8 px
   statt 22 px. Ein fester Pixelwert würde dort um 4 px überkorrigieren.

   transform statt margin-left: Ein negativer margin-left verkleinert
   den Platz im Flex-Kasten, worauf max-width: 100 % greift und das
   Logo auf 246 px zusammenstaucht (gemessen). transform verändert das
   Layout nicht und lässt die Bildgröße unberührt.

   Der blaue Schwung ragt danach links über die Textkante hinaus. Auf
   dem Handy läuft sein blassestes Ende aus dem Bild – das erzeugt
   keinen waagerechten Überlauf, weil Browser in Leserichtung nach
   links nichts scrollbar machen (gemessen: 0 px bei 320 px).
   Wirkt bei allen Fensterbreiten.
   ------------------------------------------------------------------ */
.site-footer .site-footer__brand .site-branding .custom-logo {
	transform: translateX(-8.209%);
}

/* ------------------------------------------------------------------
   Kopf-Logo auf dieselbe Kante wie der Inhalt darunter

   Dieselbe Ursache wie im Fußbereich: In druckio-logo-randlos.png
   (268 × 95 px) beginnt der Schriftzug erst in Bildspalte 22, davor
   liegt nur das blasse, auslaufende Ende des blauen Schwungs. Der
   Browser richtet den Bildrand aus, das Auge den Schriftzug – daher
   22 px Versatz. 22/268 = 8,209 %.

   Gemessen bei 1440 px auf der Startseite, vor der Korrektur:
     Kasten des Kopf-Logos       142,50 px
     Schriftzug „DRUCKIO"        164,50 px
     Hero-Überschrift darunter   142,50 px

   Prozent statt Pixel, damit der Ausgleich mitwandert, wenn das Logo
   in schmalen Fenstern kleiner skaliert wird. transform statt
   margin-left, weil ein negativer Rand den Platz im Flex-Kasten
   verkleinert und max-width: 100 % das Logo stauchen würde.

   Auf Ronnys Entscheidung vom 07.08.2026, nachdem dieselbe Korrektur
   im Fußbereich stand. Beide Logos folgen jetzt derselben Regel.
   ------------------------------------------------------------------ */
.site-header .site-branding .custom-logo {
	transform: translateX(-8.209%);
}

/* ------------------------------------------------------------------
   Zeilenabstand der Kachelreihen in der Handyansicht

   Elementor gibt diesen Reihen nur einen waagerechten Abstand mit
   (--gap: 0px 24px). Solange die Karten nebeneinander stehen, fällt das
   nicht auf. Unter 768 px stapeln sie sich – und kleben aneinander.

   Gemessen am 07.08.2026 bei 375 px auf der Startseite:
     .card-white-16px   Abstände 0 / 0 / 1 px
     .service-card      Abstände 0 / 0 / 23 / 0 px
   Zum Vergleich die beiden Rasterreihen derselben Seite, die es richtig
   machen: .g-901e541 und .target-group-card, je 20 px.

   Für 768–1155 px steht weiter oben bereits eine Regel mit row-gap: 24px
   (Abschnitt „Vier Vorteilskacheln"). Sie endet bei 767,98 px – genau
   dort setzt diese hier an. 20 px statt 24, damit es zu den beiden
   Rasterreihen passt, die auf derselben Seite darunter folgen.
   ------------------------------------------------------------------ */

@media (max-width: 767.98px) {
	.elementor .e-con.e-flex > .e-con-inner:has(> .card-white-16px),
	.elementor .e-con.e-flex > .e-con-inner:has(> .service-card) {
		row-gap: 20px;
	}
}

/* ------------------------------------------------------------------
   Kopfbereich in der Handyansicht: Menü links, Logo mittig

   Auf Ronnys Wunsch vom 07.08.2026. Vorher: Logo links, blauer runder
   Knopf rechts. Jetzt: drei weiße Striche links ohne Fläche, Logo in
   der Mitte.

   Der Knopf wird aus dem Textfluss genommen (position: absolute) und
   links angeheftet. Nur so steht das Logo wirklich in der Fenstermitte
   und nicht in der Mitte des Restplatzes daneben. Der Kopfstreifen
   bekommt dafür position: relative als Bezugspunkt.

   Das Logo trägt im Desktop-Zustand translateX(-8.209%), weil sein
   Schriftzug erst in Bildspalte 22 von 268 beginnt und sonst gegenüber
   dem Text darunter eingerückt wirkt. Beim Zentrieren gilt das nicht
   mehr: Dort zählt die Mitte zwischen den sichtbaren Kanten. Gemessen
   sind es links 22 und rechts 25 Randspalten – die Schrift sitzt also
   1,5 px zu weit links im Bild. Genau das gleicht die Regel aus.

   max-width begrenzt das Logo, damit es bei 320 px nicht unter den
   Knopf läuft: 44 px Knopf + 16 px Luft auf beiden Seiten.
   ------------------------------------------------------------------ */

@media (max-width: 767.98px) {
	.site-header .site-header__inner {
		position: relative;
		justify-content: center;
	}

	/* Das Logo wird absolut in die Fenstermitte gesetzt – wie der Knopf.

	   Warum nicht einfach margin-inline: auto? Der Kopfstreifen steht auf
	   justify-content: space-between, und eine Regel dagegen wird von
	   Elementor überschrieben. Dazu kommt ein zweites, 0 px breites
	   Element (.site-header__end) am rechten Rand: Mit space-between
	   verteilen sich die automatischen Ränder dadurch auf drei Stellen
	   statt zwei – gemessen 47 px links, 47 rechts, 47 vor dem leeren
	   Element. Das Logo landete 35,5 px zu weit links.

	   Absolut positioniert ist es von der Flex-Verteilung unabhängig.
	   min-height am Streifen ersetzt die Höhe, die das Logo im Fluss
	   beigetragen hat. */
	.site-header .site-header__inner {
		min-height: 68px;
	}

	.site-header .site-branding {
		position: absolute;
		left: 50%;
		top: 50%;
		/* −50 % zentriert den Bildkasten. Der Schriftzug sitzt darin aber
		   nicht mittig: links 22, rechts 25 Randspalten – also 1,5 px zu
		   weit links. Deshalb 1,5 px nach rechts, damit die sichtbare
		   Schrift mittig steht und nicht die Bilddatei. */
		transform: translate(calc(-50% + 1.5px), -50%);
		margin-inline: 0;
		max-width: min(190px, calc(100% - 120px));
	}

	.site-header .site-branding .custom-logo {
		transform: none;
		max-width: 100%;
		height: auto;
	}

	.site-header .menu-toggle {
		position: absolute;
		left: 0;
		top: 50%;
		transform: translateY(-50%);
		background: none;
		border: 0;
		border-radius: 0;
		box-shadow: none;
		width: 44px;
		height: 44px;
		padding: 10px 8px;
		display: flex;
		flex-direction: column;
		justify-content: space-between;
	}

	.site-header .menu-toggle:hover,
	.site-header .menu-toggle:focus-visible {
		background: none;
	}

	/* Drei weiße Striche, gleich lang und gleichmäßig verteilt. */
	.site-header .menu-toggle .menu-toggle__bar {
		background-color: #FFFFFF;
		width: 100%;
		height: 2px;
		border-radius: 1px;
	}

	/* Der Fokusrahmen darf nicht mit verschwinden – ohne Fläche ist er
	   der einzige Hinweis für Tastaturnutzer, wo sie gerade stehen. */
	.site-header .menu-toggle:focus-visible {
		outline: 2px solid #FFFFFF;
		outline-offset: 4px;
	}
}

/* ------------------------------------------------------------------
   Fußbereich in der Handyansicht: mittig, Links nebeneinander

   Auf Ronnys Wunsch vom 07.08.2026. Vorher standen Überschrift und
   Einträge linksbündig untereinander – bei sechs bzw. sieben Einträgen
   je Spalte wurde der Fuß dadurch über 800 px hoch.

   Jetzt steht die Überschrift mittig, die Einträge darunter in einer
   zentrierten Zeile mit Mittelpunkt als Trenner. Sie brechen um, wenn
   der Platz nicht reicht.

   Die Trefferfläche bleibt bei 44 px: Das Polster sorgt dafür, dass
   sich die Links sicher antippen lassen, auch wenn sie enger stehen.
   Der Trenner ist aria-hidden über content: "" nicht nötig – ::after
   erzeugt kein Element im Zugänglichkeitsbaum, Screenreader lesen ihn
   nicht mit.
   ------------------------------------------------------------------ */

@media (max-width: 767.98px) {
	.site-footer .site-footer__col,
	.site-footer .site-footer__col--contact,
	.site-footer .footer-col__title {
		text-align: center;
	}

	.site-footer .site-footer__col > ul,
	.site-footer .footer-nav__list {
		flex-direction: row;
		flex-wrap: wrap;
		justify-content: center;
		align-items: center;
		column-gap: 0;
		row-gap: 2px;
	}

	.site-footer .site-footer__col > ul > li,
	.site-footer .footer-nav__list > li {
		display: flex;
		align-items: center;
	}

	/* Kein Trennzeichen, sondern Abstand.

	   Ein ::after-Mittelpunkt sitzt bei umbrechenden Zeilen auch am
	   Zeilenende und zeigt dort ins Leere – im Bildschirmfoto gut zu
	   sehen. Welches Element das letzte einer Zeile ist, weiß CSS nicht,
	   deshalb lässt sich das nicht wegregeln. Abstand trennt genauso
	   deutlich und bricht sauber um. */
	.site-footer .site-footer__col > ul,
	.site-footer .footer-nav__list {
		column-gap: 22px;
	}

	/* Trefferfläche halten – ohne das Polster wären die Links 19 px hoch. */
	.site-footer .site-footer__col > ul > li > a,
	.site-footer .footer-nav__list > li > a {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
		padding-block: 2px;
	}

	/* Die Kontaktspalte hat keine Liste, nur Zeilen – die bekommen
	   dasselbe Polster, damit Telefon und E-Mail antippbar bleiben. */
	.site-footer .site-footer__col--contact a {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
	}
}

/* ------------------------------------------------------------------
   Fuß-Logo und Markenblock in der Handyansicht mittig

   Ergänzung zum Abschnitt darüber: Die drei Spalten stehen jetzt
   mittig, der Markenblock mit Logo und Schlagzeile stand noch links.

   Gemessen bei 375 px: Logomitte 122 px statt 187,5.

   Für den Desktop gilt weiter translateX(-8.209%) – dort steht das Logo
   linksbündig über dem Text, und der unsichtbare Rand der Bilddatei muss
   ausgeglichen werden. Beim Zentrieren zählt dagegen die Mitte zwischen
   den sichtbaren Kanten: links 22, rechts 25 Randspalten, der Schriftzug
   sitzt also 1,5 px zu weit links im Bild.
   ------------------------------------------------------------------ */

@media (max-width: 767.98px) {
	.site-footer .site-footer__brand {
		text-align: center;
	}

	/* .site-branding ist ein Flex-Container. text-align wirkt dort nicht
	   auf die Kinder – gemessen: Logo blieb bei 12 px, obwohl der Kasten
	   352 px breit ist. justify-content ist der richtige Hebel. */
	.site-footer .site-footer__brand .site-branding {
		justify-content: center;
		text-align: center;
	}

	.site-footer .site-footer__brand .site-branding .custom-logo {
		display: block;
		margin-inline: auto;
		transform: translateX(1.5px);
	}

	/* Copyright-Zeile und Schlagzeile mitziehen. */
	.site-footer .site-footer__brand p,
	.site-footer .site-footer__tagline,
	.site-footer .site-footer__copy {
		text-align: center;
	}
}

/* Schlagzeile, Trennlinien und Copyright im Fuß mittig ziehen. */
@media (max-width: 767.98px) {
	.site-footer .site-footer__brand *,
	.site-footer .site-footer__tagline,
	.site-footer .site-footer__claim,
	.site-footer .site-footer__bottom,
	.site-footer .site-footer__bottom * {
		text-align: center;
	}

	/* Die Trennlinien liefen nur über die Breite des Markenblocks. */
	.site-footer hr,
	.site-footer .site-footer__brand hr,
	.site-footer [class*="divider"] {
		width: 100%;
		margin-inline: auto;
	}
}

/* Schlagzeile „Your Brand. Our Mission." mittig, Linien über volle Breite.

   .site-footer__tagline ist ein Flexkasten mit justify-content: normal
   und nur 256 px breit – gemessen bei 375 px Fenster. Deshalb stand der
   Text links, und die Linien darüber und darunter (Rahmen des Kastens,
   keine hr-Elemente) endeten mitten im Fuß. */
@media (max-width: 767.98px) {
	.site-footer .site-footer__tagline {
		/* Der Kasten steht auf flex-direction: column. Bei senkrechter
		   Richtung wirkt justify-content auf die Hochachse – waagerecht
		   zentriert align-items. Dazu bringt das Theme max-width: 256px
		   mit; deshalb endeten die Linien darüber und darunter mitten
		   im Fuß (gemessen: Kasten 256 px in einem 355 px breiten
		   Elternteil). */
		align-items: center;
		max-width: none;
		width: 100%;
	}

	.site-footer .site-footer__tagline-text {
		text-align: center;
	}
}

/* Ausgewogener Zeilenumbruch im Fuß.

   Der Beschreibungstext ist zentriert (gemessen: beide Zeilen bei Mitte
   186 gegen Fenstermitte 187,5), wirkte aber schief: Die erste Zeile lief
   von 22 bis 350 px, die zweite nur von 50 bis 322. Ein zentrierter Block
   mit stark ungleichen Zeilen sieht aus wie ein linksbündiger.

   text-wrap: balance verteilt die Wörter gleichmäßig auf die Zeilen.
   Ältere Browser ignorieren die Angabe – dann bleibt es beim bisherigen
   Umbruch, nichts geht kaputt. */
@media (max-width: 767.98px) {
	.site-footer .site-footer__description,
	.site-footer .site-footer__tagline-text,
	.site-footer .footer-col__title {
		text-wrap: balance;
	}
}

/* Zentrierte Kästen im Fuß brauchen einen automatischen Rand.

   Gefunden, weil Ronny den Text als „nicht mittig" gemeldet hat, während
   meine Messung bei 375 px nur 7,5 px Abweichung zeigte. Bei breiteren
   Handys wird daraus viel mehr — der Kasten hat max-width: 352px und ohne
   margin auto klebt er links fest:

     375 px Fenster → 7,5 px daneben
     414 px Fenster → 21 px
     430 px Fenster → 29 px   (iPhone Pro Max)
     767 px Fenster → 197,5 px

   text-align: center zentriert nur den Text INNERHALB des Kastens, nicht
   den Kasten selbst. Genau das war die Falle.

   Lehre für die nächste Messung: nicht bei einer Breite prüfen, sondern
   über die ganze Spanne — der Fehler wächst mit dem Fenster. */
@media (max-width: 767.98px) {
	.site-footer .site-footer__description,
	.site-footer .site-footer__tagline,
	.site-footer .site-footer__tagline-text,
	.site-footer .site-footer__col,
	.site-footer .footer-col__title {
		margin-inline: auto;
	}
}

/* Vorspann „So einfach funktioniert es" linksbündig wie die anderen

   Auf der Startseite tragen fünf Abschnitte einen Vorspann mit blauem
   Strich davor. Vier davon stehen linksbündig, einer nicht: Sein
   Elementor-Container 79117d8 hat justify-content: center bekommen,
   die anderen stehen auf normal bzw. flex-start.

   Gemessen bei 375 px, Abstand vom linken Rand des Containers:
     Unsere Leistungen      36 px
     Für wen wir arbeiten   36 px
     So einfach …           73 px   ← fällt heraus
     Anwendungsbeispiele    36 px
     Jetzt starten          36 px

   Über CSS statt in den Seitendaten, weil die Einstellung sonst beim
   nächsten Bearbeiten in Elementor wieder gesetzt werden kann. Gilt bei
   allen Fensterbreiten – die Abweichung besteht auch am Bildschirm.
   ------------------------------------------------------------------ */

.elementor .elementor-element-79117d8 {
	justify-content: flex-start;
}

/* ------------------------------------------------------------------
   Einheitlicher Seitenrand in der Tablet-Ansicht (768–1024 px)

   Auf Ronnys Hinweis vom 07.08.2026: Die Abstände zum Rand passten
   nicht zueinander. Gemessen bei 819 px auf der Startseite – zehn
   Sektionen, vier verschiedene Ränder:

     Hero                                     0 px
     Alles aus einer Hand · Vielfältige
     Verfahren · In vier Schritten ·
     Typische Aufgaben                       32 px
     Textildruck · Lasergravur ·
     Maßgeschneiderte Lösungen ·
     Anfrage senden                          42 px
     Trikotsatz                              52 px (+10 px Sektionspolster)

   Das ist gewachsen, nicht entworfen: Jede Sektion wurde einzeln in
   Elementor gebaut, und die Voreinstellung für die Innenbreite hat sich
   unterwegs geändert.

   40 px ist der Mittelwert zwischen den beiden häufigsten Werten und
   ergibt bei 768 px Fenster 688 px Inhaltsbreite – genug für zwei
   Kacheln nebeneinander.

   Der Hero (2e2357a) bleibt ausgenommen: Er trägt ein randloses
   Hintergrundbild, dort ist 0 px richtig. Sein Text hat einen eigenen
   Innenabstand. Die Kennung ist auf allen sechs Seiten dieselbe.
   ------------------------------------------------------------------ */

@media (min-width: 768px) and (max-width: 1024.98px) {
	.elementor .e-con.e-parent:not(.elementor-element-2e2357a) > .e-con-inner {
		max-width: 100%;
		width: 100%;
		padding-inline: 40px;
	}

	/* Eine Sektion bringt zusätzlich 10 px am Rahmen mit – sonst käme
	   sie auf 50 px. */
	.elementor .e-con.e-parent:not(.elementor-element-2e2357a) {
		padding-inline: 0;
	}
}

/* Abschnitt „In vier Schritten zum fertigen Produkt" linksbündig

   Ergänzung zur Regel für den Vorspann weiter oben. Der Vorspann sitzt
   jetzt richtig, die Überschrift stand aber weiter eingerückt: Der
   innere Container der Sektion 55ded8e trägt align-items: center,
   alle vergleichbaren Abschnitte stehen auf normal.

   Gemessen bei 819 px, linke Kante der Überschrift:
     Vielfältige Verfahren        72 px
     Typische Aufgaben            72 px
     In vier Schritten            79 px   ← fällt heraus

   align-items steuert bei flex-direction: column die Querachse, also
   die waagerechte Ausrichtung. Deshalb wirkt es hier wie eine
   Zentrierung, obwohl text-align auf start steht.
   ------------------------------------------------------------------ */

.elementor .elementor-element-55ded8e > .e-con-inner {
	align-items: flex-start;
}

/* ------------------------------------------------------------------
   Fokusrahmen für Elementors neue Bausteine

   Befund der Barrierefreiheitsprüfung vom 07.08.2026: Auf der Startseite
   verlieren zehn Links ihren Fokusrahmen — fünf Bildlinks und fünf
   Überschriftenlinks im Abschnitt „Typische Aufgaben".

   Ursache: Elementor liefert für seine neue Baustein-Generation
   .e-image-link-base { all: unset } und .e-heading-link-base { all: unset }.
   „all: unset" setzt JEDE Eigenschaft zurück, auch den Fokusrahmen. Die
   Theme-Regel a:focus-visible hat die Spezifität (0,1,1), Elementors Regel
   (0,2,0) — Elementor gewinnt.

   Wer mit der Tastatur navigiert, tabbt dort zehnmal ins Blinde und weiß
   nicht, wohin die Eingabetaste führt. WCAG 2.4.7, Stufe AA.

   .e-paragraph-link-base trägt dasselbe all: unset und wird derzeit
   nirgends benutzt — die Regel deckt es mit ab, damit es nicht später
   auffällt.
   ------------------------------------------------------------------ */

.elementor a[class*="-link-base"]:focus-visible {
	outline: 2px solid #2B6CEE;
	outline-offset: 3px;
	border-radius: 2px;
}

/* Auf dunklem Grund weiß, sonst geht der Rahmen unter. */
.elementor .bg-dark a[class*="-link-base"]:focus-visible,
.site-footer a[class*="-link-base"]:focus-visible {
	outline-color: #FFFFFF;
}

/* Die Zwischenebene im Tablet-Bereich entpolstern

   Nachtrag zur Regel „Einheitlicher Seitenrand" weiter oben. Sie hat den
   52-px-Ausreißer eingefangen, aber 32 gegen 42 px blieben.

   Der Grund war nicht der Innenabstand, sondern die Verschachtelung:
   Zwischen der äußeren Sektion und dem Inhalt liegt eine weitere
   Container-Ebene, die 10 px Polster mitbringt. Gemessen bei 819 px –
   fünfmal auf der Startseite, jedes Mal 755 px breit bei linker Kante 32:

     f6eb77d · 5620edb · 569907e · 5adbef0 · d7a5754

   32 + 10 = 42. Genau die Differenz, die aufgefallen war.

   Der Selektor greift nur die erste Verschachtelungsebene
   (Sektion → e-con-inner → Container). Die Kacheln selbst sitzen tiefer
   und behalten ihr Polster – sonst klebte der Text an der Kartenkante.
   ------------------------------------------------------------------ */

@media (min-width: 768px) and (max-width: 1024.98px) {
	.elementor .e-con.e-parent > .e-con-inner > .e-con {
		padding-inline: 0;
	}
}

/* Zwei Sektionen sitzen eine Ebene tiefer — Ausgleich

   Letzter Rest des Tablet-Randes. Die Sektionen be3aca6
   („Maßgeschneiderte Lösungen") und d32f6ea („Anfrage senden") stehen
   nicht direkt im Seitenraster, sondern in einem Wrapper mit 10 px
   Polster. Sie beginnen deshalb bei 42 statt 32 px, ihr Inhalt bei 82
   statt 72.

   Der Wrapper trägt keine Elementor-Kennung und lässt sich nicht sicher
   ansprechen, ohne andere Seiten zu treffen. Deshalb hier der Ausgleich
   an den zwei Sektionen selbst: 30 statt 40 px Innenabstand, damit der
   Text auf denselben 72 px landet wie überall sonst.

   Wenn diese Sektionen in Elementor je umgebaut werden, kann die Regel
   weg — dann sitzen sie wie die anderen.
   ------------------------------------------------------------------ */

@media (min-width: 768px) and (max-width: 1024.98px) {
	/* Die Regel „Einheitlicher Seitenrand" oben nutzt :not(), und der
	   Inhalt einer :not()-Klammer zählt bei der Spezifität mit. Sie wiegt
	   damit vier Klassen, dieser Ausgleich zunächst nur drei – und verlor.
	   Mit .e-con.e-parent im Selektor wiegen beide gleich schwer, und die
	   spätere Regel gewinnt. */
	.elementor .e-con.e-parent.elementor-element-be3aca6 > .e-con-inner,
	.elementor .e-con.e-parent.elementor-element-d32f6ea > .e-con-inner {
		padding-inline: 30px;
	}
}
